diff --git a/build/three.js b/build/three.js index 09a2ab511d711a..11c38a4471bc3c 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 = '127'; + const REVISION = '128'; const MOUSE = { LEFT: 0, MIDDLE: 1, @@ -219,10 +219,8 @@ /** * https://github.com/mrdoob/eventdispatcher.js/ */ - function EventDispatcher() {} - - Object.assign(EventDispatcher.prototype, { - addEventListener: function (type, listener) { + class EventDispatcher { + addEventListener(type, listener) { if (this._listeners === undefined) this._listeners = {}; const listeners = this._listeners; @@ -233,13 +231,15 @@ if (listeners[type].indexOf(listener) === -1) { listeners[type].push(listener); } - }, - hasEventListener: function (type, listener) { + } + + hasEventListener(type, listener) { if (this._listeners === undefined) return false; const listeners = this._listeners; return listeners[type] !== undefined && listeners[type].indexOf(listener) !== -1; - }, - removeEventListener: function (type, listener) { + } + + removeEventListener(type, listener) { if (this._listeners === undefined) return; const listeners = this._listeners; const listenerArray = listeners[type]; @@ -251,8 +251,9 @@ listenerArray.splice(index, 1); } } - }, - dispatchEvent: function (event) { + } + + dispatchEvent(event) { if (this._listeners === undefined) return; const listeners = this._listeners; const listenerArray = listeners[event.type]; @@ -269,7 +270,8 @@ event.target = null; } } - }); + + } const _lut = []; @@ -278,144 +280,187 @@ } let _seed = 1234567; - const MathUtils = { - DEG2RAD: Math.PI / 180, - RAD2DEG: 180 / Math.PI, - generateUUID: function () { - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 - const d0 = Math.random() * 0xffffffff | 0; - const d1 = Math.random() * 0xffffffff | 0; - const d2 = Math.random() * 0xffffffff | 0; - const d3 = Math.random() * 0xffffffff | 0; - const uuid = _lut[d0 & 0xff] + _lut[d0 >> 8 & 0xff] + _lut[d0 >> 16 & 0xff] + _lut[d0 >> 24 & 0xff] + '-' + _lut[d1 & 0xff] + _lut[d1 >> 8 & 0xff] + '-' + _lut[d1 >> 16 & 0x0f | 0x40] + _lut[d1 >> 24 & 0xff] + '-' + _lut[d2 & 0x3f | 0x80] + _lut[d2 >> 8 & 0xff] + '-' + _lut[d2 >> 16 & 0xff] + _lut[d2 >> 24 & 0xff] + _lut[d3 & 0xff] + _lut[d3 >> 8 & 0xff] + _lut[d3 >> 16 & 0xff] + _lut[d3 >> 24 & 0xff]; // .toUpperCase() here flattens concatenated strings to save heap memory space. - - return uuid.toUpperCase(); - }, - clamp: function (value, min, max) { - return Math.max(min, Math.min(max, value)); - }, - // compute euclidian modulo of m % n - // https://en.wikipedia.org/wiki/Modulo_operation - euclideanModulo: function (n, m) { - return (n % m + m) % m; - }, - // Linear mapping from range to range - mapLinear: function (x, a1, a2, b1, b2) { - return b1 + (x - a1) * (b2 - b1) / (a2 - a1); - }, - // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ - inverseLerp: function (x, y, value) { - if (x !== y) { - return (value - x) / (y - x); - } else { - return 0; - } - }, - // https://en.wikipedia.org/wiki/Linear_interpolation - lerp: function (x, y, t) { - return (1 - t) * x + t * y; - }, - // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ - damp: function (x, y, lambda, dt) { - return MathUtils.lerp(x, y, 1 - Math.exp(-lambda * dt)); - }, - // https://www.desmos.com/calculator/vcsjnyz7x4 - pingpong: function (x, length = 1) { - return length - Math.abs(MathUtils.euclideanModulo(x, length * 2) - length); - }, - // http://en.wikipedia.org/wiki/Smoothstep - smoothstep: function (x, min, max) { - if (x <= min) return 0; - if (x >= max) return 1; - x = (x - min) / (max - min); - return x * x * (3 - 2 * x); - }, - smootherstep: function (x, min, max) { - if (x <= min) return 0; - if (x >= max) return 1; - x = (x - min) / (max - min); - return x * x * x * (x * (x * 6 - 15) + 10); - }, - // Random integer from interval - randInt: function (low, high) { - return low + Math.floor(Math.random() * (high - low + 1)); - }, - // Random float from interval - randFloat: function (low, high) { - return low + Math.random() * (high - low); - }, - // Random float from <-range/2, range/2> interval - randFloatSpread: function (range) { - return range * (0.5 - Math.random()); - }, - // Deterministic pseudo-random float in the interval [ 0, 1 ] - seededRandom: function (s) { - if (s !== undefined) _seed = s % 2147483647; // Park-Miller algorithm + const DEG2RAD = Math.PI / 180; + const RAD2DEG = 180 / Math.PI; // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 - _seed = _seed * 16807 % 2147483647; - return (_seed - 1) / 2147483646; - }, - degToRad: function (degrees) { - return degrees * MathUtils.DEG2RAD; - }, - radToDeg: function (radians) { - return radians * MathUtils.RAD2DEG; - }, - isPowerOfTwo: function (value) { - return (value & value - 1) === 0 && value !== 0; - }, - ceilPowerOfTwo: function (value) { - return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2)); - }, - floorPowerOfTwo: function (value) { - return Math.pow(2, Math.floor(Math.log(value) / Math.LN2)); - }, - setQuaternionFromProperEuler: function (q, a, b, c, order) { - // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles - // rotations are applied to the axes in the order specified by 'order' - // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' - // angles are in radians - const cos = Math.cos; - const sin = Math.sin; - const c2 = cos(b / 2); - const s2 = sin(b / 2); - const c13 = cos((a + c) / 2); - const s13 = sin((a + c) / 2); - const c1_3 = cos((a - c) / 2); - const s1_3 = sin((a - c) / 2); - const c3_1 = cos((c - a) / 2); - const s3_1 = sin((c - a) / 2); + function generateUUID() { + const d0 = Math.random() * 0xffffffff | 0; + const d1 = Math.random() * 0xffffffff | 0; + const d2 = Math.random() * 0xffffffff | 0; + const d3 = Math.random() * 0xffffffff | 0; + const uuid = _lut[d0 & 0xff] + _lut[d0 >> 8 & 0xff] + _lut[d0 >> 16 & 0xff] + _lut[d0 >> 24 & 0xff] + '-' + _lut[d1 & 0xff] + _lut[d1 >> 8 & 0xff] + '-' + _lut[d1 >> 16 & 0x0f | 0x40] + _lut[d1 >> 24 & 0xff] + '-' + _lut[d2 & 0x3f | 0x80] + _lut[d2 >> 8 & 0xff] + '-' + _lut[d2 >> 16 & 0xff] + _lut[d2 >> 24 & 0xff] + _lut[d3 & 0xff] + _lut[d3 >> 8 & 0xff] + _lut[d3 >> 16 & 0xff] + _lut[d3 >> 24 & 0xff]; // .toUpperCase() here flattens concatenated strings to save heap memory space. - switch (order) { - case 'XYX': - q.set(c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13); - break; + return uuid.toUpperCase(); + } - case 'YZY': - q.set(s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13); - break; + function clamp(value, min, max) { + return Math.max(min, Math.min(max, value)); + } // compute euclidian modulo of m % n + // https://en.wikipedia.org/wiki/Modulo_operation - case 'ZXZ': - q.set(s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13); - break; - case 'XZX': - q.set(c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13); - break; + function euclideanModulo(n, m) { + return (n % m + m) % m; + } // Linear mapping from range to range - case 'YXY': - q.set(s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13); - break; - case 'ZYZ': - q.set(s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13); - break; + function mapLinear(x, a1, a2, b1, b2) { + return b1 + (x - a1) * (b2 - b1) / (a2 - a1); + } // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ - default: - console.warn('THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order); - } + + function inverseLerp(x, y, value) { + if (x !== y) { + return (value - x) / (y - x); + } else { + return 0; } - }; + } // https://en.wikipedia.org/wiki/Linear_interpolation + + + function lerp(x, y, t) { + return (1 - t) * x + t * y; + } // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ + + + function damp(x, y, lambda, dt) { + return lerp(x, y, 1 - Math.exp(-lambda * dt)); + } // https://www.desmos.com/calculator/vcsjnyz7x4 + + + function pingpong(x, length = 1) { + return length - Math.abs(euclideanModulo(x, length * 2) - length); + } // http://en.wikipedia.org/wiki/Smoothstep + + + function smoothstep(x, min, max) { + if (x <= min) return 0; + if (x >= max) return 1; + x = (x - min) / (max - min); + return x * x * (3 - 2 * x); + } + + function smootherstep(x, min, max) { + if (x <= min) return 0; + if (x >= max) return 1; + x = (x - min) / (max - min); + return x * x * x * (x * (x * 6 - 15) + 10); + } // Random integer from interval + + + function randInt(low, high) { + return low + Math.floor(Math.random() * (high - low + 1)); + } // Random float from interval + + + function randFloat(low, high) { + return low + Math.random() * (high - low); + } // Random float from <-range/2, range/2> interval + + + function randFloatSpread(range) { + return range * (0.5 - Math.random()); + } // Deterministic pseudo-random float in the interval [ 0, 1 ] + + + function seededRandom(s) { + if (s !== undefined) _seed = s % 2147483647; // Park-Miller algorithm + + _seed = _seed * 16807 % 2147483647; + return (_seed - 1) / 2147483646; + } + + function degToRad(degrees) { + return degrees * DEG2RAD; + } + + function radToDeg(radians) { + return radians * RAD2DEG; + } + + function isPowerOfTwo(value) { + return (value & value - 1) === 0 && value !== 0; + } + + function ceilPowerOfTwo(value) { + return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2)); + } + + function floorPowerOfTwo(value) { + return Math.pow(2, Math.floor(Math.log(value) / Math.LN2)); + } + + function setQuaternionFromProperEuler(q, a, b, c, order) { + // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles + // rotations are applied to the axes in the order specified by 'order' + // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' + // angles are in radians + const cos = Math.cos; + const sin = Math.sin; + const c2 = cos(b / 2); + const s2 = sin(b / 2); + const c13 = cos((a + c) / 2); + const s13 = sin((a + c) / 2); + const c1_3 = cos((a - c) / 2); + const s1_3 = sin((a - c) / 2); + const c3_1 = cos((c - a) / 2); + const s3_1 = sin((c - a) / 2); + + switch (order) { + case 'XYX': + q.set(c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13); + break; + + case 'YZY': + q.set(s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13); + break; + + case 'ZXZ': + q.set(s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13); + break; + + case 'XZX': + q.set(c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13); + break; + + case 'YXY': + q.set(s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13); + break; + + case 'ZYZ': + q.set(s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13); + break; + + default: + console.warn('THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order); + } + } + + var MathUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler + }); class Vector2 { constructor(x = 0, y = 0) { @@ -1029,8 +1074,8 @@ let _canvas; - const ImageUtils = { - getDataURL: function (image) { + class ImageUtils { + static getDataURL(image) { if (/^data:/i.test(image.src)) { return image.src; } @@ -1066,7 +1111,8 @@ return canvas.toDataURL('image/png'); } } - }; + + } let textureId = 0; @@ -1076,7 +1122,7 @@ Object.defineProperty(this, 'id', { value: textureId++ }); - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.name = ''; this.image = image; this.mipmaps = []; @@ -1181,7 +1227,7 @@ const image = this.image; if (image.uuid === undefined) { - image.uuid = MathUtils.generateUUID(); // UGH + image.uuid = generateUUID(); // UGH } if (!isRootObject && meta.images[image.uuid] === undefined) { @@ -2210,7 +2256,7 @@ } angleTo(q) { - return 2 * Math.acos(Math.abs(MathUtils.clamp(this.dot(q), -1, 1))); + return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1))); } rotateTowards(q, step) { @@ -2825,7 +2871,7 @@ if (denominator === 0) return Math.PI / 2; const theta = this.dot(v) / denominator; // clamp, to handle numerical problems - return Math.acos(MathUtils.clamp(theta, -1, 1)); + return Math.acos(clamp(theta, -1, 1)); } distanceTo(v) { @@ -4706,8 +4752,7 @@ } setFromRotationMatrix(m, order, update) { - const clamp = MathUtils.clamp; // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) const te = m.elements; const m11 = te[0], m12 = te[4], @@ -4906,25 +4951,25 @@ let _object3DId = 0; - const _v1$4 = new Vector3(); + const _v1$4 = new /*@__PURE__*/Vector3(); - const _q1 = new Quaternion(); + const _q1 = new /*@__PURE__*/Quaternion(); - const _m1$1 = new Matrix4(); + const _m1$1 = new /*@__PURE__*/Matrix4(); - const _target = new Vector3(); + const _target = new /*@__PURE__*/Vector3(); - const _position$3 = new Vector3(); + const _position$3 = new /*@__PURE__*/Vector3(); - const _scale$2 = new Vector3(); + const _scale$2 = new /*@__PURE__*/Vector3(); - const _quaternion$2 = new Quaternion(); + const _quaternion$2 = new /*@__PURE__*/Quaternion(); - const _xAxis = new Vector3(1, 0, 0); + const _xAxis = new /*@__PURE__*/Vector3(1, 0, 0); - const _yAxis = new Vector3(0, 1, 0); + const _yAxis = new /*@__PURE__*/Vector3(0, 1, 0); - const _zAxis = new Vector3(0, 0, 1); + const _zAxis = new /*@__PURE__*/Vector3(0, 0, 1); const _addedEvent = { type: 'added' @@ -4933,115 +4978,121 @@ type: 'removed' }; - function Object3D() { - Object.defineProperty(this, 'id', { - value: _object3DId++ - }); - this.uuid = MathUtils.generateUUID(); - this.name = ''; - this.type = 'Object3D'; - this.parent = null; - this.children = []; - this.up = Object3D.DefaultUp.clone(); - const position = new Vector3(); - const rotation = new Euler(); - const quaternion = new Quaternion(); - const scale = new Vector3(1, 1, 1); + class Object3D extends EventDispatcher { + constructor() { + super(); + Object.defineProperty(this, 'id', { + value: _object3DId++ + }); + this.uuid = generateUUID(); + this.name = ''; + this.type = 'Object3D'; + this.parent = null; + this.children = []; + this.up = Object3D.DefaultUp.clone(); + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3(1, 1, 1); - function onRotationChange() { - quaternion.setFromEuler(rotation, false); - } + function onRotationChange() { + quaternion.setFromEuler(rotation, false); + } - function onQuaternionChange() { - rotation.setFromQuaternion(quaternion, undefined, false); - } + function onQuaternionChange() { + rotation.setFromQuaternion(quaternion, undefined, false); + } - rotation._onChange(onRotationChange); + rotation._onChange(onRotationChange); - quaternion._onChange(onQuaternionChange); + quaternion._onChange(onQuaternionChange); - Object.defineProperties(this, { - position: { - configurable: true, - enumerable: true, - value: position - }, - rotation: { - configurable: true, - enumerable: true, - value: rotation - }, - 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 = {}; - } + Object.defineProperties(this, { + position: { + configurable: true, + enumerable: true, + value: position + }, + rotation: { + configurable: true, + enumerable: true, + value: rotation + }, + 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 = {}; + } - Object3D.DefaultUp = new Vector3(0, 1, 0); - Object3D.DefaultMatrixAutoUpdate = true; - Object3D.prototype = Object.assign(Object.create(EventDispatcher.prototype), { - constructor: Object3D, - isObject3D: true, - onBeforeRender: function () {}, - onAfterRender: function () {}, - applyMatrix4: function (matrix) { + onBeforeRender() {} + + onAfterRender() {} + + applyMatrix4(matrix) { if (this.matrixAutoUpdate) this.updateMatrix(); this.matrix.premultiply(matrix); this.matrix.decompose(this.position, this.quaternion, this.scale); - }, - applyQuaternion: function (q) { + } + + applyQuaternion(q) { this.quaternion.premultiply(q); return this; - }, - setRotationFromAxisAngle: function (axis, angle) { + } + + setRotationFromAxisAngle(axis, angle) { // assumes axis is normalized this.quaternion.setFromAxisAngle(axis, angle); - }, - setRotationFromEuler: function (euler) { + } + + setRotationFromEuler(euler) { this.quaternion.setFromEuler(euler, true); - }, - setRotationFromMatrix: function (m) { + } + + setRotationFromMatrix(m) { // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) this.quaternion.setFromRotationMatrix(m); - }, - setRotationFromQuaternion: function (q) { + } + + setRotationFromQuaternion(q) { // assumes q is normalized this.quaternion.copy(q); - }, - rotateOnAxis: function (axis, angle) { + } + + 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: function (axis, angle) { + } + + rotateOnWorldAxis(axis, angle) { // rotate object on axis in world space // axis is assumed to be normalized // method assumes no rotated parent @@ -5049,40 +5100,50 @@ this.quaternion.premultiply(_q1); return this; - }, - rotateX: function (angle) { + } + + rotateX(angle) { return this.rotateOnAxis(_xAxis, angle); - }, - rotateY: function (angle) { + } + + rotateY(angle) { return this.rotateOnAxis(_yAxis, angle); - }, - rotateZ: function (angle) { + } + + rotateZ(angle) { return this.rotateOnAxis(_zAxis, angle); - }, - translateOnAxis: function (axis, distance) { + } + + 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: function (distance) { + } + + translateX(distance) { return this.translateOnAxis(_xAxis, distance); - }, - translateY: function (distance) { + } + + translateY(distance) { return this.translateOnAxis(_yAxis, distance); - }, - translateZ: function (distance) { + } + + translateZ(distance) { return this.translateOnAxis(_zAxis, distance); - }, - localToWorld: function (vector) { + } + + localToWorld(vector) { return vector.applyMatrix4(this.matrixWorld); - }, - worldToLocal: function (vector) { + } + + worldToLocal(vector) { return vector.applyMatrix4(_m1$1.copy(this.matrixWorld).invert()); - }, - lookAt: function (x, y, z) { + } + + lookAt(x, y, z) { // This method does not support objects having non-uniformly-scaled parent(s) if (x.isVector3) { _target.copy(x); @@ -5110,8 +5171,9 @@ this.quaternion.premultiply(_q1.invert()); } - }, - add: function (object) { + } + + add(object) { if (arguments.length > 1) { for (let i = 0; i < arguments.length; i++) { this.add(arguments[i]); @@ -5138,8 +5200,9 @@ } return this; - }, - remove: function (object) { + } + + remove(object) { if (arguments.length > 1) { for (let i = 0; i < arguments.length; i++) { this.remove(arguments[i]); @@ -5157,8 +5220,9 @@ } return this; - }, - clear: function () { + } + + clear() { for (let i = 0; i < this.children.length; i++) { const object = this.children[i]; object.parent = null; @@ -5167,8 +5231,9 @@ this.children.length = 0; return this; - }, - attach: function (object) { + } + + attach(object) { // adds object as a child of this, while maintaining the object's world transform this.updateWorldMatrix(true, false); @@ -5184,14 +5249,17 @@ this.add(object); object.updateWorldMatrix(false, true); return this; - }, - getObjectById: function (id) { + } + + getObjectById(id) { return this.getObjectByProperty('id', id); - }, - getObjectByName: function (name) { + } + + getObjectByName(name) { return this.getObjectByProperty('name', name); - }, - getObjectByProperty: function (name, value) { + } + + getObjectByProperty(name, value) { if (this[name] === value) return this; for (let i = 0, l = this.children.length; i < l; i++) { @@ -5204,8 +5272,9 @@ } return undefined; - }, - getWorldPosition: function (target) { + } + + getWorldPosition(target) { if (target === undefined) { console.warn('THREE.Object3D: .getWorldPosition() target is now required'); target = new Vector3(); @@ -5213,8 +5282,9 @@ this.updateWorldMatrix(true, false); return target.setFromMatrixPosition(this.matrixWorld); - }, - getWorldQuaternion: function (target) { + } + + getWorldQuaternion(target) { if (target === undefined) { console.warn('THREE.Object3D: .getWorldQuaternion() target is now required'); target = new Quaternion(); @@ -5223,8 +5293,9 @@ this.updateWorldMatrix(true, false); this.matrixWorld.decompose(_position$3, target, _scale$2); return target; - }, - getWorldScale: function (target) { + } + + getWorldScale(target) { if (target === undefined) { console.warn('THREE.Object3D: .getWorldScale() target is now required'); target = new Vector3(); @@ -5233,8 +5304,9 @@ this.updateWorldMatrix(true, false); this.matrixWorld.decompose(_position$3, _quaternion$2, target); return target; - }, - getWorldDirection: function (target) { + } + + getWorldDirection(target) { if (target === undefined) { console.warn('THREE.Object3D: .getWorldDirection() target is now required'); target = new Vector3(); @@ -5243,17 +5315,20 @@ this.updateWorldMatrix(true, false); const e = this.matrixWorld.elements; return target.set(e[8], e[9], e[10]).normalize(); - }, - raycast: function () {}, - traverse: function (callback) { + } + + raycast() {} + + traverse(callback) { callback(this); const children = this.children; for (let i = 0, l = children.length; i < l; i++) { children[i].traverse(callback); } - }, - traverseVisible: function (callback) { + } + + traverseVisible(callback) { if (this.visible === false) return; callback(this); const children = this.children; @@ -5261,20 +5336,23 @@ for (let i = 0, l = children.length; i < l; i++) { children[i].traverseVisible(callback); } - }, - traverseAncestors: function (callback) { + } + + traverseAncestors(callback) { const parent = this.parent; if (parent !== null) { callback(parent); parent.traverseAncestors(callback); } - }, - updateMatrix: function () { + } + + updateMatrix() { this.matrix.compose(this.position, this.quaternion, this.scale); this.matrixWorldNeedsUpdate = true; - }, - updateMatrixWorld: function (force) { + } + + updateMatrixWorld(force) { if (this.matrixAutoUpdate) this.updateMatrix(); if (this.matrixWorldNeedsUpdate || force) { @@ -5294,8 +5372,9 @@ for (let i = 0, l = children.length; i < l; i++) { children[i].updateMatrixWorld(force); } - }, - updateWorldMatrix: function (updateParents, updateChildren) { + } + + updateWorldMatrix(updateParents, updateChildren) { const parent = this.parent; if (updateParents === true && parent !== null) { @@ -5318,8 +5397,9 @@ children[i].updateWorldMatrix(false, true); } } - }, - toJSON: function (meta) { + } + + toJSON(meta) { // meta is a string when called from JSON.stringify const isRootObject = meta === undefined || typeof meta === 'string'; const output = {}; // meta is a hash used to collect geometries, materials. @@ -5469,11 +5549,13 @@ return values; } - }, - clone: function (recursive) { + } + + clone(recursive) { return new this.constructor().copy(this, recursive); - }, - copy: function (source, recursive = true) { + } + + copy(source, recursive = true) { this.name = source.name; this.up.copy(source.up); this.position.copy(source.position); @@ -5501,7 +5583,12 @@ return this; } - }); + + } + + Object3D.DefaultUp = new Vector3(0, 1, 0); + Object3D.DefaultMatrixAutoUpdate = true; + Object3D.prototype.isObject3D = true; const _vector1 = /*@__PURE__*/new Vector3(); @@ -5940,7 +6027,7 @@ Object.defineProperty(this, 'id', { value: materialId++ }); - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.name = ''; this.type = 'Material'; this.fog = true; @@ -5989,6 +6076,9 @@ Material.prototype = Object.assign(Object.create(EventDispatcher.prototype), { constructor: Material, isMaterial: true, + onBuild: function () + /* shaderobject, renderer */ + {}, onBeforeCompile: function () /* shaderobject, renderer */ {}, @@ -6112,13 +6202,13 @@ if (this.envMap && this.envMap.isTexture) { data.envMap = this.envMap.toJSON(meta).uuid; - data.reflectivity = this.reflectivity; // Scale behind envMap - - data.refractionRatio = this.refractionRatio; if (this.combine !== undefined) data.combine = this.combine; - if (this.envMapIntensity !== undefined) data.envMapIntensity = this.envMapIntensity; } + 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; } @@ -6483,9 +6573,9 @@ setHSL(h, s, l) { // h,s,l ranges are in 0.0 - 1.0 - h = MathUtils.euclideanModulo(h, 1); - s = MathUtils.clamp(s, 0, 1); - l = MathUtils.clamp(l, 0, 1); + h = euclideanModulo(h, 1); + s = clamp(s, 0, 1); + l = clamp(l, 0, 1); if (s === 0) { this.r = this.g = this.b = l; @@ -6582,7 +6672,7 @@ setColorName(style) { // color keywords - const hex = _colorKeywords[style]; + const hex = _colorKeywords[style.toLowerCase()]; if (hex !== undefined) { // red @@ -6784,9 +6874,9 @@ lerpHSL(color, alpha) { this.getHSL(_hslA); color.getHSL(_hslB); - const h = MathUtils.lerp(_hslA.h, _hslB.h, alpha); - const s = MathUtils.lerp(_hslA.s, _hslB.s, alpha); - const l = MathUtils.lerp(_hslA.l, _hslB.l, alpha); + 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; } @@ -6921,41 +7011,41 @@ MeshBasicMaterial.prototype.isMeshBasicMaterial = true; - const _vector$9 = new Vector3(); + const _vector$9 = new /*@__PURE__*/Vector3(); - const _vector2 = new Vector2(); + const _vector2 = new /*@__PURE__*/Vector2(); - function BufferAttribute(array, itemSize, normalized) { - if (Array.isArray(array)) { - throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.'); - } + class BufferAttribute { + constructor(array, itemSize, normalized) { + if (Array.isArray(array)) { + throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.'); + } - this.name = ''; - this.array = array; - this.itemSize = itemSize; - this.count = array !== undefined ? array.length / itemSize : 0; - this.normalized = normalized === true; - this.usage = StaticDrawUsage; - this.updateRange = { - offset: 0, - count: -1 - }; - this.version = 0; - } + this.name = ''; + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized === true; + this.usage = StaticDrawUsage; + this.updateRange = { + offset: 0, + count: -1 + }; + this.version = 0; - Object.defineProperty(BufferAttribute.prototype, 'needsUpdate', { - set: function (value) { + this.onUploadCallback = function () {}; + } + + set needsUpdate(value) { if (value === true) this.version++; } - }); - Object.assign(BufferAttribute.prototype, { - isBufferAttribute: true, - onUploadCallback: function () {}, - setUsage: function (value) { + + setUsage(value) { this.usage = value; return this; - }, - copy: function (source) { + } + + copy(source) { this.name = source.name; this.array = new source.array.constructor(source.array); this.itemSize = source.itemSize; @@ -6963,8 +7053,9 @@ this.normalized = source.normalized; this.usage = source.usage; return this; - }, - copyAt: function (index1, attribute, index2) { + } + + copyAt(index1, attribute, index2) { index1 *= this.itemSize; index2 *= attribute.itemSize; @@ -6973,12 +7064,14 @@ } return this; - }, - copyArray: function (array) { + } + + copyArray(array) { this.array.set(array); return this; - }, - copyColorsArray: function (colors) { + } + + copyColorsArray(colors) { const array = this.array; let offset = 0; @@ -6996,8 +7089,9 @@ } return this; - }, - copyVector2sArray: function (vectors) { + } + + copyVector2sArray(vectors) { const array = this.array; let offset = 0; @@ -7014,8 +7108,9 @@ } return this; - }, - copyVector3sArray: function (vectors) { + } + + copyVector3sArray(vectors) { const array = this.array; let offset = 0; @@ -7033,8 +7128,9 @@ } return this; - }, - copyVector4sArray: function (vectors) { + } + + copyVector4sArray(vectors) { const array = this.array; let offset = 0; @@ -7053,8 +7149,9 @@ } return this; - }, - applyMatrix3: function (m) { + } + + applyMatrix3(m) { if (this.itemSize === 2) { for (let i = 0, l = this.count; i < l; i++) { _vector2.fromBufferAttribute(this, i); @@ -7074,8 +7171,9 @@ } return this; - }, - applyMatrix4: function (m) { + } + + applyMatrix4(m) { for (let i = 0, l = this.count; i < l; i++) { _vector$9.x = this.getX(i); _vector$9.y = this.getY(i); @@ -7087,8 +7185,9 @@ } return this; - }, - applyNormalMatrix: function (m) { + } + + applyNormalMatrix(m) { for (let i = 0, l = this.count; i < l; i++) { _vector$9.x = this.getX(i); _vector$9.y = this.getY(i); @@ -7100,8 +7199,9 @@ } return this; - }, - transformDirection: function (m) { + } + + transformDirection(m) { for (let i = 0, l = this.count; i < l; i++) { _vector$9.x = this.getX(i); _vector$9.y = this.getY(i); @@ -7113,68 +7213,83 @@ } return this; - }, - set: function (value, offset = 0) { + } + + set(value, offset = 0) { this.array.set(value, offset); return this; - }, - getX: function (index) { + } + + getX(index) { return this.array[index * this.itemSize]; - }, - setX: function (index, x) { + } + + setX(index, x) { this.array[index * this.itemSize] = x; return this; - }, - getY: function (index) { + } + + getY(index) { return this.array[index * this.itemSize + 1]; - }, - setY: function (index, y) { + } + + setY(index, y) { this.array[index * this.itemSize + 1] = y; return this; - }, - getZ: function (index) { + } + + getZ(index) { return this.array[index * this.itemSize + 2]; - }, - setZ: function (index, z) { + } + + setZ(index, z) { this.array[index * this.itemSize + 2] = z; return this; - }, - getW: function (index) { + } + + getW(index) { return this.array[index * this.itemSize + 3]; - }, - setW: function (index, w) { + } + + setW(index, w) { this.array[index * this.itemSize + 3] = w; return this; - }, - setXY: function (index, x, y) { + } + + setXY(index, x, y) { index *= this.itemSize; this.array[index + 0] = x; this.array[index + 1] = y; return this; - }, - setXYZ: function (index, x, y, z) { + } + + setXYZ(index, x, y, z) { index *= this.itemSize; this.array[index + 0] = x; this.array[index + 1] = y; this.array[index + 2] = z; return this; - }, - setXYZW: function (index, x, y, z, w) { + } + + setXYZW(index, x, y, z, w) { index *= this.itemSize; this.array[index + 0] = x; this.array[index + 1] = y; this.array[index + 2] = z; this.array[index + 3] = w; return this; - }, - onUpload: function (callback) { + } + + onUpload(callback) { this.onUploadCallback = callback; return this; - }, - clone: function () { + } + + clone() { return new this.constructor(this.array, this.itemSize).copy(this); - }, - toJSON: function () { + } + + toJSON() { const data = { itemSize: this.itemSize, type: this.array.constructor.name, @@ -7186,78 +7301,82 @@ if (this.updateRange.offset !== 0 || this.updateRange.count !== -1) data.updateRange = this.updateRange; return data; } - }); // - function Int8BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Int8Array(array), itemSize, normalized); } - Int8BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; + BufferAttribute.prototype.isBufferAttribute = true; // + + class Int8BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Int8Array(array), itemSize, normalized); + } - function Uint8BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Uint8Array(array), itemSize, normalized); } - Uint8BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; + class Uint8BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Uint8Array(array), itemSize, normalized); + } - function Uint8ClampedBufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Uint8ClampedArray(array), itemSize, normalized); } - Uint8ClampedBufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; + class Uint8ClampedBufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Uint8ClampedArray(array), itemSize, normalized); + } - function Int16BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Int16Array(array), itemSize, normalized); } - Int16BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; + class Int16BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Int16Array(array), itemSize, normalized); + } - function Uint16BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Uint16Array(array), itemSize, normalized); } - Uint16BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; + class Uint16BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Uint16Array(array), itemSize, normalized); + } - function Int32BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Int32Array(array), itemSize, normalized); } - Int32BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; + class Int32BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Int32Array(array), itemSize, normalized); + } - function Uint32BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Uint32Array(array), itemSize, normalized); } - Uint32BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; + class Uint32BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Uint32Array(array), itemSize, normalized); + } - function Float16BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Uint16Array(array), itemSize, normalized); } - Float16BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Float16BufferAttribute.prototype.constructor = Float16BufferAttribute; - Float16BufferAttribute.prototype.isFloat16BufferAttribute = true; + class Float16BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Uint16Array(array), itemSize, normalized); + } - function Float32BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Float32Array(array), itemSize, normalized); } - Float32BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; + Float16BufferAttribute.prototype.isFloat16BufferAttribute = true; + + class Float32BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Float32Array(array), itemSize, normalized); + } - function Float64BufferAttribute(array, itemSize, normalized) { - BufferAttribute.call(this, new Float64Array(array), itemSize, normalized); } - Float64BufferAttribute.prototype = Object.create(BufferAttribute.prototype); - Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; // + class Float64BufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized) { + super(new Float64Array(array), itemSize, normalized); + } + + } // function arrayMax(array) { if (array.length === 0) return -Infinity; @@ -7288,46 +7407,46 @@ let _id = 0; - const _m1 = new Matrix4(); + const _m1 = new /*@__PURE__*/Matrix4(); - const _obj = new Object3D(); + const _obj = new /*@__PURE__*/Object3D(); - const _offset = new Vector3(); + const _offset = new /*@__PURE__*/Vector3(); - const _box$1 = new Box3(); + const _box$1 = new /*@__PURE__*/Box3(); - const _boxMorphTargets = new Box3(); + const _boxMorphTargets = new /*@__PURE__*/Box3(); - const _vector$8 = new Vector3(); + const _vector$8 = new /*@__PURE__*/Vector3(); - function BufferGeometry() { - Object.defineProperty(this, 'id', { - value: _id++ - }); - this.uuid = MathUtils.generateUUID(); - this.name = ''; - this.type = 'BufferGeometry'; - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.morphTargetsRelative = false; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; - this.drawRange = { - start: 0, - count: Infinity - }; - this.userData = {}; - } + class BufferGeometry extends EventDispatcher { + constructor() { + super(); + Object.defineProperty(this, 'id', { + value: _id++ + }); + this.uuid = generateUUID(); + this.name = ''; + this.type = 'BufferGeometry'; + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.morphTargetsRelative = false; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; + this.drawRange = { + start: 0, + count: Infinity + }; + this.userData = {}; + } - BufferGeometry.prototype = Object.assign(Object.create(EventDispatcher.prototype), { - constructor: BufferGeometry, - isBufferGeometry: true, - getIndex: function () { + getIndex() { return this.index; - }, - setIndex: function (index) { + } + + setIndex(index) { if (Array.isArray(index)) { this.index = new (arrayMax(index) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute)(index, 1); } else { @@ -7335,36 +7454,44 @@ } return this; - }, - getAttribute: function (name) { + } + + getAttribute(name) { return this.attributes[name]; - }, - setAttribute: function (name, attribute) { + } + + setAttribute(name, attribute) { this.attributes[name] = attribute; return this; - }, - deleteAttribute: function (name) { + } + + deleteAttribute(name) { delete this.attributes[name]; return this; - }, - hasAttribute: function (name) { + } + + hasAttribute(name) { return this.attributes[name] !== undefined; - }, - addGroup: function (start, count, materialIndex = 0) { + } + + addGroup(start, count, materialIndex = 0) { this.groups.push({ start: start, count: count, materialIndex: materialIndex }); - }, - clearGroups: function () { + } + + clearGroups() { this.groups = []; - }, - setDrawRange: function (start, count) { + } + + setDrawRange(start, count) { this.drawRange.start = start; this.drawRange.count = count; - }, - applyMatrix4: function (matrix) { + } + + applyMatrix4(matrix) { const position = this.attributes.position; if (position !== undefined) { @@ -7396,57 +7523,65 @@ } return this; - }, - rotateX: function (angle) { + } + + rotateX(angle) { // rotate geometry around world x-axis _m1.makeRotationX(angle); this.applyMatrix4(_m1); return this; - }, - rotateY: function (angle) { + } + + rotateY(angle) { // rotate geometry around world y-axis _m1.makeRotationY(angle); this.applyMatrix4(_m1); return this; - }, - rotateZ: function (angle) { + } + + rotateZ(angle) { // rotate geometry around world z-axis _m1.makeRotationZ(angle); this.applyMatrix4(_m1); return this; - }, - translate: function (x, y, z) { + } + + translate(x, y, z) { // translate geometry _m1.makeTranslation(x, y, z); this.applyMatrix4(_m1); return this; - }, - scale: function (x, y, z) { + } + + scale(x, y, z) { // scale geometry _m1.makeScale(x, y, z); this.applyMatrix4(_m1); return this; - }, - lookAt: function (vector) { + } + + lookAt(vector) { _obj.lookAt(vector); _obj.updateMatrix(); this.applyMatrix4(_obj.matrix); return this; - }, - center: function () { + } + + center() { this.computeBoundingBox(); this.boundingBox.getCenter(_offset).negate(); this.translate(_offset.x, _offset.y, _offset.z); return this; - }, - setFromPoints: function (points) { + } + + setFromPoints(points) { const position = []; for (let i = 0, l = points.length; i < l; i++) { @@ -7456,8 +7591,9 @@ this.setAttribute('position', new Float32BufferAttribute(position, 3)); return this; - }, - computeBoundingBox: function () { + } + + computeBoundingBox() { if (this.boundingBox === null) { this.boundingBox = new Box3(); } @@ -7501,8 +7637,9 @@ if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) { console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this); } - }, - computeBoundingSphere: function () { + } + + computeBoundingSphere() { if (this.boundingSphere === null) { this.boundingSphere = new Sphere(); } @@ -7583,10 +7720,12 @@ console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this); } } - }, - computeFaceNormals: function () {// backwards compatibility - }, - computeTangents: function () { + } + + computeFaceNormals() {// backwards compatibility + } + + computeTangents() { const index = this.index; const attributes = this.attributes; // based on http://www.terathon.com/code/tangent.html // (per vertex tangents) @@ -7700,8 +7839,9 @@ handleVertex(indices[j + 2]); } } - }, - computeVertexNormals: function () { + } + + computeVertexNormals() { const index = this.index; const positionAttribute = this.getAttribute('position'); @@ -7766,8 +7906,9 @@ this.normalizeNormals(); normalAttribute.needsUpdate = true; } - }, - merge: function (geometry, offset) { + } + + merge(geometry, offset) { if (!(geometry && geometry.isBufferGeometry)) { console.error('THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry); return; @@ -7795,8 +7936,9 @@ } return this; - }, - normalizeNormals: function () { + } + + normalizeNormals() { const normals = this.attributes.normal; for (let i = 0, il = normals.count; i < il; i++) { @@ -7806,8 +7948,9 @@ normals.setXYZ(i, _vector$8.x, _vector$8.y, _vector$8.z); } - }, - toNonIndexed: function () { + } + + toNonIndexed() { function convertBufferAttribute(attribute, indices) { const array = attribute.array; const itemSize = attribute.itemSize; @@ -7869,8 +8012,9 @@ } return geometry2; - }, - toJSON: function () { + } + + toJSON() { const data = { metadata: { version: 4.5, @@ -7953,8 +8097,9 @@ } return data; - }, - clone: function () { + } + + clone() { /* // Handle primitives const parameters = this.parameters; @@ -7970,8 +8115,9 @@ return new this.constructor().copy( this ); */ return new BufferGeometry().copy(this); - }, - copy: function (source) { + } + + copy(source) { // reset this.index = null; this.attributes = {}; @@ -8041,61 +8187,63 @@ this.userData = source.userData; return this; - }, - dispose: function () { + } + + dispose() { this.dispatchEvent({ type: 'dispose' }); } - }); - const _inverseMatrix$2 = new Matrix4(); + } - const _ray$2 = new Ray(); + BufferGeometry.prototype.isBufferGeometry = true; - const _sphere$3 = new Sphere(); + const _inverseMatrix$2 = /*@__PURE__*/new Matrix4(); - const _vA$1 = new Vector3(); + const _ray$2 = /*@__PURE__*/new Ray(); - const _vB$1 = new Vector3(); + const _sphere$3 = /*@__PURE__*/new Sphere(); - const _vC$1 = new Vector3(); + const _vA$1 = /*@__PURE__*/new Vector3(); - const _tempA = new Vector3(); + const _vB$1 = /*@__PURE__*/new Vector3(); - const _tempB = new Vector3(); + const _vC$1 = /*@__PURE__*/new Vector3(); - const _tempC = new Vector3(); + const _tempA = /*@__PURE__*/new Vector3(); - const _morphA = new Vector3(); + const _tempB = /*@__PURE__*/new Vector3(); - const _morphB = new Vector3(); + const _tempC = /*@__PURE__*/new Vector3(); - const _morphC = new Vector3(); + const _morphA = /*@__PURE__*/new Vector3(); - const _uvA$1 = new Vector2(); + const _morphB = /*@__PURE__*/new Vector3(); - const _uvB$1 = new Vector2(); + const _morphC = /*@__PURE__*/new Vector3(); - const _uvC$1 = new Vector2(); + const _uvA$1 = /*@__PURE__*/new Vector2(); - const _intersectionPoint = new Vector3(); + const _uvB$1 = /*@__PURE__*/new Vector2(); - const _intersectionPointWorld = new Vector3(); + const _uvC$1 = /*@__PURE__*/new Vector2(); - function Mesh(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) { - Object3D.call(this); - this.type = 'Mesh'; - this.geometry = geometry; - this.material = material; - this.updateMorphTargets(); - } + const _intersectionPoint = /*@__PURE__*/new Vector3(); - Mesh.prototype = Object.assign(Object.create(Object3D.prototype), { - constructor: Mesh, - isMesh: true, - copy: function (source) { - Object3D.prototype.copy.call(this, source); + const _intersectionPointWorld = /*@__PURE__*/new Vector3(); + + class Mesh extends Object3D { + constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) { + super(); + this.type = 'Mesh'; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } + + copy(source) { + super.copy(source); if (source.morphTargetInfluences !== undefined) { this.morphTargetInfluences = source.morphTargetInfluences.slice(); @@ -8108,8 +8256,9 @@ this.material = source.material; this.geometry = source.geometry; return this; - }, - updateMorphTargets: function () { + } + + updateMorphTargets() { const geometry = this.geometry; if (geometry.isBufferGeometry) { @@ -8137,8 +8286,9 @@ console.error('THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); } } - }, - raycast: function (raycaster, intersects) { + } + + raycast(raycaster, intersects) { const geometry = this.geometry; const material = this.material; const matrixWorld = this.matrixWorld; @@ -8258,7 +8408,10 @@ console.error('THREE.Mesh.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); } } - }); + + } + + Mesh.prototype.isMesh = true; function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) { let intersect; @@ -8552,163 +8705,163 @@ * } */ - function ShaderMaterial(parameters) { - Material.call(this); - this.type = 'ShaderMaterial'; - this.defines = {}; - this.uniforms = {}; - this.vertexShader = default_vertex; - this.fragmentShader = default_fragment; - this.linewidth = 1; - this.wireframe = false; - this.wireframeLinewidth = 1; - this.fog = false; // set to use scene fog + class ShaderMaterial extends Material { + constructor(parameters) { + super(); + this.type = 'ShaderMaterial'; + this.defines = {}; + this.uniforms = {}; + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; + this.linewidth = 1; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.fog = false; // set to use scene fog - this.lights = false; // set to use scene lights + this.lights = false; // set to use scene lights - this.clipping = false; // set to use user-defined clipping planes + this.clipping = false; // set to use user-defined clipping planes - this.skinning = false; // set to use skinning attribute streams + this.skinning = false; // set to use skinning attribute streams - this.morphTargets = false; // set to use morph targets + this.morphTargets = false; // set to use morph targets - this.morphNormals = false; // set to use morph normals + this.morphNormals = false; // set to use morph normals - this.extensions = { - derivatives: false, - // set to use derivatives - fragDepth: false, - // set to use fragment depth values - drawBuffers: false, - // set to use draw buffers - shaderTextureLOD: false // set to use shader texture LOD + this.extensions = { + derivatives: false, + // set to use derivatives + fragDepth: false, + // set to use fragment depth values + drawBuffers: false, + // set to use draw buffers + shaderTextureLOD: false // set to use shader texture LOD - }; // When rendered geometry doesn't include these attributes but the material does, - // use these default values in WebGL. This avoids errors when buffer data is missing. + }; // When rendered geometry doesn't include these attributes but the material does, + // use these default values in WebGL. This avoids errors when buffer data is missing. - this.defaultAttributeValues = { - 'color': [1, 1, 1], - 'uv': [0, 0], - 'uv2': [0, 0] - }; - this.index0AttributeName = undefined; - this.uniformsNeedUpdate = false; - this.glslVersion = null; + this.defaultAttributeValues = { + 'color': [1, 1, 1], + 'uv': [0, 0], + 'uv2': [0, 0] + }; + this.index0AttributeName = undefined; + this.uniformsNeedUpdate = false; + this.glslVersion = null; - if (parameters !== undefined) { - if (parameters.attributes !== undefined) { - console.error('THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.'); + if (parameters !== undefined) { + if (parameters.attributes !== undefined) { + console.error('THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.'); + } + + this.setValues(parameters); } + } - this.setValues(parameters); + copy(source) { + super.copy(source); + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; + this.uniforms = cloneUniforms(source.uniforms); + this.defines = Object.assign({}, source.defines); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.lights = source.lights; + this.clipping = source.clipping; + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; + this.morphNormals = source.morphNormals; + this.extensions = Object.assign({}, source.extensions); + this.glslVersion = source.glslVersion; + return this; } - } - ShaderMaterial.prototype = Object.create(Material.prototype); - ShaderMaterial.prototype.constructor = ShaderMaterial; - ShaderMaterial.prototype.isShaderMaterial = true; + toJSON(meta) { + const data = super.toJSON(meta); + data.glslVersion = this.glslVersion; + data.uniforms = {}; - ShaderMaterial.prototype.copy = function (source) { - Material.prototype.copy.call(this, source); - this.fragmentShader = source.fragmentShader; - this.vertexShader = source.vertexShader; - this.uniforms = cloneUniforms(source.uniforms); - this.defines = Object.assign({}, source.defines); - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.lights = source.lights; - this.clipping = source.clipping; - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - this.extensions = Object.assign({}, source.extensions); - this.glslVersion = source.glslVersion; - return this; - }; + for (const name in this.uniforms) { + const uniform = this.uniforms[name]; + const value = uniform.value; - ShaderMaterial.prototype.toJSON = function (meta) { - const data = Material.prototype.toJSON.call(this, meta); - data.glslVersion = this.glslVersion; - data.uniforms = {}; + if (value && value.isTexture) { + data.uniforms[name] = { + type: 't', + value: value.toJSON(meta).uuid + }; + } else if (value && value.isColor) { + data.uniforms[name] = { + type: 'c', + value: value.getHex() + }; + } else if (value && value.isVector2) { + data.uniforms[name] = { + type: 'v2', + value: value.toArray() + }; + } else if (value && value.isVector3) { + data.uniforms[name] = { + type: 'v3', + value: value.toArray() + }; + } else if (value && value.isVector4) { + data.uniforms[name] = { + type: 'v4', + value: value.toArray() + }; + } else if (value && value.isMatrix3) { + data.uniforms[name] = { + type: 'm3', + value: value.toArray() + }; + } else if (value && value.isMatrix4) { + data.uniforms[name] = { + type: 'm4', + value: value.toArray() + }; + } else { + data.uniforms[name] = { + value: value + }; // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far + } + } - for (const name in this.uniforms) { - const uniform = this.uniforms[name]; - const value = uniform.value; + if (Object.keys(this.defines).length > 0) data.defines = this.defines; + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; + const extensions = {}; - if (value && value.isTexture) { - data.uniforms[name] = { - type: 't', - value: value.toJSON(meta).uuid - }; - } else if (value && value.isColor) { - data.uniforms[name] = { - type: 'c', - value: value.getHex() - }; - } else if (value && value.isVector2) { - data.uniforms[name] = { - type: 'v2', - value: value.toArray() - }; - } else if (value && value.isVector3) { - data.uniforms[name] = { - type: 'v3', - value: value.toArray() - }; - } else if (value && value.isVector4) { - data.uniforms[name] = { - type: 'v4', - value: value.toArray() - }; - } else if (value && value.isMatrix3) { - data.uniforms[name] = { - type: 'm3', - value: value.toArray() - }; - } else if (value && value.isMatrix4) { - data.uniforms[name] = { - type: 'm4', - value: value.toArray() - }; - } else { - data.uniforms[name] = { - value: value - }; // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far + for (const key in this.extensions) { + if (this.extensions[key] === true) extensions[key] = true; } - } - - if (Object.keys(this.defines).length > 0) data.defines = this.defines; - data.vertexShader = this.vertexShader; - data.fragmentShader = this.fragmentShader; - const extensions = {}; - for (const key in this.extensions) { - if (this.extensions[key] === true) extensions[key] = true; + if (Object.keys(extensions).length > 0) data.extensions = extensions; + return data; } - if (Object.keys(extensions).length > 0) data.extensions = extensions; - return data; - }; - - function Camera() { - Object3D.call(this); - this.type = 'Camera'; - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); - this.projectionMatrixInverse = new Matrix4(); } - Camera.prototype = Object.assign(Object.create(Object3D.prototype), { - constructor: Camera, - isCamera: true, - copy: function (source, recursive) { - Object3D.prototype.copy.call(this, source, recursive); + ShaderMaterial.prototype.isShaderMaterial = true; + + class Camera extends Object3D { + constructor() { + super(); + this.type = 'Camera'; + this.matrixWorldInverse = new Matrix4(); + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); + } + + copy(source, recursive) { + super.copy(source, recursive); this.matrixWorldInverse.copy(source.matrixWorldInverse); this.projectionMatrix.copy(source.projectionMatrix); this.projectionMatrixInverse.copy(source.projectionMatrixInverse); return this; - }, - getWorldDirection: function (target) { + } + + getWorldDirection(target) { if (target === undefined) { console.warn('THREE.Camera: .getWorldDirection() target is now required'); target = new Vector3(); @@ -8717,42 +8870,46 @@ this.updateWorldMatrix(true, false); const e = this.matrixWorld.elements; return target.set(-e[8], -e[9], -e[10]).normalize(); - }, - updateMatrixWorld: function (force) { - Object3D.prototype.updateMatrixWorld.call(this, force); + } + + updateMatrixWorld(force) { + super.updateMatrixWorld(force); this.matrixWorldInverse.copy(this.matrixWorld).invert(); - }, - updateWorldMatrix: function (updateParents, updateChildren) { - Object3D.prototype.updateWorldMatrix.call(this, updateParents, updateChildren); + } + + updateWorldMatrix(updateParents, updateChildren) { + super.updateWorldMatrix(updateParents, updateChildren); this.matrixWorldInverse.copy(this.matrixWorld).invert(); - }, - clone: function () { + } + + clone() { return new this.constructor().copy(this); } - }); - function PerspectiveCamera(fov = 50, aspect = 1, near = 0.1, far = 2000) { - Camera.call(this); - this.type = 'PerspectiveCamera'; - this.fov = fov; - this.zoom = 1; - this.near = near; - this.far = far; - this.focus = 10; - this.aspect = aspect; - this.view = null; - this.filmGauge = 35; // width of the film (default in millimeters) + } - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + Camera.prototype.isCamera = true; - this.updateProjectionMatrix(); - } + class PerspectiveCamera extends Camera { + constructor(fov = 50, aspect = 1, near = 0.1, far = 2000) { + super(); + this.type = 'PerspectiveCamera'; + this.fov = fov; + this.zoom = 1; + this.near = near; + this.far = far; + this.focus = 10; + this.aspect = aspect; + this.view = null; + this.filmGauge = 35; // width of the film (default in millimeters) + + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - PerspectiveCamera.prototype = Object.assign(Object.create(Camera.prototype), { - constructor: PerspectiveCamera, - isPerspectiveCamera: true, - copy: function (source, recursive) { - Camera.prototype.copy.call(this, source, recursive); + this.updateProjectionMatrix(); + } + + copy(source, recursive) { + super.copy(source, recursive); this.fov = source.fov; this.zoom = source.zoom; this.near = source.near; @@ -8763,8 +8920,7 @@ this.filmGauge = source.filmGauge; this.filmOffset = source.filmOffset; return this; - }, - + } /** * Sets the FOV by focal length in respect to the current .filmGauge. * @@ -8773,32 +8929,37 @@ * * Values for focal length and film gauge must have the same unit. */ - setFocalLength: function (focalLength) { + + + setFocalLength(focalLength) { /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - this.fov = MathUtils.RAD2DEG * 2 * Math.atan(vExtentSlope); + this.fov = RAD2DEG * 2 * Math.atan(vExtentSlope); this.updateProjectionMatrix(); - }, - + } /** * Calculates the focal length from the current .fov and .filmGauge. */ - getFocalLength: function () { - const vExtentSlope = Math.tan(MathUtils.DEG2RAD * 0.5 * this.fov); + + + getFocalLength() { + const vExtentSlope = Math.tan(DEG2RAD * 0.5 * this.fov); return 0.5 * this.getFilmHeight() / vExtentSlope; - }, - getEffectiveFOV: function () { - return MathUtils.RAD2DEG * 2 * Math.atan(Math.tan(MathUtils.DEG2RAD * 0.5 * this.fov) / this.zoom); - }, - getFilmWidth: function () { + } + + getEffectiveFOV() { + return RAD2DEG * 2 * Math.atan(Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom); + } + + getFilmWidth() { // film not completely covered in portrait format (aspect < 1) return this.filmGauge * Math.min(this.aspect, 1); - }, - getFilmHeight: function () { + } + + getFilmHeight() { // film not completely covered in landscape format (aspect > 1) return this.filmGauge / Math.max(this.aspect, 1); - }, - + } /** * Sets an offset in a larger frustum. This is useful for multi-window or * multi-monitor/multi-machine setups. @@ -8834,7 +8995,9 @@ * * Note there is no reason monitors have to be the same size or in a grid. */ - setViewOffset: function (fullWidth, fullHeight, x, y, width, height) { + + + setViewOffset(fullWidth, fullHeight, x, y, width, height) { this.aspect = fullWidth / fullHeight; if (this.view === null) { @@ -8857,17 +9020,19 @@ this.view.width = width; this.view.height = height; this.updateProjectionMatrix(); - }, - clearViewOffset: function () { + } + + clearViewOffset() { if (this.view !== null) { this.view.enabled = false; } this.updateProjectionMatrix(); - }, - updateProjectionMatrix: function () { + } + + updateProjectionMatrix() { const near = this.near; - let top = near * Math.tan(MathUtils.DEG2RAD * 0.5 * this.fov) / this.zoom; + let top = near * Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom; let height = 2 * top; let width = this.aspect * height; let left = -0.5 * width; @@ -8886,9 +9051,10 @@ if (skew !== 0) left += near * skew / this.getFilmWidth(); this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far); this.projectionMatrixInverse.copy(this.projectionMatrix).invert(); - }, - toJSON: function (meta) { - const data = Object3D.prototype.toJSON.call(this, meta); + } + + toJSON(meta) { + const data = super.toJSON(meta); data.object.fov = this.fov; data.object.zoom = this.zoom; data.object.near = this.near; @@ -8900,7 +9066,10 @@ data.object.filmOffset = this.filmOffset; return data; } - }); + + } + + PerspectiveCamera.prototype.isPerspectiveCamera = true; const fov = 90, aspect = 1; @@ -11633,6 +11802,7 @@ this.wrapR = ClampToEdgeWrapping; this.generateMipmaps = false; this.flipY = false; + this.unpackAlignment = 1; this.needsUpdate = true; } @@ -11661,6 +11831,7 @@ this.wrapR = ClampToEdgeWrapping; this.generateMipmaps = false; this.flipY = false; + this.unpackAlignment = 1; this.needsUpdate = true; } @@ -13003,7 +13174,7 @@ combine: material.combine, vertexTangents: material.normalMap && material.vertexTangents, vertexColors: material.vertexColors, - vertexAlphas: material.vertexColors === true && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4, + vertexAlphas: material.vertexColors === true && object.geometry && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4, vertexUvs: !!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatMap || !!material.clearcoatRoughnessMap || !!material.clearcoatNormalMap || !!material.displacementMap || !!material.transmissionMap, uvsVertexOnly: !(!!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatNormalMap || !!material.transmissionMap) && !!material.displacementMap, fog: !!fog, @@ -14512,6 +14683,17 @@ if (currentBoundFramebuffers[target] !== framebuffer) { gl.bindFramebuffer(target, framebuffer); currentBoundFramebuffers[target] = framebuffer; + + if (isWebGL2) { + // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER + if (target === gl.DRAW_FRAMEBUFFER) { + currentBoundFramebuffers[gl.FRAMEBUFFER] = framebuffer; + } + + if (target === gl.FRAMEBUFFER) { + currentBoundFramebuffers[gl.DRAW_FRAMEBUFFER] = framebuffer; + } + } } } @@ -14958,7 +15140,7 @@ if (scale < 1 || needsPowerOfTwo === true) { // only perform resize for certain image types if (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement || typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap) { - const floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor; + const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor; const width = floor(scale * image.width); const height = floor(scale * image.height); if (_canvas === undefined) _canvas = createCanvas(width, height); // cube textures can't reuse the same canvas @@ -14982,8 +15164,8 @@ return image; } - function isPowerOfTwo(image) { - return MathUtils.isPowerOfTwo(image.width) && MathUtils.isPowerOfTwo(image.height); + function isPowerOfTwo$1(image) { + return isPowerOfTwo(image.width) && isPowerOfTwo(image.height); } function textureNeedsPowerOfTwo(texture) { @@ -15273,9 +15455,9 @@ _gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE); - const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo(texture.image) === false; + const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false; const image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize); - const supportsMips = isPowerOfTwo(image) || isWebGL2, + const supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format); let glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType); @@ -15423,7 +15605,7 @@ } const image = cubeImage[0], - supportsMips = isPowerOfTwo(image) || isWebGL2, + supportsMips = isPowerOfTwo$1(image) || isWebGL2, glFormat = utils.convert(texture.format), glType = utils.convert(texture.type), glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType); @@ -15628,7 +15810,7 @@ const isCube = renderTarget.isWebGLCubeRenderTarget === true; const isMultisample = renderTarget.isWebGLMultisampleRenderTarget === true; const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray; - const supportsMips = isPowerOfTwo(renderTarget) || isWebGL2; // Handles WebGL2 RGBFormat fallback - #18858 + const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; // Handles WebGL2 RGBFormat fallback - #18858 if (isWebGL2 && texture.format === RGBFormat && (texture.type === FloatType || texture.type === HalfFloatType)) { texture.format = RGBAFormat; @@ -15723,7 +15905,7 @@ function updateRenderTargetMipmap(renderTarget) { const texture = renderTarget.texture; - const supportsMips = isPowerOfTwo(renderTarget) || isWebGL2; + const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2; if (textureNeedsGenerateMipmaps(texture, supportsMips)) { const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; @@ -15739,18 +15921,19 @@ function updateMultisampleRenderTarget(renderTarget) { if (renderTarget.isWebGLMultisampleRenderTarget) { if (isWebGL2) { - const renderTargetProperties = properties.get(renderTarget); - state.bindFramebuffer(_gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); - state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer); const width = renderTarget.width; const height = renderTarget.height; let mask = _gl.COLOR_BUFFER_BIT; if (renderTarget.depthBuffer) mask |= _gl.DEPTH_BUFFER_BIT; if (renderTarget.stencilBuffer) mask |= _gl.STENCIL_BUFFER_BIT; + const renderTargetProperties = properties.get(renderTarget); + state.bindFramebuffer(_gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); + state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer); _gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST); - state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); // see #18905 + state.bindFramebuffer(_gl.READ_FRAMEBUFFER, null); + state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer); } else { console.warn('THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.'); } @@ -15961,15 +16144,18 @@ Group.prototype.isGroup = true; - function WebXRController() { - this._targetRay = null; - this._grip = null; - this._hand = null; - } + const _moveEvent = { + type: 'move' + }; - Object.assign(WebXRController.prototype, { - constructor: WebXRController, - getHandSpace: function () { + class WebXRController { + constructor() { + this._targetRay = null; + this._grip = null; + this._hand = null; + } + + getHandSpace() { if (this._hand === null) { this._hand = new Group(); this._hand.matrixAutoUpdate = false; @@ -15981,26 +16167,37 @@ } return this._hand; - }, - getTargetRaySpace: function () { + } + + getTargetRaySpace() { if (this._targetRay === null) { this._targetRay = new Group(); this._targetRay.matrixAutoUpdate = false; this._targetRay.visible = false; + this._targetRay.hasLinearVelocity = false; + this._targetRay.linearVelocity = new Vector3(); + this._targetRay.hasAngularVelocity = false; + this._targetRay.angularVelocity = new Vector3(); } return this._targetRay; - }, - getGripSpace: function () { + } + + getGripSpace() { if (this._grip === null) { this._grip = new Group(); this._grip.matrixAutoUpdate = false; this._grip.visible = false; + this._grip.hasLinearVelocity = false; + this._grip.linearVelocity = new Vector3(); + this._grip.hasAngularVelocity = false; + this._grip.angularVelocity = new Vector3(); } return this._grip; - }, - dispatchEvent: function (event) { + } + + dispatchEvent(event) { if (this._targetRay !== null) { this._targetRay.dispatchEvent(event); } @@ -16014,8 +16211,9 @@ } return this; - }, - disconnect: function (inputSource) { + } + + disconnect(inputSource) { this.dispatchEvent({ type: 'disconnected', data: inputSource @@ -16034,8 +16232,9 @@ } return this; - }, - update: function (inputSource, frame, referenceSpace) { + } + + update(inputSource, frame, referenceSpace) { let inputPose = null; let gripPose = null; let handPose = null; @@ -16050,6 +16249,22 @@ if (inputPose !== null) { targetRay.matrix.fromArray(inputPose.transform.matrix); targetRay.matrix.decompose(targetRay.position, targetRay.rotation, targetRay.scale); + + if (inputPose.linearVelocity) { + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy(inputPose.linearVelocity); + } else { + targetRay.hasLinearVelocity = false; + } + + if (inputPose.angularVelocity) { + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy(inputPose.angularVelocity); + } else { + targetRay.hasAngularVelocity = false; + } + + this.dispatchEvent(_moveEvent); } } @@ -16111,6 +16326,20 @@ if (gripPose !== null) { grip.matrix.fromArray(gripPose.transform.matrix); grip.matrix.decompose(grip.position, grip.rotation, grip.scale); + + if (gripPose.linearVelocity) { + grip.hasLinearVelocity = true; + grip.linearVelocity.copy(gripPose.linearVelocity); + } else { + grip.hasLinearVelocity = false; + } + + if (gripPose.angularVelocity) { + grip.hasAngularVelocity = true; + grip.angularVelocity.copy(gripPose.angularVelocity); + } else { + grip.hasAngularVelocity = false; + } } } } @@ -16130,358 +16359,361 @@ return this; } - }); - function WebXRManager(renderer, gl) { - const scope = this; - const state = renderer.state; - let session = null; - let framebufferScaleFactor = 1.0; - let referenceSpace = null; - let referenceSpaceType = 'local-floor'; - let pose = null; - const controllers = []; - const inputSourcesMap = new Map(); // - - const cameraL = new PerspectiveCamera(); - cameraL.layers.enable(1); - cameraL.viewport = new Vector4(); - const cameraR = new PerspectiveCamera(); - cameraR.layers.enable(2); - cameraR.viewport = new Vector4(); - const cameras = [cameraL, cameraR]; - const cameraVR = new ArrayCamera(); - cameraVR.layers.enable(1); - cameraVR.layers.enable(2); - let _currentDepthNear = null; - let _currentDepthFar = null; // + } - this.enabled = false; - this.isPresenting = false; + class WebXRManager extends EventDispatcher { + constructor(renderer, gl) { + super(); + const scope = this; + const state = renderer.state; + let session = null; + let framebufferScaleFactor = 1.0; + let referenceSpace = null; + let referenceSpaceType = 'local-floor'; + let pose = null; + const controllers = []; + const inputSourcesMap = new Map(); // + + const cameraL = new PerspectiveCamera(); + cameraL.layers.enable(1); + cameraL.viewport = new Vector4(); + const cameraR = new PerspectiveCamera(); + cameraR.layers.enable(2); + cameraR.viewport = new Vector4(); + const cameras = [cameraL, cameraR]; + const cameraVR = new ArrayCamera(); + cameraVR.layers.enable(1); + cameraVR.layers.enable(2); + let _currentDepthNear = null; + let _currentDepthFar = null; // + + this.enabled = false; + this.isPresenting = false; + + this.getController = function (index) { + let controller = controllers[index]; + + if (controller === undefined) { + controller = new WebXRController(); + controllers[index] = controller; + } + + return controller.getTargetRaySpace(); + }; - this.getController = function (index) { - let controller = controllers[index]; + this.getControllerGrip = function (index) { + let controller = controllers[index]; - if (controller === undefined) { - controller = new WebXRController(); - controllers[index] = controller; - } + if (controller === undefined) { + controller = new WebXRController(); + controllers[index] = controller; + } - return controller.getTargetRaySpace(); - }; + return controller.getGripSpace(); + }; - this.getControllerGrip = function (index) { - let controller = controllers[index]; + this.getHand = function (index) { + let controller = controllers[index]; - if (controller === undefined) { - controller = new WebXRController(); - controllers[index] = controller; - } + if (controller === undefined) { + controller = new WebXRController(); + controllers[index] = controller; + } - return controller.getGripSpace(); - }; + return controller.getHandSpace(); + }; // - this.getHand = function (index) { - let controller = controllers[index]; - if (controller === undefined) { - controller = new WebXRController(); - controllers[index] = controller; - } + function onSessionEvent(event) { + const controller = inputSourcesMap.get(event.inputSource); - return controller.getHandSpace(); - }; // + if (controller) { + controller.dispatchEvent({ + type: event.type, + data: event.inputSource + }); + } + } + function onSessionEnd() { + inputSourcesMap.forEach(function (controller, inputSource) { + controller.disconnect(inputSource); + }); + inputSourcesMap.clear(); + _currentDepthNear = null; + _currentDepthFar = null; // restore framebuffer/rendering state - function onSessionEvent(event) { - const controller = inputSourcesMap.get(event.inputSource); + state.bindXRFramebuffer(null); + renderer.setRenderTarget(renderer.getRenderTarget()); // - if (controller) { - controller.dispatchEvent({ - type: event.type, - data: event.inputSource + animation.stop(); + scope.isPresenting = false; + scope.dispatchEvent({ + type: 'sessionend' }); } - } - function onSessionEnd() { - inputSourcesMap.forEach(function (controller, inputSource) { - controller.disconnect(inputSource); - }); - inputSourcesMap.clear(); - _currentDepthNear = null; - _currentDepthFar = null; // restore framebuffer/rendering state + this.setFramebufferScaleFactor = function (value) { + framebufferScaleFactor = value; - state.bindXRFramebuffer(null); - renderer.setRenderTarget(renderer.getRenderTarget()); // + if (scope.isPresenting === true) { + console.warn('THREE.WebXRManager: Cannot change framebuffer scale while presenting.'); + } + }; - animation.stop(); - scope.isPresenting = false; - scope.dispatchEvent({ - type: 'sessionend' - }); - } + this.setReferenceSpaceType = function (value) { + referenceSpaceType = value; - this.setFramebufferScaleFactor = function (value) { - framebufferScaleFactor = value; + if (scope.isPresenting === true) { + console.warn('THREE.WebXRManager: Cannot change reference space type while presenting.'); + } + }; - if (scope.isPresenting === true) { - console.warn('THREE.WebXRManager: Cannot change framebuffer scale while presenting.'); - } - }; + this.getReferenceSpace = function () { + return referenceSpace; + }; - this.setReferenceSpaceType = function (value) { - referenceSpaceType = value; + this.getSession = function () { + return session; + }; - if (scope.isPresenting === true) { - console.warn('THREE.WebXRManager: Cannot change reference space type while presenting.'); - } - }; + this.setSession = async function (value) { + session = value; + + if (session !== null) { + session.addEventListener('select', onSessionEvent); + session.addEventListener('selectstart', onSessionEvent); + session.addEventListener('selectend', onSessionEvent); + session.addEventListener('squeeze', onSessionEvent); + session.addEventListener('squeezestart', onSessionEvent); + session.addEventListener('squeezeend', onSessionEvent); + session.addEventListener('end', onSessionEnd); + session.addEventListener('inputsourceschange', onInputSourcesChange); + const attributes = gl.getContextAttributes(); + + if (attributes.xrCompatible !== true) { + await gl.makeXRCompatible(); + } - this.getReferenceSpace = function () { - return referenceSpace; - }; + const layerInit = { + antialias: attributes.antialias, + alpha: attributes.alpha, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor: framebufferScaleFactor + }; // eslint-disable-next-line no-undef + + const baseLayer = new XRWebGLLayer(session, gl, layerInit); + session.updateRenderState({ + baseLayer: baseLayer + }); + referenceSpace = await session.requestReferenceSpace(referenceSpaceType); + animation.setContext(session); + animation.start(); + scope.isPresenting = true; + scope.dispatchEvent({ + type: 'sessionstart' + }); + } + }; - this.getSession = function () { - return session; - }; + function onInputSourcesChange(event) { + const inputSources = session.inputSources; // Assign inputSources to available controllers - this.setSession = async function (value) { - session = value; - - if (session !== null) { - session.addEventListener('select', onSessionEvent); - session.addEventListener('selectstart', onSessionEvent); - session.addEventListener('selectend', onSessionEvent); - session.addEventListener('squeeze', onSessionEvent); - session.addEventListener('squeezestart', onSessionEvent); - session.addEventListener('squeezeend', onSessionEvent); - session.addEventListener('end', onSessionEnd); - session.addEventListener('inputsourceschange', onInputSourcesChange); - const attributes = gl.getContextAttributes(); - - if (attributes.xrCompatible !== true) { - await gl.makeXRCompatible(); - } - - const layerInit = { - antialias: attributes.antialias, - alpha: attributes.alpha, - depth: attributes.depth, - stencil: attributes.stencil, - framebufferScaleFactor: framebufferScaleFactor - }; // eslint-disable-next-line no-undef - - const baseLayer = new XRWebGLLayer(session, gl, layerInit); - session.updateRenderState({ - baseLayer: baseLayer - }); - referenceSpace = await session.requestReferenceSpace(referenceSpaceType); - animation.setContext(session); - animation.start(); - scope.isPresenting = true; - scope.dispatchEvent({ - type: 'sessionstart' - }); - } - }; + for (let i = 0; i < controllers.length; i++) { + inputSourcesMap.set(inputSources[i], controllers[i]); + } // Notify disconnected - function onInputSourcesChange(event) { - const inputSources = session.inputSources; // Assign inputSources to available controllers - for (let i = 0; i < controllers.length; i++) { - inputSourcesMap.set(inputSources[i], controllers[i]); - } // Notify disconnected + for (let i = 0; i < event.removed.length; i++) { + const inputSource = event.removed[i]; + const controller = inputSourcesMap.get(inputSource); + if (controller) { + controller.dispatchEvent({ + type: 'disconnected', + data: inputSource + }); + inputSourcesMap.delete(inputSource); + } + } // Notify connected - for (let i = 0; i < event.removed.length; i++) { - const inputSource = event.removed[i]; - const controller = inputSourcesMap.get(inputSource); - if (controller) { - controller.dispatchEvent({ - type: 'disconnected', - data: inputSource - }); - inputSourcesMap.delete(inputSource); + for (let i = 0; i < event.added.length; i++) { + const inputSource = event.added[i]; + const controller = inputSourcesMap.get(inputSource); + + if (controller) { + controller.dispatchEvent({ + type: 'connected', + data: inputSource + }); + } } - } // Notify connected + } // - for (let i = 0; i < event.added.length; i++) { - const inputSource = event.added[i]; - const controller = inputSourcesMap.get(inputSource); + const cameraLPos = new Vector3(); + const cameraRPos = new Vector3(); + /** + * Assumes 2 cameras that are parallel and share an X-axis, and that + * the cameras' projection and world matrices have already been set. + * And that near and far planes are identical for both cameras. + * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 + */ - if (controller) { - controller.dispatchEvent({ - type: 'connected', - data: inputSource - }); + function setProjectionFromUnion(camera, cameraL, cameraR) { + cameraLPos.setFromMatrixPosition(cameraL.matrixWorld); + cameraRPos.setFromMatrixPosition(cameraR.matrixWorld); + const ipd = cameraLPos.distanceTo(cameraRPos); + const projL = cameraL.projectionMatrix.elements; + const projR = cameraR.projectionMatrix.elements; // VR systems will have identical far and near planes, and + // most likely identical top and bottom frustum extents. + // Use the left camera for these values. + + const near = projL[14] / (projL[10] - 1); + const far = projL[14] / (projL[10] + 1); + const topFov = (projL[9] + 1) / projL[5]; + const bottomFov = (projL[9] - 1) / projL[5]; + const leftFov = (projL[8] - 1) / projL[0]; + const rightFov = (projR[8] + 1) / projR[0]; + const left = near * leftFov; + const right = near * rightFov; // Calculate the new camera's position offset from the + // left camera. xOffset should be roughly half `ipd`. + + const zOffset = ipd / (-leftFov + rightFov); + const xOffset = zOffset * -leftFov; // TODO: Better way to apply this offset? + + cameraL.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale); + camera.translateX(xOffset); + camera.translateZ(zOffset); + camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale); + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // although must now be relative to the new union camera. + + const near2 = near + zOffset; + const far2 = far + zOffset; + const left2 = left - xOffset; + const right2 = right + (ipd - xOffset); + const top2 = topFov * far / far2 * near2; + const bottom2 = bottomFov * far / far2 * near2; + camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2); + } + + function updateCamera(camera, parent) { + if (parent === null) { + camera.matrixWorld.copy(camera.matrix); + } else { + camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix); } - } - } // - - const cameraLPos = new Vector3(); - const cameraRPos = new Vector3(); - /** - * Assumes 2 cameras that are parallel and share an X-axis, and that - * the cameras' projection and world matrices have already been set. - * And that near and far planes are identical for both cameras. - * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 - */ - - function setProjectionFromUnion(camera, cameraL, cameraR) { - cameraLPos.setFromMatrixPosition(cameraL.matrixWorld); - cameraRPos.setFromMatrixPosition(cameraR.matrixWorld); - const ipd = cameraLPos.distanceTo(cameraRPos); - const projL = cameraL.projectionMatrix.elements; - const projR = cameraR.projectionMatrix.elements; // VR systems will have identical far and near planes, and - // most likely identical top and bottom frustum extents. - // Use the left camera for these values. - - const near = projL[14] / (projL[10] - 1); - const far = projL[14] / (projL[10] + 1); - const topFov = (projL[9] + 1) / projL[5]; - const bottomFov = (projL[9] - 1) / projL[5]; - const leftFov = (projL[8] - 1) / projL[0]; - const rightFov = (projR[8] + 1) / projR[0]; - const left = near * leftFov; - const right = near * rightFov; // Calculate the new camera's position offset from the - // left camera. xOffset should be roughly half `ipd`. - - const zOffset = ipd / (-leftFov + rightFov); - const xOffset = zOffset * -leftFov; // TODO: Better way to apply this offset? - - cameraL.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale); - camera.translateX(xOffset); - camera.translateZ(zOffset); - camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale); - camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); // Find the union of the frustum values of the cameras and scale - // the values so that the near plane's position does not change in world space, - // although must now be relative to the new union camera. - - const near2 = near + zOffset; - const far2 = far + zOffset; - const left2 = left - xOffset; - const right2 = right + (ipd - xOffset); - const top2 = topFov * far / far2 * near2; - const bottom2 = bottomFov * far / far2 * near2; - camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2); - } - - function updateCamera(camera, parent) { - if (parent === null) { - camera.matrixWorld.copy(camera.matrix); - } else { - camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix); + camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); } - camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); - } + this.getCamera = function (camera) { + cameraVR.near = cameraR.near = cameraL.near = camera.near; + cameraVR.far = cameraR.far = cameraL.far = camera.far; - this.getCamera = function (camera) { - cameraVR.near = cameraR.near = cameraL.near = camera.near; - cameraVR.far = cameraR.far = cameraL.far = camera.far; + if (_currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far) { + // Note that the new renderState won't apply until the next frame. See #18320 + session.updateRenderState({ + depthNear: cameraVR.near, + depthFar: cameraVR.far + }); + _currentDepthNear = cameraVR.near; + _currentDepthFar = cameraVR.far; + } - if (_currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far) { - // Note that the new renderState won't apply until the next frame. See #18320 - session.updateRenderState({ - depthNear: cameraVR.near, - depthFar: cameraVR.far - }); - _currentDepthNear = cameraVR.near; - _currentDepthFar = cameraVR.far; - } + const parent = camera.parent; + const cameras = cameraVR.cameras; + updateCamera(cameraVR, parent); - const parent = camera.parent; - const cameras = cameraVR.cameras; - updateCamera(cameraVR, parent); + for (let i = 0; i < cameras.length; i++) { + updateCamera(cameras[i], parent); + } // update camera and its children - for (let i = 0; i < cameras.length; i++) { - updateCamera(cameras[i], parent); - } // update camera and its children + camera.matrixWorld.copy(cameraVR.matrixWorld); + camera.matrix.copy(cameraVR.matrix); + camera.matrix.decompose(camera.position, camera.quaternion, camera.scale); + const children = camera.children; - camera.matrixWorld.copy(cameraVR.matrixWorld); - camera.matrix.copy(cameraVR.matrix); - camera.matrix.decompose(camera.position, camera.quaternion, camera.scale); - const children = camera.children; + for (let i = 0, l = children.length; i < l; i++) { + children[i].updateMatrixWorld(true); + } // update projection matrix for proper view frustum culling - for (let i = 0, l = children.length; i < l; i++) { - children[i].updateMatrixWorld(true); - } // update projection matrix for proper view frustum culling + if (cameras.length === 2) { + setProjectionFromUnion(cameraVR, cameraL, cameraR); + } else { + // assume single camera setup (AR) + cameraVR.projectionMatrix.copy(cameraL.projectionMatrix); + } - if (cameras.length === 2) { - setProjectionFromUnion(cameraVR, cameraL, cameraR); - } else { - // assume single camera setup (AR) - cameraVR.projectionMatrix.copy(cameraL.projectionMatrix); - } + return cameraVR; + }; // Animation Loop - return cameraVR; - }; // Animation Loop + let onAnimationFrameCallback = null; - let onAnimationFrameCallback = null; + function onAnimationFrame(time, frame) { + pose = frame.getViewerPose(referenceSpace); - function onAnimationFrame(time, frame) { - pose = frame.getViewerPose(referenceSpace); + if (pose !== null) { + const views = pose.views; + const baseLayer = session.renderState.baseLayer; + state.bindXRFramebuffer(baseLayer.framebuffer); + let cameraVRNeedsUpdate = false; // check if it's necessary to rebuild cameraVR's camera list - if (pose !== null) { - const views = pose.views; - const baseLayer = session.renderState.baseLayer; - state.bindXRFramebuffer(baseLayer.framebuffer); - let cameraVRNeedsUpdate = false; // check if it's necessary to rebuild cameraVR's camera list + if (views.length !== cameraVR.cameras.length) { + cameraVR.cameras.length = 0; + cameraVRNeedsUpdate = true; + } - if (views.length !== cameraVR.cameras.length) { - cameraVR.cameras.length = 0; - cameraVRNeedsUpdate = true; - } + for (let i = 0; i < views.length; i++) { + const view = views[i]; + const viewport = baseLayer.getViewport(view); + const camera = cameras[i]; + camera.matrix.fromArray(view.transform.matrix); + camera.projectionMatrix.fromArray(view.projectionMatrix); + camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height); - for (let i = 0; i < views.length; i++) { - const view = views[i]; - const viewport = baseLayer.getViewport(view); - const camera = cameras[i]; - camera.matrix.fromArray(view.transform.matrix); - camera.projectionMatrix.fromArray(view.projectionMatrix); - camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height); + if (i === 0) { + cameraVR.matrix.copy(camera.matrix); + } - if (i === 0) { - cameraVR.matrix.copy(camera.matrix); + if (cameraVRNeedsUpdate === true) { + cameraVR.cameras.push(camera); + } } + } // - if (cameraVRNeedsUpdate === true) { - cameraVR.cameras.push(camera); - } - } - } // + const inputSources = session.inputSources; - const inputSources = session.inputSources; + for (let i = 0; i < controllers.length; i++) { + const controller = controllers[i]; + const inputSource = inputSources[i]; + controller.update(inputSource, frame, referenceSpace); + } - for (let i = 0; i < controllers.length; i++) { - const controller = controllers[i]; - const inputSource = inputSources[i]; - controller.update(inputSource, frame, referenceSpace); + if (onAnimationFrameCallback) onAnimationFrameCallback(time, frame); } - if (onAnimationFrameCallback) onAnimationFrameCallback(time, frame); - } + const animation = new WebGLAnimation(); + animation.setAnimationLoop(onAnimationFrame); - const animation = new WebGLAnimation(); - animation.setAnimationLoop(onAnimationFrame); + this.setAnimationLoop = function (callback) { + onAnimationFrameCallback = callback; + }; - this.setAnimationLoop = function (callback) { - onAnimationFrameCallback = callback; - }; + this.dispose = function () {}; + } - this.dispose = function () {}; } - Object.assign(WebXRManager.prototype, EventDispatcher.prototype); - function WebGLMaterials(properties) { function refreshFogUniforms(uniforms, fog) { uniforms.fogColor.value.copy(fog.color); @@ -17872,6 +18104,7 @@ } } else { parameters.uniforms = programCache.getUniforms(material); + material.onBuild(parameters, _this); material.onBeforeCompile(parameters, _this); program = programCache.acquireProgram(parameters, programCacheKey); programs.set(programCacheKey, program); @@ -17935,7 +18168,7 @@ const environment = material.isMeshStandardMaterial ? scene.environment : null; const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.texture.encoding; const envMap = cubemaps.get(material.envMap || environment); - const vertexAlphas = material.vertexColors === true && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4; + const vertexAlphas = material.vertexColors === true && object.geometry && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4; const materialProperties = properties.get(material); const lights = currentRenderState.state.lights; @@ -18056,7 +18289,7 @@ // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) let size = Math.sqrt(bones.length * 4); // 4 pixels needed for 1 matrix - size = MathUtils.ceilPowerOfTwo(size); + size = ceilPowerOfTwo(size); size = Math.max(size, 4); const boneMatrices = new Float32Array(size * size * 4); // 4 floats per RGBA pixel @@ -18489,39 +18722,40 @@ Scene.prototype.isScene = true; - function InterleavedBuffer(array, stride) { - this.array = array; - this.stride = stride; - this.count = array !== undefined ? array.length / stride : 0; - this.usage = StaticDrawUsage; - this.updateRange = { - offset: 0, - count: -1 - }; - this.version = 0; - this.uuid = MathUtils.generateUUID(); - } + class InterleavedBuffer { + constructor(array, stride) { + this.array = array; + this.stride = stride; + this.count = array !== undefined ? array.length / stride : 0; + this.usage = StaticDrawUsage; + this.updateRange = { + offset: 0, + count: -1 + }; + this.version = 0; + this.uuid = generateUUID(); - Object.defineProperty(InterleavedBuffer.prototype, 'needsUpdate', { - set: function (value) { + this.onUploadCallback = function () {}; + } + + set needsUpdate(value) { if (value === true) this.version++; } - }); - Object.assign(InterleavedBuffer.prototype, { - isInterleavedBuffer: true, - onUploadCallback: function () {}, - setUsage: function (value) { + + setUsage(value) { this.usage = value; return this; - }, - copy: function (source) { + } + + copy(source) { this.array = new source.array.constructor(source.array); this.count = source.count; this.stride = source.stride; this.usage = source.usage; return this; - }, - copyAt: function (index1, attribute, index2) { + } + + copyAt(index1, attribute, index2) { index1 *= this.stride; index2 *= attribute.stride; @@ -18530,18 +18764,20 @@ } return this; - }, - set: function (value, offset = 0) { + } + + set(value, offset = 0) { this.array.set(value, offset); return this; - }, - clone: function (data) { + } + + clone(data) { if (data.arrayBuffers === undefined) { data.arrayBuffers = {}; } if (this.array.buffer._uuid === undefined) { - this.array.buffer._uuid = MathUtils.generateUUID(); + this.array.buffer._uuid = generateUUID(); } if (data.arrayBuffers[this.array.buffer._uuid] === undefined) { @@ -18552,19 +18788,21 @@ const ib = new InterleavedBuffer(array, this.stride); ib.setUsage(this.usage); return ib; - }, - onUpload: function (callback) { + } + + onUpload(callback) { this.onUploadCallback = callback; return this; - }, - toJSON: function (data) { + } + + toJSON(data) { if (data.arrayBuffers === undefined) { data.arrayBuffers = {}; } // generate UUID for array buffer if necessary if (this.array.buffer._uuid === undefined) { - this.array.buffer._uuid = MathUtils.generateUUID(); + this.array.buffer._uuid = generateUUID(); } if (data.arrayBuffers[this.array.buffer._uuid] === undefined) { @@ -18579,38 +18817,35 @@ stride: this.stride }; } - }); - const _vector$6 = new Vector3(); - - function InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, normalized) { - this.name = ''; - this.data = interleavedBuffer; - this.itemSize = itemSize; - this.offset = offset; - this.normalized = normalized === true; } - Object.defineProperties(InterleavedBufferAttribute.prototype, { - count: { - get: function () { - return this.data.count; - } - }, - array: { - get: function () { - return this.data.array; - } - }, - needsUpdate: { - set: function (value) { - this.data.needsUpdate = value; - } + InterleavedBuffer.prototype.isInterleavedBuffer = true; + + const _vector$6 = new /*@__PURE__*/Vector3(); + + class InterleavedBufferAttribute { + constructor(interleavedBuffer, itemSize, offset, normalized) { + this.name = ''; + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; + this.normalized = normalized === true; } - }); - Object.assign(InterleavedBufferAttribute.prototype, { - isInterleavedBufferAttribute: true, - applyMatrix4: function (m) { + + get count() { + return this.data.count; + } + + get array() { + return this.data.array; + } + + set needsUpdate(value) { + this.data.needsUpdate = value; + } + + applyMatrix4(m) { for (let i = 0, l = this.data.count; i < l; i++) { _vector$6.x = this.getX(i); _vector$6.y = this.getY(i); @@ -18622,8 +18857,9 @@ } return this; - }, - applyNormalMatrix: function (m) { + } + + applyNormalMatrix(m) { for (let i = 0, l = this.count; i < l; i++) { _vector$6.x = this.getX(i); _vector$6.y = this.getY(i); @@ -18635,8 +18871,9 @@ } return this; - }, - transformDirection: function (m) { + } + + transformDirection(m) { for (let i = 0, l = this.count; i < l; i++) { _vector$6.x = this.getX(i); _vector$6.y = this.getY(i); @@ -18648,57 +18885,69 @@ } return this; - }, - setX: function (index, x) { + } + + setX(index, x) { this.data.array[index * this.data.stride + this.offset] = x; return this; - }, - setY: function (index, y) { + } + + setY(index, y) { this.data.array[index * this.data.stride + this.offset + 1] = y; return this; - }, - setZ: function (index, z) { + } + + setZ(index, z) { this.data.array[index * this.data.stride + this.offset + 2] = z; return this; - }, - setW: function (index, w) { + } + + setW(index, w) { this.data.array[index * this.data.stride + this.offset + 3] = w; return this; - }, - getX: function (index) { + } + + getX(index) { return this.data.array[index * this.data.stride + this.offset]; - }, - getY: function (index) { + } + + getY(index) { return this.data.array[index * this.data.stride + this.offset + 1]; - }, - getZ: function (index) { + } + + getZ(index) { return this.data.array[index * this.data.stride + this.offset + 2]; - }, - getW: function (index) { + } + + getW(index) { return this.data.array[index * this.data.stride + this.offset + 3]; - }, - setXY: function (index, x, y) { + } + + setXY(index, x, y) { index = index * this.data.stride + this.offset; this.data.array[index + 0] = x; this.data.array[index + 1] = y; return this; - }, - setXYZ: function (index, x, y, z) { + } + + setXYZ(index, x, y, z) { index = index * this.data.stride + this.offset; this.data.array[index + 0] = x; this.data.array[index + 1] = y; this.data.array[index + 2] = z; return this; - }, - setXYZW: function (index, x, y, z, w) { + } + + setXYZW(index, x, y, z, w) { index = index * this.data.stride + this.offset; this.data.array[index + 0] = x; this.data.array[index + 1] = y; this.data.array[index + 2] = z; this.data.array[index + 3] = w; return this; - }, - clone: function (data) { + } + + clone(data) { if (data === undefined) { console.log('THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.'); const array = []; @@ -18723,8 +18972,9 @@ return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid], this.itemSize, this.offset, this.normalized); } - }, - toJSON: function (data) { + } + + toJSON(data) { if (data === undefined) { console.log('THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.'); const array = []; @@ -18763,7 +19013,10 @@ }; } } - }); + + } + + InterleavedBufferAttribute.prototype.isInterleavedBufferAttribute = true; /** * parameters = { @@ -19077,36 +19330,35 @@ } - const _basePosition = new Vector3(); + const _basePosition = /*@__PURE__*/new Vector3(); - const _skinIndex = new Vector4(); + const _skinIndex = /*@__PURE__*/new Vector4(); - const _skinWeight = new Vector4(); + const _skinWeight = /*@__PURE__*/new Vector4(); - const _vector$5 = new Vector3(); + const _vector$5 = /*@__PURE__*/new Vector3(); - const _matrix = new Matrix4(); + const _matrix = /*@__PURE__*/new Matrix4(); - function SkinnedMesh(geometry, material) { - Mesh.call(this, geometry, material); - this.type = 'SkinnedMesh'; - this.bindMode = 'attached'; - this.bindMatrix = new Matrix4(); - this.bindMatrixInverse = new Matrix4(); - } + class SkinnedMesh extends Mesh { + constructor(geometry, material) { + super(geometry, material); + this.type = 'SkinnedMesh'; + this.bindMode = 'attached'; + this.bindMatrix = new Matrix4(); + this.bindMatrixInverse = new Matrix4(); + } - SkinnedMesh.prototype = Object.assign(Object.create(Mesh.prototype), { - constructor: SkinnedMesh, - isSkinnedMesh: true, - copy: function (source) { - Mesh.prototype.copy.call(this, source); + copy(source) { + super.copy(source); this.bindMode = source.bindMode; this.bindMatrix.copy(source.bindMatrix); this.bindMatrixInverse.copy(source.bindMatrixInverse); this.skeleton = source.skeleton; return this; - }, - bind: function (skeleton, bindMatrix) { + } + + bind(skeleton, bindMatrix) { this.skeleton = skeleton; if (bindMatrix === undefined) { @@ -19117,11 +19369,13 @@ this.bindMatrix.copy(bindMatrix); this.bindMatrixInverse.copy(bindMatrix).invert(); - }, - pose: function () { + } + + pose() { this.skeleton.pose(); - }, - normalizeSkinWeights: function () { + } + + normalizeSkinWeights() { const vector = new Vector4(); const skinWeight = this.geometry.attributes.skinWeight; @@ -19140,9 +19394,10 @@ skinWeight.setXYZW(i, vector.x, vector.y, vector.z, vector.w); } - }, - updateMatrixWorld: function (force) { - Mesh.prototype.updateMatrixWorld.call(this, force); + } + + updateMatrixWorld(force) { + super.updateMatrixWorld(force); if (this.bindMode === 'attached') { this.bindMatrixInverse.copy(this.matrixWorld).invert(); @@ -19151,8 +19406,9 @@ } else { console.warn('THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode); } - }, - boneTransform: function (index, target) { + } + + boneTransform(index, target) { const skeleton = this.skeleton; const geometry = this.geometry; @@ -19178,17 +19434,20 @@ return target.applyMatrix4(this.bindMatrixInverse); } - }); - function Bone() { - Object3D.call(this); - this.type = 'Bone'; } - Bone.prototype = Object.assign(Object.create(Object3D.prototype), { - constructor: Bone, - isBone: true - }); + SkinnedMesh.prototype.isSkinnedMesh = true; + + class Bone extends Object3D { + constructor() { + super(); + this.type = 'Bone'; + } + + } + + Bone.prototype.isBone = true; const _offsetMatrix = /*@__PURE__*/new Matrix4(); @@ -19196,7 +19455,7 @@ class Skeleton { constructor(bones = [], boneInverses = []) { - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.bones = bones.slice(0); this.boneInverses = boneInverses; this.boneMatrices = null; @@ -19356,39 +19615,40 @@ } - const _instanceLocalMatrix = new Matrix4(); + const _instanceLocalMatrix = /*@__PURE__*/new Matrix4(); - const _instanceWorldMatrix = new Matrix4(); + const _instanceWorldMatrix = /*@__PURE__*/new Matrix4(); const _instanceIntersects = []; - const _mesh = new Mesh(); + const _mesh = /*@__PURE__*/new Mesh(); - function InstancedMesh(geometry, material, count) { - Mesh.call(this, geometry, material); - this.instanceMatrix = new BufferAttribute(new Float32Array(count * 16), 16); - this.instanceColor = null; - this.count = count; - this.frustumCulled = false; - } + class InstancedMesh extends Mesh { + constructor(geometry, material, count) { + super(geometry, material); + this.instanceMatrix = new BufferAttribute(new Float32Array(count * 16), 16); + this.instanceColor = null; + this.count = count; + this.frustumCulled = false; + } - InstancedMesh.prototype = Object.assign(Object.create(Mesh.prototype), { - constructor: InstancedMesh, - isInstancedMesh: true, - copy: function (source) { - Mesh.prototype.copy.call(this, source); + copy(source) { + super.copy(source); this.instanceMatrix.copy(source.instanceMatrix); if (source.instanceColor !== null) this.instanceColor = source.instanceColor.clone(); this.count = source.count; return this; - }, - getColorAt: function (index, color) { + } + + getColorAt(index, color) { color.fromArray(this.instanceColor.array, index * 3); - }, - getMatrixAt: function (index, matrix) { + } + + getMatrixAt(index, matrix) { matrix.fromArray(this.instanceMatrix.array, index * 16); - }, - raycast: function (raycaster, intersects) { + } + + raycast(raycaster, intersects) { const matrixWorld = this.matrixWorld; const raycastTimes = this.count; _mesh.geometry = this.geometry; @@ -19416,24 +19676,31 @@ _instanceIntersects.length = 0; } - }, - setColorAt: function (index, color) { + } + + setColorAt(index, color) { if (this.instanceColor === null) { this.instanceColor = new BufferAttribute(new Float32Array(this.count * 3), 3); } color.toArray(this.instanceColor.array, index * 3); - }, - setMatrixAt: function (index, matrix) { + } + + setMatrixAt(index, matrix) { matrix.toArray(this.instanceMatrix.array, index * 16); - }, - updateMorphTargets: function () {}, - dispose: function () { + } + + updateMorphTargets() {} + + dispose() { this.dispatchEvent({ type: 'dispose' }); } - }); + + } + + InstancedMesh.prototype.isInstancedMesh = true; /** * parameters = { @@ -19472,34 +19739,33 @@ LineBasicMaterial.prototype.isLineBasicMaterial = true; - const _start$1 = new Vector3(); + const _start$1 = /*@__PURE__*/new Vector3(); - const _end$1 = new Vector3(); + const _end$1 = /*@__PURE__*/new Vector3(); - const _inverseMatrix$1 = new Matrix4(); + const _inverseMatrix$1 = /*@__PURE__*/new Matrix4(); - const _ray$1 = new Ray(); + const _ray$1 = /*@__PURE__*/new Ray(); - const _sphere$1 = new Sphere(); + const _sphere$1 = /*@__PURE__*/new Sphere(); - function Line(geometry = new BufferGeometry(), material = new LineBasicMaterial()) { - Object3D.call(this); - this.type = 'Line'; - this.geometry = geometry; - this.material = material; - this.updateMorphTargets(); - } + class Line extends Object3D { + constructor(geometry = new BufferGeometry(), material = new LineBasicMaterial()) { + super(); + this.type = 'Line'; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } - Line.prototype = Object.assign(Object.create(Object3D.prototype), { - constructor: Line, - isLine: true, - copy: function (source) { - Object3D.prototype.copy.call(this, source); + copy(source) { + super.copy(source); this.material = source.material; this.geometry = source.geometry; return this; - }, - computeLineDistances: function () { + } + + computeLineDistances() { const geometry = this.geometry; if (geometry.isBufferGeometry) { @@ -19526,8 +19792,9 @@ } return this; - }, - raycast: function (raycaster, intersects) { + } + + raycast(raycaster, intersects) { const geometry = this.geometry; const matrixWorld = this.matrixWorld; const threshold = raycaster.params.Line.threshold; @@ -19617,8 +19884,9 @@ } else if (geometry.isGeometry) { console.error('THREE.Line.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); } - }, - updateMorphTargets: function () { + } + + updateMorphTargets() { const geometry = this.geometry; if (geometry.isBufferGeometry) { @@ -19647,21 +19915,22 @@ } } } - }); - const _start = new Vector3(); + } + + Line.prototype.isLine = true; - const _end = new Vector3(); + const _start = /*@__PURE__*/new Vector3(); - function LineSegments(geometry, material) { - Line.call(this, geometry, material); - this.type = 'LineSegments'; - } + const _end = /*@__PURE__*/new Vector3(); + + class LineSegments extends Line { + constructor(geometry, material) { + super(geometry, material); + this.type = 'LineSegments'; + } - LineSegments.prototype = Object.assign(Object.create(Line.prototype), { - constructor: LineSegments, - isLineSegments: true, - computeLineDistances: function () { + computeLineDistances() { const geometry = this.geometry; if (geometry.isBufferGeometry) { @@ -19689,7 +19958,10 @@ return this; } - }); + + } + + LineSegments.prototype.isLineSegments = true; class LineLoop extends Line { constructor(geometry, material) { @@ -19743,32 +20015,31 @@ PointsMaterial.prototype.isPointsMaterial = true; - const _inverseMatrix = new Matrix4(); + const _inverseMatrix = /*@__PURE__*/new Matrix4(); - const _ray = new Ray(); + const _ray = /*@__PURE__*/new Ray(); - const _sphere = new Sphere(); + const _sphere = /*@__PURE__*/new Sphere(); - const _position$2 = new Vector3(); + const _position$2 = /*@__PURE__*/new Vector3(); - function Points(geometry = new BufferGeometry(), material = new PointsMaterial()) { - Object3D.call(this); - this.type = 'Points'; - this.geometry = geometry; - this.material = material; - this.updateMorphTargets(); - } + class Points extends Object3D { + constructor(geometry = new BufferGeometry(), material = new PointsMaterial()) { + super(); + this.type = 'Points'; + this.geometry = geometry; + this.material = material; + this.updateMorphTargets(); + } - Points.prototype = Object.assign(Object.create(Object3D.prototype), { - constructor: Points, - isPoints: true, - copy: function (source) { - Object3D.prototype.copy.call(this, source); + copy(source) { + super.copy(source); this.material = source.material; this.geometry = source.geometry; return this; - }, - raycast: function (raycaster, intersects) { + } + + raycast(raycaster, intersects) { const geometry = this.geometry; const matrixWorld = this.matrixWorld; const threshold = raycaster.params.Points.threshold; @@ -19819,8 +20090,9 @@ } else { console.error('THREE.Points.raycast() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); } - }, - updateMorphTargets: function () { + } + + updateMorphTargets() { const geometry = this.geometry; if (geometry.isBufferGeometry) { @@ -19849,7 +20121,10 @@ } } } - }); + + } + + Points.prototype.isPoints = true; function testPoint(point, index, localThresholdSq, matrixWorld, raycaster, intersects, object) { const rayPointDistanceSq = _ray.distanceSqToPoint(point); @@ -20436,7 +20711,7 @@ const precisionPoints = 4; const precision = Math.pow(10, precisionPoints); - const thresholdDot = Math.cos(MathUtils.DEG2RAD * thresholdAngle); + const thresholdDot = Math.cos(DEG2RAD * thresholdAngle); const indexAttr = geometry.getIndex(); const positionAttr = geometry.getAttribute('position'); const indexCount = indexAttr ? indexAttr.count : positionAttr.count; @@ -21117,9 +21392,9 @@ return sum; } - const ShapeUtils = { + class ShapeUtils { // calculate area of the contour polygon - area: function (contour) { + static area(contour) { const n = contour.length; let a = 0.0; @@ -21128,11 +21403,13 @@ } return a * 0.5; - }, - isClockWise: function (pts) { + } + + static isClockWise(pts) { return ShapeUtils.area(pts) < 0; - }, - triangulateShape: function (contour, holes) { + } + + static triangulateShape(contour, holes) { const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] const holeIndices = []; // array of hole indices @@ -21160,7 +21437,8 @@ return faces; } - }; + + } function removeDupEndPts(points) { const l = points.length; @@ -21711,7 +21989,7 @@ }; segments = Math.floor(segments); // clamp phiLength so it's in range of [ 0, 2PI ] - phiLength = MathUtils.clamp(phiLength, 0, Math.PI * 2); // buffers + phiLength = clamp(phiLength, 0, Math.PI * 2); // buffers const indices = []; const vertices = []; @@ -21809,89 +22087,89 @@ * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html */ - function ParametricGeometry(func, slices, stacks) { - BufferGeometry.call(this); - this.type = 'ParametricGeometry'; - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; // buffers - - const indices = []; - const vertices = []; - const normals = []; - const uvs = []; - const EPS = 0.00001; - const normal = new Vector3(); - const p0 = new Vector3(), - p1 = new Vector3(); - const pu = new Vector3(), - pv = new Vector3(); - - if (func.length < 3) { - console.error('THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.'); - } // generate vertices, normals and uvs - - - const sliceCount = slices + 1; - - for (let i = 0; i <= stacks; i++) { - const v = i / stacks; - - for (let j = 0; j <= slices; j++) { - const u = j / slices; // vertex - - func(u, v, p0); - vertices.push(p0.x, p0.y, p0.z); // normal - // approximate tangent vectors via finite differences - - if (u - EPS >= 0) { - func(u - EPS, v, p1); - pu.subVectors(p0, p1); - } else { - func(u + EPS, v, p1); - pu.subVectors(p1, p0); - } + class ParametricGeometry extends BufferGeometry { + constructor(func, slices, stacks) { + super(); + this.type = 'ParametricGeometry'; + this.parameters = { + func: func, + slices: slices, + stacks: stacks + }; // buffers - if (v - EPS >= 0) { - func(u, v - EPS, p1); - pv.subVectors(p0, p1); - } else { - func(u, v + EPS, p1); - pv.subVectors(p1, p0); - } // cross product of tangent vectors returns surface normal + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + const EPS = 0.00001; + const normal = new Vector3(); + const p0 = new Vector3(), + p1 = new Vector3(); + const pu = new Vector3(), + pv = new Vector3(); + if (func.length < 3) { + console.error('THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.'); + } // generate vertices, normals and uvs - normal.crossVectors(pu, pv).normalize(); - normals.push(normal.x, normal.y, normal.z); // uv - uvs.push(u, v); - } - } // generate indices + const sliceCount = slices + 1; + for (let i = 0; i <= stacks; i++) { + const v = i / stacks; - for (let i = 0; i < stacks; i++) { - for (let j = 0; j < slices; j++) { - const a = i * sliceCount + j; - const b = i * sliceCount + j + 1; - const c = (i + 1) * sliceCount + j + 1; - const d = (i + 1) * sliceCount + j; // faces one and two + for (let j = 0; j <= slices; j++) { + const u = j / slices; // vertex - indices.push(a, b, d); - indices.push(b, c, d); - } - } // build geometry + func(u, v, p0); + vertices.push(p0.x, p0.y, p0.z); // normal + // approximate tangent vectors via finite differences + if (u - EPS >= 0) { + func(u - EPS, v, p1); + pu.subVectors(p0, p1); + } else { + func(u + EPS, v, p1); + pu.subVectors(p1, p0); + } + + if (v - EPS >= 0) { + func(u, v - EPS, p1); + pv.subVectors(p0, p1); + } else { + func(u, v + EPS, p1); + pv.subVectors(p1, p0); + } // cross product of tangent vectors returns surface normal - this.setIndex(indices); - this.setAttribute('position', new Float32BufferAttribute(vertices, 3)); - this.setAttribute('normal', new Float32BufferAttribute(normals, 3)); - this.setAttribute('uv', new Float32BufferAttribute(uvs, 2)); - } - ParametricGeometry.prototype = Object.create(BufferGeometry.prototype); - ParametricGeometry.prototype.constructor = ParametricGeometry; + normal.crossVectors(pu, pv).normalize(); + normals.push(normal.x, normal.y, normal.z); // uv + + uvs.push(u, v); + } + } // generate indices + + + for (let i = 0; i < stacks; i++) { + for (let j = 0; j < slices; j++) { + const a = i * sliceCount + j; + const b = i * sliceCount + j + 1; + const c = (i + 1) * sliceCount + j + 1; + const d = (i + 1) * sliceCount + j; // faces one and two + + indices.push(a, b, d); + indices.push(b, c, d); + } + } // build geometry + + + this.setIndex(indices); + this.setAttribute('position', new Float32BufferAttribute(vertices, 3)); + this.setAttribute('normal', new Float32BufferAttribute(normals, 3)); + this.setAttribute('uv', new Float32BufferAttribute(uvs, 2)); + } + + } class RingGeometry extends BufferGeometry { constructor(innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) { @@ -22690,95 +22968,96 @@ * } */ - function MeshStandardMaterial(parameters) { - Material.call(this); - this.defines = { - 'STANDARD': '' - }; - this.type = 'MeshStandardMaterial'; - this.color = new Color(0xffffff); // diffuse - - this.roughness = 1.0; - this.metalness = 0.0; - this.map = null; - this.lightMap = null; - this.lightMapIntensity = 1.0; - this.aoMap = null; - this.aoMapIntensity = 1.0; - this.emissive = new Color(0x000000); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; - this.bumpMap = null; - this.bumpScale = 1; - this.normalMap = null; - this.normalMapType = TangentSpaceNormalMap; - this.normalScale = new Vector2(1, 1); - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - this.roughnessMap = null; - this.metalnessMap = null; - this.alphaMap = null; - this.envMap = null; - this.envMapIntensity = 1.0; - this.refractionRatio = 0.98; - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; - this.flatShading = false; - this.vertexTangents = false; - this.setValues(parameters); - } - - MeshStandardMaterial.prototype = Object.create(Material.prototype); - MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; - MeshStandardMaterial.prototype.isMeshStandardMaterial = true; + class MeshStandardMaterial extends Material { + constructor(parameters) { + super(); + this.defines = { + 'STANDARD': '' + }; + this.type = 'MeshStandardMaterial'; + this.color = new Color(0xffffff); // diffuse - MeshStandardMaterial.prototype.copy = function (source) { - Material.prototype.copy.call(this, source); - this.defines = { - 'STANDARD': '' - }; - this.color.copy(source.color); - this.roughness = source.roughness; - this.metalness = source.metalness; - this.map = source.map; - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; - this.emissive.copy(source.emissive); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; - this.normalMap = source.normalMap; - this.normalMapType = source.normalMapType; - this.normalScale.copy(source.normalScale); - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - this.roughnessMap = source.roughnessMap; - this.metalnessMap = source.metalnessMap; - this.alphaMap = source.alphaMap; - this.envMap = source.envMap; - this.envMapIntensity = source.envMapIntensity; - this.refractionRatio = source.refractionRatio; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - this.flatShading = source.flatShading; - this.vertexTangents = source.vertexTangents; - return this; - }; + this.roughness = 1.0; + this.metalness = 0.0; + this.map = null; + this.lightMap = null; + this.lightMapIntensity = 1.0; + this.aoMap = null; + this.aoMapIntensity = 1.0; + this.emissive = new Color(0x000000); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; + this.bumpMap = null; + this.bumpScale = 1; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2(1, 1); + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + this.roughnessMap = null; + this.metalnessMap = null; + this.alphaMap = null; + this.envMap = null; + this.envMapIntensity = 1.0; + this.refractionRatio = 0.98; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + this.skinning = false; + this.morphTargets = false; + this.morphNormals = false; + this.flatShading = false; + this.vertexTangents = false; + this.setValues(parameters); + } + + copy(source) { + super.copy(source); + this.defines = { + 'STANDARD': '' + }; + this.color.copy(source.color); + this.roughness = source.roughness; + this.metalness = source.metalness; + this.map = source.map; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + this.emissive.copy(source.emissive); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy(source.normalScale); + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + this.roughnessMap = source.roughnessMap; + this.metalnessMap = source.metalnessMap; + this.alphaMap = source.alphaMap; + this.envMap = source.envMap; + this.envMapIntensity = source.envMapIntensity; + this.refractionRatio = source.refractionRatio; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; + this.morphNormals = source.morphNormals; + this.flatShading = source.flatShading; + this.vertexTangents = source.vertexTangents; + return this; + } + + } + + MeshStandardMaterial.prototype.isMeshStandardMaterial = true; /** * parameters = { @@ -22799,64 +23078,65 @@ * } */ - function MeshPhysicalMaterial(parameters) { - MeshStandardMaterial.call(this); - this.defines = { - 'STANDARD': '', - 'PHYSICAL': '' - }; - this.type = 'MeshPhysicalMaterial'; - this.clearcoat = 0.0; - this.clearcoatMap = null; - this.clearcoatRoughness = 0.0; - this.clearcoatRoughnessMap = null; - this.clearcoatNormalScale = new Vector2(1, 1); - this.clearcoatNormalMap = null; - this.reflectivity = 0.5; // maps to F0 = 0.04 - - Object.defineProperty(this, 'ior', { - get: function () { - return (1 + 0.4 * this.reflectivity) / (1 - 0.4 * this.reflectivity); - }, - set: function (ior) { - this.reflectivity = MathUtils.clamp(2.5 * (ior - 1) / (ior + 1), 0, 1); - } - }); - this.sheen = null; // null will disable sheen bsdf + class MeshPhysicalMaterial extends MeshStandardMaterial { + constructor(parameters) { + super(); + this.defines = { + 'STANDARD': '', + 'PHYSICAL': '' + }; + this.type = 'MeshPhysicalMaterial'; + this.clearcoat = 0.0; + this.clearcoatMap = null; + this.clearcoatRoughness = 0.0; + this.clearcoatRoughnessMap = null; + this.clearcoatNormalScale = new Vector2(1, 1); + this.clearcoatNormalMap = null; + this.reflectivity = 0.5; // maps to F0 = 0.04 + + Object.defineProperty(this, 'ior', { + get: function () { + return (1 + 0.4 * this.reflectivity) / (1 - 0.4 * this.reflectivity); + }, + set: function (ior) { + this.reflectivity = clamp(2.5 * (ior - 1) / (ior + 1), 0, 1); + } + }); + this.sheen = null; // null will disable sheen bsdf - this.transmission = 0.0; - this.transmissionMap = null; - this.setValues(parameters); - } + this.transmission = 0.0; + this.transmissionMap = null; + this.setValues(parameters); + } - MeshPhysicalMaterial.prototype = Object.create(MeshStandardMaterial.prototype); - MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; - MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; + copy(source) { + super.copy(source); + this.defines = { + 'STANDARD': '', + 'PHYSICAL': '' + }; + this.clearcoat = source.clearcoat; + this.clearcoatMap = source.clearcoatMap; + this.clearcoatRoughness = source.clearcoatRoughness; + this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; + this.clearcoatNormalMap = source.clearcoatNormalMap; + this.clearcoatNormalScale.copy(source.clearcoatNormalScale); + this.reflectivity = source.reflectivity; - MeshPhysicalMaterial.prototype.copy = function (source) { - MeshStandardMaterial.prototype.copy.call(this, source); - this.defines = { - 'STANDARD': '', - 'PHYSICAL': '' - }; - this.clearcoat = source.clearcoat; - this.clearcoatMap = source.clearcoatMap; - this.clearcoatRoughness = source.clearcoatRoughness; - this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; - this.clearcoatNormalMap = source.clearcoatNormalMap; - this.clearcoatNormalScale.copy(source.clearcoatNormalScale); - this.reflectivity = source.reflectivity; - - if (source.sheen) { - this.sheen = (this.sheen || new Color()).copy(source.sheen); - } else { - this.sheen = null; + if (source.sheen) { + this.sheen = (this.sheen || new Color()).copy(source.sheen); + } else { + this.sheen = null; + } + + this.transmission = source.transmission; + this.transmissionMap = source.transmissionMap; + return this; } - this.transmission = source.transmission; - this.transmissionMap = source.transmissionMap; - return this; - }; + } + + MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; /** * parameters = { @@ -23661,16 +23941,18 @@ * http://www.oodesign.com/template-method-pattern.html * */ - function Interpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) { - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; - this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor(sampleSize); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; - } - - Object.assign(Interpolant.prototype, { - evaluate: function (t) { + class Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; + this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor(sampleSize); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; + this.settings = null; + this.DefaultSettings_ = {}; + } + + evaluate(t) { const pp = this.parameterPositions; let i1 = this._cachedIndex, t1 = pp[i1], @@ -23786,16 +24068,13 @@ return this.interpolate_(i1, t0, t, t1); - }, - settings: null, - // optional, subclass-specific settings structure - // Note: The indirection allows central control of many interpolants. - // --- Protected interface - DefaultSettings_: {}, - getSettings_: function () { + } + + getSettings_() { return this.settings || this.DefaultSettings_; - }, - copySampleValue_: function (index) { + } + + copySampleValue_(index) { // copies a sample value to the result buffer const result = this.resultBuffer, values = this.sampleValues, @@ -23807,25 +24086,25 @@ } return result; - }, - // Template methods for derived classes: - interpolate_: function () + } // Template methods for derived classes: + + + interpolate_() /* i1, t0, t, t1 */ { throw new Error('call to abstract method'); // implementations shall return this.resultBuffer - }, - intervalChanged_: function () + } + + intervalChanged_() /* i1, t0, t1 */ {// empty } - }); // DECLARE ALIAS AFTER assign prototype - Object.assign(Interpolant.prototype, { - //( 0, t, t0 ), returns this.resultBuffer - beforeStart_: Interpolant.prototype.copySampleValue_, - //( N-1, tN-1, t ), returns this.resultBuffer - afterEnd_: Interpolant.prototype.copySampleValue_ - }); + } // ALIAS DEFINITIONS + + + Interpolant.prototype.beforeStart_ = Interpolant.prototype.copySampleValue_; + Interpolant.prototype.afterEnd_ = Interpolant.prototype.copySampleValue_; /** * Fast and simple cubic spline interpolant. @@ -23835,21 +24114,20 @@ * over their parameter interval. */ - function CubicInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) { - Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer); - this._weightPrev = -0; - this._offsetPrev = -0; - this._weightNext = -0; - this._offsetNext = -0; - } + class CubicInterpolant extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + this._weightPrev = -0; + this._offsetPrev = -0; + this._weightNext = -0; + this._offsetNext = -0; + this.DefaultSettings_ = { + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding + }; + } - CubicInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), { - constructor: CubicInterpolant, - DefaultSettings_: { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - }, - intervalChanged_: function (i1, t0, t1) { + intervalChanged_(i1, t0, t1) { const pp = this.parameterPositions; let iPrev = i1 - 2, iNext = i1 + 1, @@ -23906,8 +24184,9 @@ this._weightNext = halfDt / (tNext - t1); this._offsetPrev = iPrev * stride; this._offsetNext = iNext * stride; - }, - interpolate_: function (i1, t0, t, t1) { + } + + interpolate_(i1, t0, t, t1) { const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, @@ -23932,15 +24211,15 @@ return result; } - }); - function LinearInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) { - Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer); } - LinearInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), { - constructor: LinearInterpolant, - interpolate_: function (i1, t0, t, t1) { + class LinearInterpolant extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } + + interpolate_(i1, t0, t, t1) { const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, @@ -23955,7 +24234,8 @@ return result; } - }); + + } /** * @@ -23963,18 +24243,18 @@ * the parameter. */ - function DiscreteInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) { - Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer); - } + class DiscreteInterpolant extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } - DiscreteInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), { - constructor: DiscreteInterpolant, - interpolate_: function (i1 + interpolate_(i1 /*, t0, t, t1 */ ) { return this.copySampleValue_(i1 - 1); } - }); + + } class KeyframeTrack { constructor(name, times, values, interpolation) { @@ -24316,13 +24596,12 @@ * Spherical linear unit quaternion interpolant. */ - function QuaternionLinearInterpolant(parameterPositions, sampleValues, sampleSize, resultBuffer) { - Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer); - } + class QuaternionLinearInterpolant extends Interpolant { + constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { + super(parameterPositions, sampleValues, sampleSize, resultBuffer); + } - QuaternionLinearInterpolant.prototype = Object.assign(Object.create(Interpolant.prototype), { - constructor: QuaternionLinearInterpolant, - interpolate_: function (i1, t0, t, t1) { + interpolate_(i1, t0, t, t1) { const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, @@ -24335,7 +24614,8 @@ return result; } - }); + + } /** * A Track of quaternion keyframe values. @@ -24379,7 +24659,7 @@ this.tracks = tracks; this.duration = duration; this.blendMode = blendMode; - this.uuid = MathUtils.generateUUID(); // this means it should figure out its duration by scanning the tracks + this.uuid = generateUUID(); // this means it should figure out its duration by scanning the tracks if (this.duration < 0) { this.resetDuration(); @@ -24704,152 +24984,162 @@ } }; - function LoadingManager(onLoad, onProgress, onError) { - const scope = this; - let isLoading = false; - let itemsLoaded = 0; - let itemsTotal = 0; - let urlModifier = undefined; - const handlers = []; // Refer to #5689 for the reason why we don't set .onStart - // in the constructor - - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; - - this.itemStart = function (url) { - itemsTotal++; - - if (isLoading === false) { - if (scope.onStart !== undefined) { - scope.onStart(url, itemsLoaded, itemsTotal); + class LoadingManager { + constructor(onLoad, onProgress, onError) { + const scope = this; + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; // Refer to #5689 for the reason why we don't set .onStart + // in the constructor + + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; + + this.itemStart = function (url) { + itemsTotal++; + + if (isLoading === false) { + if (scope.onStart !== undefined) { + scope.onStart(url, itemsLoaded, itemsTotal); + } } - } - isLoading = true; - }; + isLoading = true; + }; - this.itemEnd = function (url) { - itemsLoaded++; + this.itemEnd = function (url) { + itemsLoaded++; - if (scope.onProgress !== undefined) { - scope.onProgress(url, itemsLoaded, itemsTotal); - } + if (scope.onProgress !== undefined) { + scope.onProgress(url, itemsLoaded, itemsTotal); + } - if (itemsLoaded === itemsTotal) { - isLoading = false; + if (itemsLoaded === itemsTotal) { + isLoading = false; - if (scope.onLoad !== undefined) { - scope.onLoad(); + if (scope.onLoad !== undefined) { + scope.onLoad(); + } } - } - }; + }; - this.itemError = function (url) { - if (scope.onError !== undefined) { - scope.onError(url); - } - }; + this.itemError = function (url) { + if (scope.onError !== undefined) { + scope.onError(url); + } + }; - this.resolveURL = function (url) { - if (urlModifier) { - return urlModifier(url); - } + this.resolveURL = function (url) { + if (urlModifier) { + return urlModifier(url); + } - return url; - }; + return url; + }; - this.setURLModifier = function (transform) { - urlModifier = transform; - return this; - }; + this.setURLModifier = function (transform) { + urlModifier = transform; + return this; + }; - this.addHandler = function (regex, loader) { - handlers.push(regex, loader); - return this; - }; + this.addHandler = function (regex, loader) { + handlers.push(regex, loader); + return this; + }; - this.removeHandler = function (regex) { - const index = handlers.indexOf(regex); + this.removeHandler = function (regex) { + const index = handlers.indexOf(regex); - if (index !== -1) { - handlers.splice(index, 2); - } + if (index !== -1) { + handlers.splice(index, 2); + } - return this; - }; + return this; + }; - this.getHandler = function (file) { - for (let i = 0, l = handlers.length; i < l; i += 2) { - const regex = handlers[i]; - const loader = handlers[i + 1]; - if (regex.global) regex.lastIndex = 0; // see #17920 + this.getHandler = function (file) { + for (let i = 0, l = handlers.length; i < l; i += 2) { + const regex = handlers[i]; + const loader = handlers[i + 1]; + if (regex.global) regex.lastIndex = 0; // see #17920 - if (regex.test(file)) { - return loader; + if (regex.test(file)) { + return loader; + } } - } - return null; - }; + return null; + }; + } + } const DefaultLoadingManager = new LoadingManager(); - function Loader(manager) { - this.manager = manager !== undefined ? manager : DefaultLoadingManager; - this.crossOrigin = 'anonymous'; - this.withCredentials = false; - this.path = ''; - this.resourcePath = ''; - this.requestHeader = {}; - } + class Loader { + constructor(manager) { + this.manager = manager !== undefined ? manager : DefaultLoadingManager; + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; + } - Object.assign(Loader.prototype, { - load: function () + load() /* url, onLoad, onProgress, onError */ - {}, - loadAsync: function (url, onProgress) { + {} + + loadAsync(url, onProgress) { const scope = this; return new Promise(function (resolve, reject) { scope.load(url, resolve, onProgress, reject); }); - }, - parse: function () + } + + parse() /* data */ - {}, - setCrossOrigin: function (crossOrigin) { + {} + + setCrossOrigin(crossOrigin) { this.crossOrigin = crossOrigin; return this; - }, - setWithCredentials: function (value) { + } + + setWithCredentials(value) { this.withCredentials = value; return this; - }, - setPath: function (path) { + } + + setPath(path) { this.path = path; return this; - }, - setResourcePath: function (resourcePath) { + } + + setResourcePath(resourcePath) { this.resourcePath = resourcePath; return this; - }, - setRequestHeader: function (requestHeader) { + } + + setRequestHeader(requestHeader) { this.requestHeader = requestHeader; return this; } - }); + + } const loading = {}; - function FileLoader(manager) { - Loader.call(this, manager); - } + class FileLoader extends Loader { + constructor(manager) { + super(manager); + } - FileLoader.prototype = Object.assign(Object.create(Loader.prototype), { - constructor: FileLoader, - load: function (url, onLoad, onProgress, onError) { + load(url, onLoad, onProgress, onError) { if (url === undefined) url = ''; if (this.path !== undefined) url = this.path + url; url = this.manager.resolveURL(url); @@ -25022,16 +25312,19 @@ scope.manager.itemStart(url); return request; - }, - setResponseType: function (value) { + } + + setResponseType(value) { this.responseType = value; return this; - }, - setMimeType: function (value) { + } + + setMimeType(value) { this.mimeType = value; return this; } - }); + + } class AnimationLoader extends Loader { constructor(manager) { @@ -25078,13 +25371,12 @@ * Sub classes have to implement the parse() method which will be used in load(). */ - function CompressedTextureLoader(manager) { - Loader.call(this, manager); - } + class CompressedTextureLoader extends Loader { + constructor(manager) { + super(manager); + } - CompressedTextureLoader.prototype = Object.assign(Object.create(Loader.prototype), { - constructor: CompressedTextureLoader, - load: function (url, onLoad, onProgress, onError) { + load(url, onLoad, onProgress, onError) { const scope = this; const images = []; const texture = new CompressedTexture(); @@ -25160,7 +25452,8 @@ return texture; } - }); + + } class ImageLoader extends Loader { constructor(manager) { @@ -25253,13 +25546,12 @@ * Sub classes have to implement the parse() method which will be used in load(). */ - function DataTextureLoader(manager) { - Loader.call(this, manager); - } + class DataTextureLoader extends Loader { + constructor(manager) { + super(manager); + } - DataTextureLoader.prototype = Object.assign(Object.create(Loader.prototype), { - constructor: DataTextureLoader, - load: function (url, onLoad, onProgress, onError) { + load(url, onLoad, onProgress, onError) { const scope = this; const texture = new DataTexture(); const loader = new FileLoader(this.manager); @@ -25319,15 +25611,15 @@ }, onProgress, onError); return texture; } - }); - function TextureLoader(manager) { - Loader.call(this, manager); } - TextureLoader.prototype = Object.assign(Object.create(Loader.prototype), { - constructor: TextureLoader, - load: function (url, onLoad, onProgress, onError) { + class TextureLoader extends Loader { + constructor(manager) { + super(manager); + } + + load(url, onLoad, onProgress, onError) { const texture = new Texture(); const loader = new ImageLoader(this.manager); loader.setCrossOrigin(this.crossOrigin); @@ -25345,7 +25637,8 @@ }, onProgress, onError); return texture; } - }); + + } /** * Extensible curve object. @@ -25377,28 +25670,30 @@ * **/ - function Curve() { - this.type = 'Curve'; - this.arcLengthDivisions = 200; - } - - Object.assign(Curve.prototype, { - // Virtual base class method to overwrite and implement in subclasses + class Curve { + constructor() { + this.type = 'Curve'; + this.arcLengthDivisions = 200; + } // Virtual base class method to overwrite and implement in subclasses // - t [0 .. 1] - getPoint: function () + + + getPoint() /* t, optionalTarget */ { console.warn('THREE.Curve: .getPoint() not implemented.'); return null; - }, - // Get point at relative position in curve according to arc length + } // Get point at relative position in curve according to arc length // - u [0 .. 1] - getPointAt: function (u, optionalTarget) { + + + getPointAt(u, optionalTarget) { const t = this.getUtoTmapping(u); return this.getPoint(t, optionalTarget); - }, - // Get sequence of points using getPoint( t ) - getPoints: function (divisions = 5) { + } // Get sequence of points using getPoint( t ) + + + getPoints(divisions = 5) { const points = []; for (let d = 0; d <= divisions; d++) { @@ -25406,9 +25701,10 @@ } return points; - }, - // Get sequence of points using getPointAt( u ) - getSpacedPoints: function (divisions = 5) { + } // Get sequence of points using getPointAt( u ) + + + getSpacedPoints(divisions = 5) { const points = []; for (let d = 0; d <= divisions; d++) { @@ -25416,16 +25712,16 @@ } return points; - }, - // Get total curve arc length - getLength: function () { + } // Get total curve arc length + + + getLength() { const lengths = this.getLengths(); return lengths[lengths.length - 1]; - }, - // Get list of cumulative segment lengths - getLengths: function (divisions) { - if (divisions === undefined) divisions = this.arcLengthDivisions; + } // Get list of cumulative segment lengths + + getLengths(divisions = this.arcLengthDivisions) { if (this.cacheArcLengths && this.cacheArcLengths.length === divisions + 1 && !this.needsUpdate) { return this.cacheArcLengths; } @@ -25446,13 +25742,15 @@ this.cacheArcLengths = cache; return cache; // { sums: cache, sum: sum }; Sum is in the last element. - }, - updateArcLengths: function () { + } + + updateArcLengths() { this.needsUpdate = true; this.getLengths(); - }, - // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant - getUtoTmapping: function (u, distance) { + } // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant + + + getUtoTmapping(u, distance) { const arcLengths = this.getLengths(); let i = 0; const il = arcLengths.length; @@ -25499,12 +25797,13 @@ const t = (i + segmentFraction) / (il - 1); return t; - }, - // Returns a unit vector tangent at t + } // Returns a unit vector tangent at t // In case any sub curve does not implement its tangent derivation, // 2 points a small delta apart will be used to find its gradient // which seems to give a reasonable approximation - getTangent: function (t, optionalTarget) { + + + getTangent(t, optionalTarget) { const delta = 0.0001; let t1 = t - delta; let t2 = t + delta; // Capping in case of danger @@ -25516,12 +25815,14 @@ const tangent = optionalTarget || (pt1.isVector2 ? new Vector2() : new Vector3()); tangent.copy(pt2).sub(pt1).normalize(); return tangent; - }, - getTangentAt: function (u, optionalTarget) { + } + + getTangentAt(u, optionalTarget) { const t = this.getUtoTmapping(u); return this.getTangent(t, optionalTarget); - }, - computeFrenetFrames: function (segments, closed) { + } + + computeFrenetFrames(segments, closed) { // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf const normal = new Vector3(); const tangents = []; @@ -25570,7 +25871,7 @@ if (vec.length() > Number.EPSILON) { vec.normalize(); - const theta = Math.acos(MathUtils.clamp(tangents[i - 1].dot(tangents[i]), -1, 1)); // clamp for floating pt errors + const theta = Math.acos(clamp(tangents[i - 1].dot(tangents[i]), -1, 1)); // clamp for floating pt errors normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta)); } @@ -25580,7 +25881,7 @@ if (closed === true) { - let theta = Math.acos(MathUtils.clamp(normals[0].dot(normals[segments]), -1, 1)); + let theta = Math.acos(clamp(normals[0].dot(normals[segments]), -1, 1)); theta /= segments; if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) { @@ -25599,15 +25900,18 @@ normals: normals, binormals: binormals }; - }, - clone: function () { + } + + clone() { return new this.constructor().copy(this); - }, - copy: function (source) { + } + + copy(source) { this.arcLengthDivisions = source.arcLengthDivisions; return this; - }, - toJSON: function () { + } + + toJSON() { const data = { metadata: { version: 4.5, @@ -25618,12 +25922,14 @@ data.arcLengthDivisions = this.arcLengthDivisions; data.type = this.type; return data; - }, - fromJSON: function (json) { + } + + fromJSON(json) { this.arcLengthDivisions = json.arcLengthDivisions; return this; } - }); + + } class EllipseCurve extends Curve { constructor(aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0) { @@ -26638,7 +26944,7 @@ class Shape extends Path { constructor(points) { super(points); - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.type = 'Shape'; this.holes = []; } @@ -26709,6 +27015,9 @@ this.intensity = intensity; } + dispose() {// Empty here in base class; some subclasses override. + } + copy(source) { super.copy(source); this.color.copy(source.color); @@ -26814,6 +27123,16 @@ return this._frameExtents; } + dispose() { + if (this.map) { + this.map.dispose(); + } + + if (this.mapPass) { + this.mapPass.dispose(); + } + } + copy(source) { this.camera = source.camera.clone(); this.bias = source.bias; @@ -26847,7 +27166,7 @@ updateMatrices(light) { const camera = this.camera; - const fov = MathUtils.RAD2DEG * 2 * light.angle * this.focus; + const fov = RAD2DEG * 2 * light.angle * this.focus; const aspect = this.mapSize.width / this.mapSize.height; const far = light.distance || camera.far; @@ -26898,6 +27217,10 @@ this.intensity = power / Math.PI; } + dispose() { + this.shadow.dispose(); + } + copy(source) { super.copy(source); this.distance = source.distance; @@ -27001,6 +27324,10 @@ this.intensity = power / (4 * Math.PI); } + dispose() { + this.shadow.dispose(); + } + copy(source) { super.copy(source); this.distance = source.distance; @@ -27096,7 +27423,7 @@ } toJSON(meta) { - const data = Object3D.prototype.toJSON.call(this, meta); + const data = super.toJSON(meta); data.object.zoom = this.zoom; data.object.left = this.left; data.object.right = this.right; @@ -27131,6 +27458,10 @@ this.shadow = new DirectionalLightShadow(); } + dispose() { + this.shadow.dispose(); + } + copy(source) { super.copy(source); this.target = source.target.clone(); @@ -27599,8 +27930,8 @@ } - const LoaderUtils = { - decodeText: function (array) { + class LoaderUtils { + static decodeText(array) { if (typeof TextDecoder !== 'undefined') { return new TextDecoder().decode(array); } // Avoid the String.fromCharCode.apply(null, array) shortcut, which @@ -27621,65 +27952,72 @@ // see #16358 return s; } - }, - extractUrlBase: function (url) { + } + + static extractUrlBase(url) { const index = url.lastIndexOf('/'); if (index === -1) return './'; return url.substr(0, index + 1); } - }; - function InstancedBufferGeometry() { - BufferGeometry.call(this); - this.type = 'InstancedBufferGeometry'; - this.instanceCount = Infinity; } - InstancedBufferGeometry.prototype = Object.assign(Object.create(BufferGeometry.prototype), { - constructor: InstancedBufferGeometry, - isInstancedBufferGeometry: true, - copy: function (source) { - BufferGeometry.prototype.copy.call(this, source); + class InstancedBufferGeometry extends BufferGeometry { + constructor() { + super(); + this.type = 'InstancedBufferGeometry'; + this.instanceCount = Infinity; + } + + copy(source) { + super.copy(source); this.instanceCount = source.instanceCount; return this; - }, - clone: function () { + } + + clone() { return new this.constructor().copy(this); - }, - toJSON: function () { - const data = BufferGeometry.prototype.toJSON.call(this); + } + + toJSON() { + const data = super.toJSON(this); data.instanceCount = this.instanceCount; data.isInstancedBufferGeometry = true; return data; } - }); - - function InstancedBufferAttribute(array, itemSize, normalized, meshPerAttribute) { - if (typeof normalized === 'number') { - meshPerAttribute = normalized; - normalized = false; - console.error('THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.'); - } - BufferAttribute.call(this, array, itemSize, normalized); - this.meshPerAttribute = meshPerAttribute || 1; } - InstancedBufferAttribute.prototype = Object.assign(Object.create(BufferAttribute.prototype), { - constructor: InstancedBufferAttribute, - isInstancedBufferAttribute: true, - copy: function (source) { - BufferAttribute.prototype.copy.call(this, source); + InstancedBufferGeometry.prototype.isInstancedBufferGeometry = true; + + class InstancedBufferAttribute extends BufferAttribute { + constructor(array, itemSize, normalized, meshPerAttribute) { + if (typeof normalized === 'number') { + meshPerAttribute = normalized; + normalized = false; + console.error('THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.'); + } + + super(array, itemSize, normalized); + this.meshPerAttribute = meshPerAttribute || 1; + } + + copy(source) { + super.copy(source); this.meshPerAttribute = source.meshPerAttribute; return this; - }, - toJSON: function () { - const data = BufferAttribute.prototype.toJSON.call(this); + } + + toJSON() { + const data = super.toJSON(); data.meshPerAttribute = this.meshPerAttribute; data.isInstancedBufferAttribute = true; return data; } - }); + + } + + InstancedBufferAttribute.prototype.isInstancedBufferAttribute = true; class BufferGeometryLoader extends Loader { constructor(manager) { @@ -28531,29 +28869,29 @@ LinearMipmapLinearFilter: LinearMipmapLinearFilter }; - function ImageBitmapLoader(manager) { - if (typeof createImageBitmap === 'undefined') { - console.warn('THREE.ImageBitmapLoader: createImageBitmap() not supported.'); - } + class ImageBitmapLoader extends Loader { + constructor(manager) { + super(manager); - if (typeof fetch === 'undefined') { - console.warn('THREE.ImageBitmapLoader: fetch() not supported.'); - } + if (typeof createImageBitmap === 'undefined') { + console.warn('THREE.ImageBitmapLoader: createImageBitmap() not supported.'); + } - Loader.call(this, manager); - this.options = { - premultiplyAlpha: 'none' - }; - } + if (typeof fetch === 'undefined') { + console.warn('THREE.ImageBitmapLoader: fetch() not supported.'); + } + + this.options = { + premultiplyAlpha: 'none' + }; + } - ImageBitmapLoader.prototype = Object.assign(Object.create(Loader.prototype), { - constructor: ImageBitmapLoader, - isImageBitmapLoader: true, - setOptions: function setOptions(options) { + setOptions(options) { this.options = options; return this; - }, - load: function (url, onLoad, onProgress, onError) { + } + + load(url, onLoad, onProgress, onError) { if (url === undefined) url = ''; if (this.path !== undefined) url = this.path + url; url = this.manager.resolveURL(url); @@ -28589,7 +28927,10 @@ }); scope.manager.itemStart(url); } - }); + + } + + ImageBitmapLoader.prototype.isImageBitmapLoader = true; class ShapePath { constructor() { @@ -29021,9 +29362,9 @@ AmbientLightProbe.prototype.isAmbientLightProbe = true; - const _eyeRight = new Matrix4(); + const _eyeRight = /*@__PURE__*/new Matrix4(); - const _eyeLeft = new Matrix4(); + const _eyeLeft = /*@__PURE__*/new Matrix4(); class StereoCamera { constructor() { @@ -29064,7 +29405,7 @@ const projectionMatrix = camera.projectionMatrix.clone(); const eyeSepHalf = cache.eyeSep / 2; const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; - const ymax = cache.near * Math.tan(MathUtils.DEG2RAD * cache.fov * 0.5) / cache.zoom; + const ymax = cache.near * Math.tan(DEG2RAD * cache.fov * 0.5) / cache.zoom; let xmin, xmax; // translate xOffset _eyeLeft.elements[12] = -eyeSepHalf; @@ -29090,8 +29431,8 @@ } class Clock { - constructor(autoStart) { - this.autoStart = autoStart !== undefined ? autoStart : true; + constructor(autoStart = true) { + this.autoStart = autoStart; this.startTime = 0; this.oldTime = 0; this.elapsedTime = 0; @@ -29866,61 +30207,71 @@ const _supportedObjectNames = ['material', 'materials', 'bones']; - function Composite(targetGroup, path, optionalParsedPath) { - const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path); - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_(path, parsedPath); - } + class Composite { + constructor(targetGroup, path, optionalParsedPath) { + const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path); + this._targetGroup = targetGroup; + this._bindings = targetGroup.subscribe_(path, parsedPath); + } - Object.assign(Composite.prototype, { - getValue: function (array, offset) { + getValue(array, offset) { this.bind(); // bind all binding const firstValidIndex = this._targetGroup.nCachedObjects_, binding = this._bindings[firstValidIndex]; // and only call .getValue on the first if (binding !== undefined) binding.getValue(array, offset); - }, - setValue: function (array, offset) { + } + + setValue(array, offset) { const bindings = this._bindings; for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { bindings[i].setValue(array, offset); } - }, - bind: function () { + } + + bind() { const bindings = this._bindings; for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { bindings[i].bind(); } - }, - unbind: function () { + } + + unbind() { const bindings = this._bindings; for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) { bindings[i].unbind(); } } - }); - function PropertyBinding(rootNode, path, parsedPath) { - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path); - this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode; - this.rootNode = rootNode; - } + } // Note: This class uses a State pattern on a per-method basis: + // 'bind' sets 'this.getValue' / 'setValue' and shadows the + // prototype version of these methods with one that represents + // the bound state. When the property is not found, the methods + // become no-ops. + - Object.assign(PropertyBinding, { - Composite: Composite, - create: function (root, path, parsedPath) { + class PropertyBinding { + constructor(rootNode, path, parsedPath) { + this.path = path; + this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path); + this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode; + this.rootNode = rootNode; // initial state of these methods that calls 'bind' + + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + } + + static create(root, path, parsedPath) { if (!(root && root.isAnimationObjectGroup)) { return new PropertyBinding(root, path, parsedPath); } else { return new PropertyBinding.Composite(root, path, parsedPath); } - }, - + } /** * Replaces spaces with underscores and removes unsupported characters from * node names, to ensure compatibility with parseTrackName(). @@ -29928,10 +30279,13 @@ * @param {string} name Node name to be sanitized. * @return {string} */ - sanitizeNodeName: function (name) { + + + static sanitizeNodeName(name) { return name.replace(/\s/g, '_').replace(_reservedRe, ''); - }, - parseTrackName: function (trackName) { + } + + static parseTrackName(trackName) { const matches = _trackRe.exec(trackName); if (!matches) { @@ -29966,8 +30320,9 @@ } return results; - }, - findNode: function (root, nodeName) { + } + + static findNode(root, nodeName) { if (!nodeName || nodeName === '' || nodeName === '.' || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) { return root; } // search into skeleton bones. @@ -30006,54 +30361,59 @@ } return null; - } - }); - Object.assign(PropertyBinding.prototype, { - // prototype, continued - // these are used to "bind" a nonexistent property - _getValue_unavailable: function () {}, - _setValue_unavailable: function () {}, - BindingType: { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 - }, - Versioning: { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 - }, - GetterByBindingType: [function getValue_direct(buffer, offset) { + } // these are used to "bind" a nonexistent property + + + _getValue_unavailable() {} + + _setValue_unavailable() {} // Getters + + + _getValue_direct(buffer, offset) { buffer[offset] = this.node[this.propertyName]; - }, function getValue_array(buffer, offset) { + } + + _getValue_array(buffer, offset) { const source = this.resolvedProperty; for (let i = 0, n = source.length; i !== n; ++i) { buffer[offset++] = source[i]; } - }, function getValue_arrayElement(buffer, offset) { + } + + _getValue_arrayElement(buffer, offset) { buffer[offset] = this.resolvedProperty[this.propertyIndex]; - }, function getValue_toArray(buffer, offset) { + } + + _getValue_toArray(buffer, offset) { this.resolvedProperty.toArray(buffer, offset); - }], - SetterByBindingTypeAndVersioning: [[// Direct - function setValue_direct(buffer, offset) { + } // Direct + + + _setValue_direct(buffer, offset) { this.targetObject[this.propertyName] = buffer[offset]; - }, function setValue_direct_setNeedsUpdate(buffer, offset) { + } + + _setValue_direct_setNeedsUpdate(buffer, offset) { this.targetObject[this.propertyName] = buffer[offset]; this.targetObject.needsUpdate = true; - }, function setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) { + } + + _setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) { this.targetObject[this.propertyName] = buffer[offset]; this.targetObject.matrixWorldNeedsUpdate = true; - }], [// EntireArray - function setValue_array(buffer, offset) { + } // EntireArray + + + _setValue_array(buffer, offset) { const dest = this.resolvedProperty; for (let i = 0, n = dest.length; i !== n; ++i) { dest[i] = buffer[offset++]; } - }, function setValue_array_setNeedsUpdate(buffer, offset) { + } + + _setValue_array_setNeedsUpdate(buffer, offset) { const dest = this.resolvedProperty; for (let i = 0, n = dest.length; i !== n; ++i) { @@ -30061,7 +30421,9 @@ } this.targetObject.needsUpdate = true; - }, function setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) { + } + + _setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) { const dest = this.resolvedProperty; for (let i = 0, n = dest.length; i !== n; ++i) { @@ -30069,39 +30431,50 @@ } this.targetObject.matrixWorldNeedsUpdate = true; - }], [// ArrayElement - function setValue_arrayElement(buffer, offset) { + } // ArrayElement + + + _setValue_arrayElement(buffer, offset) { this.resolvedProperty[this.propertyIndex] = buffer[offset]; - }, function setValue_arrayElement_setNeedsUpdate(buffer, offset) { + } + + _setValue_arrayElement_setNeedsUpdate(buffer, offset) { this.resolvedProperty[this.propertyIndex] = buffer[offset]; this.targetObject.needsUpdate = true; - }, function setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) { + } + + _setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) { this.resolvedProperty[this.propertyIndex] = buffer[offset]; this.targetObject.matrixWorldNeedsUpdate = true; - }], [// HasToFromArray - function setValue_fromArray(buffer, offset) { + } // HasToFromArray + + + _setValue_fromArray(buffer, offset) { this.resolvedProperty.fromArray(buffer, offset); - }, function setValue_fromArray_setNeedsUpdate(buffer, offset) { + } + + _setValue_fromArray_setNeedsUpdate(buffer, offset) { this.resolvedProperty.fromArray(buffer, offset); this.targetObject.needsUpdate = true; - }, function setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) { + } + + _setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) { this.resolvedProperty.fromArray(buffer, offset); this.targetObject.matrixWorldNeedsUpdate = true; - }]], - getValue: function getValue_unbound(targetArray, offset) { + } + + _getValue_unbound(targetArray, offset) { this.bind(); - this.getValue(targetArray, offset); // Note: This class uses a State pattern on a per-method basis: - // 'bind' sets 'this.getValue' / 'setValue' and shadows the - // prototype version of these methods with one that represents - // the bound state. When the property is not found, the methods - // become no-ops. - }, - setValue: function getValue_unbound(sourceArray, offset) { + this.getValue(targetArray, offset); + } + + _setValue_unbound(sourceArray, offset) { this.bind(); this.setValue(sourceArray, offset); - }, - // create getter / setter pair for a property in the scene graph - bind: function () { + } // create getter / setter pair for a property in the scene graph + + + bind() { let targetObject = this.node; const parsedPath = this.parsedPath; const objectName = parsedPath.objectName; @@ -30244,21 +30617,36 @@ this.getValue = this.GetterByBindingType[bindingType]; this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning]; - }, - unbind: function () { + } + + unbind() { this.node = null; // back to the prototype version of getValue / setValue // note: avoiding to mutate the shape of 'this' via 'delete' this.getValue = this._getValue_unbound; this.setValue = this._setValue_unbound; } - }); // DECLARE ALIAS AFTER assign prototype - Object.assign(PropertyBinding.prototype, { - // initial state of these methods that calls 'bind' - _getValue_unbound: PropertyBinding.prototype.getValue, - _setValue_unbound: PropertyBinding.prototype.setValue - }); + } + + PropertyBinding.Composite = Composite; + PropertyBinding.prototype.BindingType = { + Direct: 0, + EntireArray: 1, + ArrayElement: 2, + HasFromToArray: 3 + }; + PropertyBinding.prototype.Versioning = { + None: 0, + NeedsUpdate: 1, + MatrixWorldNeedsUpdate: 2 + }; + PropertyBinding.prototype.GetterByBindingType = [PropertyBinding.prototype._getValue_direct, PropertyBinding.prototype._getValue_array, PropertyBinding.prototype._getValue_arrayElement, PropertyBinding.prototype._getValue_toArray]; + PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [[// Direct + PropertyBinding.prototype._setValue_direct, PropertyBinding.prototype._setValue_direct_setNeedsUpdate, PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate], [// EntireArray + PropertyBinding.prototype._setValue_array, PropertyBinding.prototype._setValue_array_setNeedsUpdate, PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate], [// ArrayElement + PropertyBinding.prototype._setValue_arrayElement, PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate], [// HasToFromArray + PropertyBinding.prototype._setValue_fromArray, PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate]]; /** * @@ -30291,7 +30679,7 @@ class AnimationObjectGroup { constructor() { - this.uuid = MathUtils.generateUUID(); // cached objects followed by the active ones + this.uuid = generateUUID(); // cached objects followed by the active ones this._objects = Array.prototype.slice.call(arguments); this.nCachedObjects_ = 0; // threshold @@ -31600,119 +31988,101 @@ } - function InstancedInterleavedBuffer(array, stride, meshPerAttribute) { - InterleavedBuffer.call(this, array, stride); - this.meshPerAttribute = meshPerAttribute || 1; - } + class InstancedInterleavedBuffer extends InterleavedBuffer { + constructor(array, stride, meshPerAttribute = 1) { + super(array, stride); + this.meshPerAttribute = meshPerAttribute || 1; + } - InstancedInterleavedBuffer.prototype = Object.assign(Object.create(InterleavedBuffer.prototype), { - constructor: InstancedInterleavedBuffer, - isInstancedInterleavedBuffer: true, - copy: function (source) { - InterleavedBuffer.prototype.copy.call(this, source); + copy(source) { + super.copy(source); this.meshPerAttribute = source.meshPerAttribute; return this; - }, - clone: function (data) { - const ib = InterleavedBuffer.prototype.clone.call(this, data); + } + + clone(data) { + const ib = super.clone(data); ib.meshPerAttribute = this.meshPerAttribute; return ib; - }, - toJSON: function (data) { - const json = InterleavedBuffer.prototype.toJSON.call(this, data); + } + + toJSON(data) { + const json = super.toJSON(data); json.isInstancedInterleavedBuffer = true; json.meshPerAttribute = this.meshPerAttribute; return json; } - }); - function GLBufferAttribute(buffer, type, itemSize, elementSize, count) { - this.buffer = buffer; - this.type = type; - this.itemSize = itemSize; - this.elementSize = elementSize; - this.count = count; - this.version = 0; } - Object.defineProperty(GLBufferAttribute.prototype, 'needsUpdate', { - set: function (value) { + InstancedInterleavedBuffer.prototype.isInstancedInterleavedBuffer = true; + + class GLBufferAttribute { + constructor(buffer, type, itemSize, elementSize, count) { + this.buffer = buffer; + this.type = type; + this.itemSize = itemSize; + this.elementSize = elementSize; + this.count = count; + this.version = 0; + } + + set needsUpdate(value) { if (value === true) this.version++; } - }); - Object.assign(GLBufferAttribute.prototype, { - isGLBufferAttribute: true, - setBuffer: function (buffer) { + + setBuffer(buffer) { this.buffer = buffer; return this; - }, - setType: function (type, elementSize) { + } + + setType(type, elementSize) { this.type = type; this.elementSize = elementSize; return this; - }, - setItemSize: function (itemSize) { + } + + setItemSize(itemSize) { this.itemSize = itemSize; return this; - }, - setCount: function (count) { + } + + setCount(count) { this.count = count; return this; } - }); - function Raycaster(origin, direction, near = 0, far = Infinity) { - this.ray = new Ray(origin, direction); // direction is assumed to be normalized (for accurate distance calculations) - - this.near = near; - this.far = far; - this.camera = null; - this.layers = new Layers(); - this.params = { - Mesh: {}, - Line: { - threshold: 1 - }, - LOD: {}, - Points: { - threshold: 1 - }, - Sprite: {} - }; - Object.defineProperties(this.params, { - PointCloud: { - get: function () { - console.warn('THREE.Raycaster: params.PointCloud has been renamed to params.Points.'); - return this.Points; - } - } - }); } - function ascSort(a, b) { - return a.distance - b.distance; - } + GLBufferAttribute.prototype.isGLBufferAttribute = true; - function intersectObject(object, raycaster, intersects, recursive) { - if (object.layers.test(raycaster.layers)) { - object.raycast(raycaster, intersects); - } + class Raycaster { + constructor(origin, direction, near = 0, far = Infinity) { + this.ray = new Ray(origin, direction); // direction is assumed to be normalized (for accurate distance calculations) - if (recursive === true) { - const children = object.children; - - for (let i = 0, l = children.length; i < l; i++) { - intersectObject(children[i], raycaster, intersects, true); - } + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); + this.params = { + Mesh: {}, + Line: { + threshold: 1 + }, + LOD: {}, + Points: { + threshold: 1 + }, + Sprite: {} + }; } - } - Object.assign(Raycaster.prototype, { - set: function (origin, direction) { + set(origin, direction) { // direction is assumed to be normalized (for accurate distance calculations) this.ray.set(origin, direction); - }, - setFromCamera: function (coords, camera) { + } + + setFromCamera(coords, camera) { if (camera && camera.isPerspectiveCamera) { this.ray.origin.setFromMatrixPosition(camera.matrixWorld); this.ray.direction.set(coords.x, coords.y, 0.5).unproject(camera).sub(this.ray.origin).normalize(); @@ -31725,13 +32095,15 @@ } else { console.error('THREE.Raycaster: Unsupported camera type: ' + camera.type); } - }, - intersectObject: function (object, recursive = false, intersects = []) { + } + + intersectObject(object, recursive = false, intersects = []) { intersectObject(object, this, intersects, recursive); intersects.sort(ascSort); return intersects; - }, - intersectObjects: function (objects, recursive = false, intersects = []) { + } + + intersectObjects(objects, recursive = false, intersects = []) { for (let i = 0, l = objects.length; i < l; i++) { intersectObject(objects[i], this, intersects, recursive); } @@ -31739,7 +32111,26 @@ intersects.sort(ascSort); return intersects; } - }); + + } + + function ascSort(a, b) { + return a.distance - b.distance; + } + + function intersectObject(object, raycaster, intersects, recursive) { + if (object.layers.test(raycaster.layers)) { + object.raycast(raycaster, intersects); + } + + if (recursive === true) { + const children = object.children; + + for (let i = 0, l = children.length; i < l; i++) { + intersectObject(children[i], raycaster, intersects, true); + } + } + } /** * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system @@ -31791,7 +32182,7 @@ this.phi = 0; } else { this.theta = Math.atan2(x, z); - this.phi = Math.acos(MathUtils.clamp(y / this.radius, -1, 1)); + this.phi = Math.acos(clamp(y / this.radius, -1, 1)); } return this; @@ -32071,7 +32462,7 @@ let t = startEnd_startP / startEnd2; if (clampToLine) { - t = MathUtils.clamp(t, 0, 1); + t = clamp(t, 0, 1); } return t; @@ -32104,27 +32495,28 @@ } - function ImmediateRenderObject(material) { - Object3D.call(this); - this.material = material; + class ImmediateRenderObject extends Object3D { + constructor(material) { + super(); + this.material = material; + + this.render = function () + /* renderCallback */ + {}; - this.render = function () - /* renderCallback */ - {}; + this.hasPositions = false; + this.hasNormals = false; + this.hasColors = false; + this.hasUvs = false; + this.positionArray = null; + this.normalArray = null; + this.colorArray = null; + this.uvArray = null; + this.count = 0; + } - this.hasPositions = false; - this.hasNormals = false; - this.hasColors = false; - this.hasUvs = false; - this.positionArray = null; - this.normalArray = null; - this.colorArray = null; - this.uvArray = null; - this.count = 0; } - ImmediateRenderObject.prototype = Object.create(Object3D.prototype); - ImmediateRenderObject.prototype.constructor = ImmediateRenderObject; ImmediateRenderObject.prototype.isImmediateRenderObject = true; const _vector$3 = /*@__PURE__*/new Vector3(); @@ -32662,6 +33054,11 @@ geometry.getAttribute('position').needsUpdate = true; } + dispose() { + this.geometry.dispose(); + this.material.dispose(); + } + } function setPoint(point, pointMap, geometry, camera, x, y, z) { @@ -32924,15 +33321,20 @@ this.type = 'AxesHelper'; } + dispose() { + this.geometry.dispose(); + this.material.dispose(); + } + } const _floatView = new Float32Array(1); const _int32View = new Int32Array(_floatView.buffer); - const DataUtils = { + class DataUtils { // Converts float32 to float16 (stored as uint16 value). - toHalfFloat: function (val) { + static toHalfFloat(val) { // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410 /* This method is faster than the OpenEXR implementation (very often @@ -32982,7 +33384,8 @@ bits += m & 1; return bits; } - }; + + } const LOD_MIN = 4; const LOD_MAX = 8; @@ -34071,22 +34474,6 @@ }; // - MathUtils.random16 = function () { - console.warn('THREE.Math: .random16() has been deprecated. Use Math.random() instead.'); - return Math.random(); - }; - - MathUtils.nearestPowerOfTwo = function (value) { - console.warn('THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().'); - return MathUtils.floorPowerOfTwo(value); - }; - - MathUtils.nextPowerOfTwo = function (value) { - console.warn('THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().'); - return MathUtils.ceilPowerOfTwo(value); - }; // - - Matrix3.prototype.flattenToArrayOffset = function (array, offset) { console.warn('THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.'); return this.toArray(array, offset); @@ -34430,18 +34817,8 @@ SkinnedMesh.prototype.initBones = function () { console.error('THREE.SkinnedMesh: initBones() has been removed.'); - }; + }; // - Object.defineProperty(Curve.prototype, '__arcLengthDivisions', { - get: function () { - console.warn('THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.'); - return this.arcLengthDivisions; - }, - set: function (value) { - console.warn('THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.'); - this.arcLengthDivisions = value; - } - }); // PerspectiveCamera.prototype.setLens = function (focalLength, filmGauge) { console.warn('THREE.PerspectiveCamera.setLens is deprecated. ' + 'Use .setFocalLength and .filmGauge for a photographic setup.'); @@ -34629,42 +35006,6 @@ } } }); - Object.defineProperties(InstancedBufferGeometry.prototype, { - maxInstancedCount: { - get: function () { - console.warn('THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.'); - return this.instanceCount; - }, - set: function (value) { - console.warn('THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.'); - this.instanceCount = value; - } - } - }); - Object.defineProperties(Raycaster.prototype, { - linePrecision: { - get: function () { - console.warn('THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.'); - return this.params.Line.threshold; - }, - set: function (value) { - console.warn('THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.'); - this.params.Line.threshold = value; - } - } - }); - Object.defineProperties(InterleavedBuffer.prototype, { - dynamic: { - get: function () { - console.warn('THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.'); - return this.usage === DynamicDrawUsage; - }, - set: function (value) { - console.warn('THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.'); - this.setUsage(value); - } - } - }); InterleavedBuffer.prototype.setDynamic = function (value) { console.warn('THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.'); @@ -34746,18 +35087,6 @@ } } }); - Object.defineProperties(MeshPhysicalMaterial.prototype, { - transparency: { - get: function () { - console.warn('THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.'); - return this.transmission; - }, - set: function (value) { - console.warn('THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.'); - this.transmission = value; - } - } - }); Object.defineProperties(ShaderMaterial.prototype, { derivatives: { get: function () { diff --git a/build/three.min.js b/build/three.min.js index d71d385e75a4d5..b14f47c0908bab 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="127",n=100,i=300,r=301,s=302,a=303,o=304,l=306,c=307,h=1e3,u=1001,d=1002,p=1003,f=1004,m=1005,g=1006,v=1007,y=1008,x=1009,_=1012,b=1014,w=1015,M=1016,S=1020,T=1022,E=1023,A=1026,L=1027,R=33776,C=33777,P=33778,D=33779,I=35840,N=35841,B=35842,O=35843,z=37492,F=37496,H=2300,U=2301,G=2302,k=2400,V=2401,W=2402,j=2500,q=2501,X=3e3,Y=3001,Z=3007,J=3002,Q=3004,K=3005,$=3006,tt=7680,et=35044,nt=35048,it="300 es";function rt(){}Object.assign(rt.prototype,{addEventListener:function(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:function(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&&-1!==n[t].indexOf(e)},removeEventListener:function(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:function(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()},clamp:function(t,e,n){return Math.max(e,Math.min(n,t))},euclideanModulo:function(t,e){return(t%e+e)%e},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:function(t,e,n){return(1-n)*t+n*e},damp:function(t,e,n,i){return ot.lerp(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(ot.euclideanModulo(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.DEG2RAD},radToDeg:function(t){return t*ot.RAD2DEG},isPowerOfTwo:function(t){return 0==(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))},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),f=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*f,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*f,o*c);break;case"ZYZ":t.set(l*f,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}}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],f=i[0],m=i[3],g=i[6],v=i[1],y=i[4],x=i[7],_=i[2],b=i[5],w=i[8];return r[0]=s*f+a*v+o*_,r[3]=s*m+a*y+o*b,r[6]=s*g+a*x+o*w,r[1]=l*f+c*v+h*_,r[4]=l*m+c*y+h*b,r[7]=l*g+c*x+h*w,r[2]=u*f+d*v+p*_,r[5]=u*m+d*y+p*b,r[8]=u*g+d*x+p*w,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 f=1/p;return t[0]=h*f,t[1]=(i*l-c*n)*f,t[2]=(a*n-i*s)*f,t[3]=u*f,t[4]=(c*e-i*o)*f,t[5]=(i*r-a*e)*f,t[6]=d*f,t[7]=(n*o-l*e)*f,t[8]=(s*e-n*r)*f,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)}}let ht;ct.prototype.isMatrix3=!0;const ut={getDataURL:function(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===ht&&(ht=document.createElementNS("http://www.w3.org/1999/xhtml","canvas")),ht.width=t.width,ht.height=t.height;const n=ht.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=ht}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 dt=0;class pt extends rt{constructor(t=pt.DEFAULT_IMAGE,e=pt.DEFAULT_MAPPING,n=1001,i=1001,r=1006,s=1008,a=1023,o=1009,l=1,c=3e3){super(),Object.defineProperty(this,"id",{value:dt++}),this.uuid=ot.generateUUID(),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 lt(0,0),this.repeat=new lt(1,1),this.center=new lt(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new ct,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,this.encoding=c,this.version=0,this.onUpdate=null}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}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=ot.generateUUID()),!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 ft(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap?ut.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."),{})}pt.DEFAULT_IMAGE=void 0,pt.DEFAULT_MAPPING=i,pt.prototype.isTexture=!0;class mt{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],f=o[2],m=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+f*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(ot.clamp(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)}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(){}}yt.prototype.isQuaternion=!0;class xt{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 _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(ot.clamp(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}}xt.prototype.isVector3=!0;const _t=new xt,bt=new yt;class wt{constructor(t=new xt(1/0,1/0,1/0),e=new xt(-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 void 0===e&&(console.warn("THREE.Box3: .getParameter() target is now required"),e=new xt),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,St),St.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(Dt),It.subVectors(this.max,Dt),Et.subVectors(t.a,Dt),At.subVectors(t.b,Dt),Lt.subVectors(t.c,Dt),Rt.subVectors(At,Et),Ct.subVectors(Lt,At),Pt.subVectors(Et,Lt);let e=[0,-Rt.z,Rt.y,0,-Ct.z,Ct.y,0,-Pt.z,Pt.y,Rt.z,0,-Rt.x,Ct.z,0,-Ct.x,Pt.z,0,-Pt.x,-Rt.y,Rt.x,0,-Ct.y,Ct.x,0,-Pt.y,Pt.x,0];return!!Ot(e,Et,At,Lt,It)&&(e=[1,0,0,0,1,0,0,0,1],!!Ot(e,Et,At,Lt,It)&&(Nt.crossVectors(Rt,Ct),e=[Nt.x,Nt.y,Nt.z],Ot(e,Et,At,Lt,It)))}clampPoint(t,e){return void 0===e&&(console.warn("THREE.Box3: .clampPoint() target is now required"),e=new xt),e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return St.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return void 0===t&&console.error("THREE.Box3: .getBoundingSphere() target is now required"),this.getCenter(t.center),t.radius=.5*this.getSize(St).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()||(Mt[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Mt[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Mt[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Mt[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Mt[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Mt[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Mt[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Mt[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Mt)),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)}}wt.prototype.isBox3=!0;const Mt=[new xt,new xt,new xt,new xt,new xt,new xt,new xt,new xt],St=new xt,Tt=new wt,Et=new xt,At=new xt,Lt=new xt,Rt=new xt,Ct=new xt,Pt=new xt,Dt=new xt,It=new xt,Nt=new xt,Bt=new xt;function Ot(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Bt.fromArray(t,s);const a=r.x*Math.abs(Bt.x)+r.y*Math.abs(Bt.y)+r.z*Math.abs(Bt.z),o=e.dot(Bt),l=n.dot(Bt),c=i.dot(Bt);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const zt=new wt,Ft=new xt,Ht=new xt,Ut=new xt;class Gt{constructor(t=new xt,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):zt.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 void 0===t&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),t=new wt),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){Ut.subVectors(t,this.center);const e=Ut.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.add(Ut.multiplyScalar(n/t)),this.radius+=n}return this}union(t){return Ht.subVectors(t.center,this.center).normalize().multiplyScalar(t.radius),this.expandByPoint(Ft.copy(t.center).add(Ht)),this.expandByPoint(Ft.copy(t.center).sub(Ht)),this}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const kt=new xt,Vt=new xt,Wt=new xt,jt=new xt,qt=new xt,Xt=new xt,Yt=new xt;class Zt{constructor(t=new xt,e=new xt(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 void 0===e&&(console.warn("THREE.Ray: .at() target is now required"),e=new xt),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,kt)),this}closestPointToPoint(t,e){void 0===e&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),e=new xt),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=kt.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(kt.copy(this.direction).multiplyScalar(e).add(this.origin),kt.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){Vt.copy(t).add(e).multiplyScalar(.5),Wt.copy(e).sub(t).normalize(),jt.copy(this.origin).sub(Vt);const r=.5*t.distanceTo(e),s=-this.direction.dot(Wt),a=jt.dot(this.direction),o=-jt.dot(Wt),l=jt.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(Wt).multiplyScalar(u).add(Vt),d}intersectSphere(t,e){kt.subVectors(t.center,this.origin);const n=kt.dot(this.direction),i=kt.dot(kt)-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,kt)}intersectTriangle(t,e,n,i,r){qt.subVectors(e,t),Xt.subVectors(n,t),Yt.crossVectors(qt,Xt);let s,a=this.direction.dot(Yt);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}jt.subVectors(this.origin,t);const o=s*this.direction.dot(Xt.crossVectors(jt,Xt));if(o<0)return null;const l=s*this.direction.dot(qt.cross(jt));if(l<0)return null;if(o+l>a)return null;const c=-s*jt.dot(Yt);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 Jt{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,f,m){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]=f,g[15]=m,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 Jt).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/Qt.setFromMatrixColumn(t,0).length(),r=1/Qt.setFromMatrixColumn(t,1).length(),s=1/Qt.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($t,t,te)}lookAt(t,e,n){const i=this.elements;return ie.subVectors(t,e),0===ie.lengthSq()&&(ie.z=1),ie.normalize(),ee.crossVectors(n,ie),0===ee.lengthSq()&&(1===Math.abs(n.z)?ie.x+=1e-4:ie.z+=1e-4,ie.normalize(),ee.crossVectors(n,ie)),ee.normalize(),ne.crossVectors(ie,ee),i[0]=ee.x,i[4]=ne.x,i[8]=ie.x,i[1]=ee.y,i[5]=ne.y,i[9]=ie.y,i[2]=ee.z,i[6]=ne.z,i[10]=ie.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],f=n[6],m=n[10],g=n[14],v=n[3],y=n[7],x=n[11],_=n[15],b=i[0],w=i[4],M=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],B=i[11],O=i[15];return r[0]=s*b+a*T+o*R+l*I,r[4]=s*w+a*E+o*C+l*N,r[8]=s*M+a*A+o*P+l*B,r[12]=s*S+a*L+o*D+l*O,r[1]=c*b+h*T+u*R+d*I,r[5]=c*w+h*E+u*C+d*N,r[9]=c*M+h*A+u*P+d*B,r[13]=c*S+h*L+u*D+d*O,r[2]=p*b+f*T+m*R+g*I,r[6]=p*w+f*E+m*C+g*N,r[10]=p*M+f*A+m*P+g*B,r[14]=p*S+f*L+m*D+g*O,r[3]=v*b+y*T+x*R+_*I,r[7]=v*w+y*E+x*C+_*N,r[11]=v*M+y*A+x*P+_*B,r[15]=v*S+y*L+x*D+_*O,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],f=t[13],m=t[14],g=t[15],v=h*m*l-f*u*l+f*o*d-a*m*d-h*o*g+a*u*g,y=p*u*l-c*m*l-p*o*d+s*m*d+c*o*g-s*u*g,x=c*f*l-p*h*l+p*a*d-s*f*d-c*a*g+s*h*g,_=p*h*o-c*f*o-p*a*u+s*f*u+c*a*m-s*h*m,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 w=1/b;return t[0]=v*w,t[1]=(f*u*r-h*m*r-f*i*d+n*m*d+h*i*g-n*u*g)*w,t[2]=(a*m*r-f*o*r+f*i*l-n*m*l-a*i*g+n*o*g)*w,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*w,t[4]=y*w,t[5]=(c*m*r-p*u*r+p*i*d-e*m*d-c*i*g+e*u*g)*w,t[6]=(p*o*r-s*m*r-p*i*l+e*m*l+s*i*g-e*o*g)*w,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*w,t[8]=x*w,t[9]=(p*h*r-c*f*r-p*n*d+e*f*d+c*n*g-e*h*g)*w,t[10]=(s*f*r-p*a*r+p*n*l-e*f*l-s*n*g+e*a*g)*w,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*w,t[12]=_*w,t[13]=(c*f*i-p*h*i+p*n*u-e*f*u-c*n*m+e*h*m)*w,t[14]=(p*a*i-s*f*i-p*n*o+e*f*o+s*n*m-e*a*m)*w,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*w,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){return this.set(1,e,n,0,t,1,n,0,t,e,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,f=s*c,m=s*h,g=a*h,v=o*l,y=o*c,x=o*h,_=n.x,b=n.y,w=n.z;return i[0]=(1-(f+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]=(m+v)*b,i[7]=0,i[8]=(p+y)*w,i[9]=(m-v)*w,i[10]=(1-(u+f))*w,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=Qt.set(i[0],i[1],i[2]).length();const s=Qt.set(i[4],i[5],i[6]).length(),a=Qt.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],Kt.copy(this);const o=1/r,l=1/s,c=1/a;return Kt.elements[0]*=o,Kt.elements[1]*=o,Kt.elements[2]*=o,Kt.elements[4]*=l,Kt.elements[5]*=l,Kt.elements[6]*=l,Kt.elements[8]*=c,Kt.elements[9]*=c,Kt.elements[10]*=c,e.setFromRotationMatrix(Kt),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}}Jt.prototype.isMatrix4=!0;const Qt=new xt,Kt=new Jt,$t=new xt(0,0,0),te=new xt(1,1,1),ee=new xt,ne=new xt,ie=new xt,re=new Jt,se=new yt;class ae{constructor(t=0,e=0,n=0,i=ae.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){return this._x=t,this._y=e,this._z=n,this._order=i||this._order,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,n){const i=ot.clamp,r=t.elements,s=r[0],a=r[4],o=r[8],l=r[1],c=r[5],h=r[9],u=r[2],d=r[6],p=r[10];switch(e=e||this._order){case"XYZ":this._y=Math.asin(i(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-h,p),this._z=Math.atan2(-a,s)):(this._x=Math.atan2(d,c),this._z=0);break;case"YXZ":this._x=Math.asin(-i(h,-1,1)),Math.abs(h)<.9999999?(this._y=Math.atan2(o,p),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-u,s),this._z=0);break;case"ZXY":this._x=Math.asin(i(d,-1,1)),Math.abs(d)<.9999999?(this._y=Math.atan2(-u,p),this._z=Math.atan2(-a,c)):(this._y=0,this._z=Math.atan2(l,s));break;case"ZYX":this._y=Math.asin(-i(u,-1,1)),Math.abs(u)<.9999999?(this._x=Math.atan2(d,p),this._z=Math.atan2(l,s)):(this._x=0,this._z=Math.atan2(-a,c));break;case"YZX":this._z=Math.asin(i(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-h,c),this._y=Math.atan2(-u,s)):(this._x=0,this._y=Math.atan2(o,p));break;case"XZY":this._z=Math.asin(-i(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(d,c),this._y=Math.atan2(o,s)):(this._x=Math.atan2(-h,p),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!1!==n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return re.makeRotationFromQuaternion(t),this.setFromRotationMatrix(re,e,n)}setFromVector3(t,e){return this.set(t.x,t.y,t.z,e||this._order)}reorder(t){return se.setFromEuler(this),this.setFromQuaternion(se,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 xt(this._x,this._y,this._z)}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}}ae.prototype.isEuler=!0,ae.DefaultOrder="XYZ",ae.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class oe{constructor(){this.mask=1}set(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:function(t){return(new this.constructor).copy(this,t)},copy:function(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;e1?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 void 0===t&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),t=new xt),t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||Se.getNormalMatrix(t),i=this.coplanarPoint(we).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)}}Te.prototype.isPlane=!0;const Ee=new xt,Ae=new xt,Le=new xt,Re=new xt,Ce=new xt,Pe=new xt,De=new xt,Ie=new xt,Ne=new xt,Be=new xt;class Oe{constructor(t=new xt,e=new xt,n=new xt){this.a=t,this.b=e,this.c=n}static getNormal(t,e,n,i){void 0===i&&(console.warn("THREE.Triangle: .getNormal() target is now required"),i=new xt),i.subVectors(n,e),Ee.subVectors(t,e),i.cross(Ee);const r=i.lengthSq();return r>0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){Ee.subVectors(i,e),Ae.subVectors(n,e),Le.subVectors(t,e);const s=Ee.dot(Ee),a=Ee.dot(Ae),o=Ee.dot(Le),l=Ae.dot(Ae),c=Ae.dot(Le),h=s*l-a*a;if(void 0===r&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),r=new xt),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,Re),Re.x>=0&&Re.y>=0&&Re.x+Re.y<=1}static getUV(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,Re),o.set(0,0),o.addScaledVector(r,Re.x),o.addScaledVector(s,Re.y),o.addScaledVector(a,Re.z),o}static isFrontFacing(t,e,n,i){return Ee.subVectors(n,e),Ae.subVectors(t,e),Ee.cross(Ae).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}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 Ee.subVectors(this.c,this.b),Ae.subVectors(this.a,this.b),.5*Ee.cross(Ae).length()}getMidpoint(t){return void 0===t&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),t=new xt),t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Oe.getNormal(this.a,this.b,this.c,t)}getPlane(t){return void 0===t&&(console.warn("THREE.Triangle: .getPlane() target is now required"),t=new Te),t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Oe.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return Oe.getUV(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return Oe.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Oe.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){void 0===e&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),e=new xt);const n=this.a,i=this.b,r=this.c;let s,a;Ce.subVectors(i,n),Pe.subVectors(r,n),Ie.subVectors(t,n);const o=Ce.dot(Ie),l=Pe.dot(Ie);if(o<=0&&l<=0)return e.copy(n);Ne.subVectors(t,i);const c=Ce.dot(Ne),h=Pe.dot(Ne);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(Ce,s);Be.subVectors(t,r);const d=Ce.dot(Be),p=Pe.dot(Be);if(p>=0&&d<=p)return e.copy(r);const f=d*l-o*p;if(f<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(n).addScaledVector(Pe,a);const m=c*p-d*h;if(m<=0&&h-c>=0&&d-p>=0)return De.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(De,a);const g=1/(m+f+u);return s=f*g,a=u*g,e.copy(n).addScaledVector(Ce,s).addScaledVector(Pe,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let ze=0;function Fe(){Object.defineProperty(this,"id",{value:ze++}),this.uuid=ot.generateUUID(),this.name="",this.type="Material",this.fog=!0,this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,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.alphaTest=0,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0}Fe.prototype=Object.assign(Object.create(rt.prototype),{constructor:Fe,isMaterial:!0,onBeforeCompile:function(){},customProgramCacheKey:function(){return this.onBeforeCompile.toString()},setValues:function(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:function(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),this.sheen&&this.sheen.isColor&&(n.sheen=this.sheen.getHex()),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.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.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,n.reflectivity=this.reflectivity,n.refractionRatio=this.refractionRatio,void 0!==this.combine&&(n.combine=this.combine),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity)),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),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),!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.morphTargets&&(n.morphTargets=!0),!0===this.morphNormals&&(n.morphNormals=!0),!0===this.skinning&&(n.skinning=!0),!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:function(){return(new this.constructor).copy(this)},copy:function(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.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:function(){this.dispatchEvent({type:"dispose"})}}),Object.defineProperty(Fe.prototype,"needsUpdate",{set:function(t){!0===t&&this.version++}});const He={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},Ue={h:0,s:0,l:0},Ge={h:0,s:0,l:0};function ke(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 Ve(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function We(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}class je{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=ot.euclideanModulo(t,1),e=ot.clamp(e,0,1),n=ot.clamp(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=ke(r,i,t+1/3),this.g=ke(r,i,t),this.b=ke(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=He[t];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=Ve(t.r),this.g=Ve(t.g),this.b=Ve(t.b),this}copyLinearToSRGB(t){return this.r=We(t.r),this.g=We(t.g),this.b=We(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){void 0===t&&(console.warn("THREE.Color: .getHSL() target is now required"),t={h:0,s:0,l:0});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+(ne&&(e=t[n]);return e}Object.defineProperty(Ze.prototype,"needsUpdate",{set:function(t){!0===t&&this.version++}}),Object.assign(Ze.prototype,{isBufferAttribute:!0,onUploadCallback:function(){},setUsage:function(t){return this.usage=t,this},copy:function(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:function(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i65535?nn:tn)(t,1):this.index=t,this},getAttribute:function(t){return this.attributes[t]},setAttribute:function(t,e){return this.attributes[t]=e,this},deleteAttribute:function(t){return delete this.attributes[t],this},hasAttribute:function(t){return void 0!==this.attributes[t]},addGroup:function(t,e,n=0){this.groups.push({start:t,count:e,materialIndex:n})},clearGroups:function(){this.groups=[]},setDrawRange:function(t,e){this.drawRange.start=t,this.drawRange.count=e},applyMatrix4:function(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},rotateX:function(t){return un.makeRotationX(t),this.applyMatrix4(un),this},rotateY:function(t){return un.makeRotationY(t),this.applyMatrix4(un),this},rotateZ:function(t){return un.makeRotationZ(t),this.applyMatrix4(un),this},translate:function(t,e,n){return un.makeTranslation(t,e,n),this.applyMatrix4(un),this},scale:function(t,e,n){return un.makeScale(t,e,n),this.applyMatrix4(un),this},lookAt:function(t){return dn.lookAt(t),dn.updateMatrix(),this.applyMatrix4(dn.matrix),this},center:function(){return this.computeBoundingBox(),this.boundingBox.getCenter(pn).negate(),this.translate(pn.x,pn.y,pn.z),this},setFromPoints:function(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:function(){return(new vn).copy(this)},copy:function(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;tn.far?null:{distance:c,point:Nn.clone(),object:t}}(t,e,n,i,bn,wn,Mn,In);if(p){o&&(Cn.fromBufferAttribute(o,c),Pn.fromBufferAttribute(o,h),Dn.fromBufferAttribute(o,u),p.uv=Oe.getUV(In,bn,wn,Mn,Cn,Pn,Dn,new lt)),l&&(Cn.fromBufferAttribute(l,c),Pn.fromBufferAttribute(l,h),Dn.fromBufferAttribute(l,u),p.uv2=Oe.getUV(In,bn,wn,Mn,Cn,Pn,Dn,new lt));const t={a:c,b:h,c:u,normal:new xt,materialIndex:0};Oe.getNormal(bn,wn,Mn,t.normal),p.face=t}return p}Bn.prototype=Object.assign(Object.create(be.prototype),{constructor:Bn,isMesh:!0,copy:function(t){return be.prototype.copy.call(this,t),void 0!==t.morphTargetInfluences&&(this.morphTargetInfluences=t.morphTargetInfluences.slice()),void 0!==t.morphTargetDictionary&&(this.morphTargetDictionary=Object.assign({},t.morphTargetDictionary)),this.material=t.material,this.geometry=t.geometry,this},updateMorphTargets:function(){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.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}},raycast:function(t,e){const n=this.geometry,i=this.material,r=this.matrixWorld;if(void 0===i)return;if(null===n.boundingSphere&&n.computeBoundingSphere(),_n.copy(n.boundingSphere),_n.applyMatrix4(r),!1===t.ray.intersectsSphere(_n))return;if(yn.copy(r).invert(),xn.copy(t.ray).applyMatrix4(yn),null!==n.boundingBox&&!1===xn.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;n0?1:-1,c.push(A.x,A.y,A.z),h.push(o/m),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},kn.prototype=Object.assign(Object.create(be.prototype),{constructor:kn,isCamera:!0,copy:function(t,e){return be.prototype.copy.call(this,t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this},getWorldDirection:function(t){void 0===t&&(console.warn("THREE.Camera: .getWorldDirection() target is now required"),t=new xt),this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()},updateMatrixWorld:function(t){be.prototype.updateMatrixWorld.call(this,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()},updateWorldMatrix:function(t,e){be.prototype.updateWorldMatrix.call(this,t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()},clone:function(){return(new this.constructor).copy(this)}}),Vn.prototype=Object.assign(Object.create(kn.prototype),{constructor:Vn,isPerspectiveCamera:!0,copy:function(t,e){return kn.prototype.copy.call(this,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:function(t){const e=.5*this.getFilmHeight()/t;this.fov=2*ot.RAD2DEG*Math.atan(e),this.updateProjectionMatrix()},getFocalLength:function(){const t=Math.tan(.5*ot.DEG2RAD*this.fov);return.5*this.getFilmHeight()/t},getEffectiveFOV:function(){return 2*ot.RAD2DEG*Math.atan(Math.tan(.5*ot.DEG2RAD*this.fov)/this.zoom)},getFilmWidth:function(){return this.filmGauge*Math.min(this.aspect,1)},getFilmHeight:function(){return this.filmGauge/Math.max(this.aspect,1)},setViewOffset:function(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:function(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()},updateProjectionMatrix:function(){const t=this.near;let e=t*Math.tan(.5*ot.DEG2RAD*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:function(t){const e=be.prototype.toJSON.call(this,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}});const Wn=90;class jn 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 Vn(Wn,1,t,e);i.layers=this.layers,i.up.set(0,-1,0),i.lookAt(new xt(1,0,0)),this.add(i);const r=new Vn(Wn,1,t,e);r.layers=this.layers,r.up.set(0,-1,0),r.lookAt(new xt(-1,0,0)),this.add(r);const s=new Vn(Wn,1,t,e);s.layers=this.layers,s.up.set(0,0,1),s.lookAt(new xt(0,1,0)),this.add(s);const a=new Vn(Wn,1,t,e);a.layers=this.layers,a.up.set(0,0,-1),a.lookAt(new xt(0,-1,0)),this.add(a);const o=new Vn(Wn,1,t,e);o.layers=this.layers,o.up.set(0,-1,0),o.lookAt(new xt(0,0,1)),this.add(o);const l=new Vn(Wn,1,t,e);l.layers=this.layers,l.up.set(0,-1,0),l.lookAt(new xt(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 qn extends pt{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=void 0!==o?o:T,l,c,h),this._needsFlipEnvMap=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}qn.prototype.isCubeTexture=!0;class Xn extends gt{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 qn(void 0,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),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 zn(5,5,5),r=new Gn({name:"CubemapFromEquirect",uniforms:Fn(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Bn(i,r),a=e.minFilter;e.minFilter===y&&(e.minFilter=g);return new jn(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)}}Xn.prototype.isWebGLCubeRenderTarget=!0;class Yn extends pt{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={data:t||null,width:e||1,height:n||1},this.magFilter=void 0!==l?l:p,this.minFilter=void 0!==c?c:p,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1,this.needsUpdate=!0}}Yn.prototype.isDataTexture=!0;const Zn=new Gt,Jn=new xt;class Qn{constructor(t=new Te,e=new Te,n=new Te,i=new Te,r=new Te,s=new Te){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],f=n[11],m=n[12],g=n[13],v=n[14],y=n[15];return e[0].setComponents(a-i,h-o,f-u,y-m).normalize(),e[1].setComponents(a+i,h+o,f+u,y+m).normalize(),e[2].setComponents(a+r,h+l,f+d,y+g).normalize(),e[3].setComponents(a-r,h-l,f-d,y-g).normalize(),e[4].setComponents(a-s,h-c,f-p,y-v).normalize(),e[5].setComponents(a+s,h+c,f+p,y+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),Zn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(Zn)}intersectsSprite(t){return Zn.center.set(0,0,0),Zn.radius=.7071067811865476,Zn.applyMatrix4(t.matrixWorld),this.intersectsSphere(Zn)}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,Jn.y=i.normal.y>0?t.max.y:t.min.y,Jn.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(Jn)<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 Kn(){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 $n(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 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 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}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.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}\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_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\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 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 max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\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 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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\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}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\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#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\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\tuniform int maxMipLevel;\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 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\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\tfogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\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 fogDepth;\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 texture2D( gradientMap, coord ).rgb;\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\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\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 );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\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\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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 );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\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 GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\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 getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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 getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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 getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_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_Diffuse_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;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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_Diffuse_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.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\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 = sheen;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat specularRoughness;\n\tvec3 specularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\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.specularRoughness;\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#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_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_Diffuse_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 CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * 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 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\tgetPointDirectLightIrradiance( 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\tgetSpotDirectLightIrradiance( 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\tgetDirectionalDirectLightIrradiance( 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 );\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 );\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 += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\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\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\t\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\t\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\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",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 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",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; }",transmissionmap_fragment:"#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif",transmissionmap_pars_fragment:"#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\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 )\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_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}",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}",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}",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}",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 \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}",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}",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 \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}",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}",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}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \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}",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 \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\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\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}",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 \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_Diffuse_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_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\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 \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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\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\tvViewPosition = - mvPosition.xyz;\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 \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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}",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 \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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSMISSION\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSMISSION\n\tuniform float transmission;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#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\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#ifdef TRANSMISSION\n\t\tfloat totalTransmission = transmission;\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\t#include \n\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#ifdef TRANSMISSION\n\t\tdiffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#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\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#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\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}",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#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\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}",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#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\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#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\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}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}",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}",shadow_vert:"#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}",sprite_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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}"},ni={common:{diffuse:{value:new je(15658734)},opacity:{value:1},map:{value:null},uvTransform:{value:new ct},uv2Transform:{value:new ct},alphaMap:{value:null}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},refractionRatio:{value:.98},maxMipLevel:{value:0}},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 je(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 je(15658734)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},uvTransform:{value:new ct}},sprite:{diffuse:{value:new je(15658734)},opacity:{value:1},center:{value:new lt(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},uvTransform:{value:new ct}}},ii={basic:{uniforms:Hn([ni.common,ni.specularmap,ni.envmap,ni.aomap,ni.lightmap,ni.fog]),vertexShader:ei.meshbasic_vert,fragmentShader:ei.meshbasic_frag},lambert:{uniforms:Hn([ni.common,ni.specularmap,ni.envmap,ni.aomap,ni.lightmap,ni.emissivemap,ni.fog,ni.lights,{emissive:{value:new je(0)}}]),vertexShader:ei.meshlambert_vert,fragmentShader:ei.meshlambert_frag},phong:{uniforms:Hn([ni.common,ni.specularmap,ni.envmap,ni.aomap,ni.lightmap,ni.emissivemap,ni.bumpmap,ni.normalmap,ni.displacementmap,ni.fog,ni.lights,{emissive:{value:new je(0)},specular:{value:new je(1118481)},shininess:{value:30}}]),vertexShader:ei.meshphong_vert,fragmentShader:ei.meshphong_frag},standard:{uniforms:Hn([ni.common,ni.envmap,ni.aomap,ni.lightmap,ni.emissivemap,ni.bumpmap,ni.normalmap,ni.displacementmap,ni.roughnessmap,ni.metalnessmap,ni.fog,ni.lights,{emissive:{value:new je(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:ei.meshphysical_vert,fragmentShader:ei.meshphysical_frag},toon:{uniforms:Hn([ni.common,ni.aomap,ni.lightmap,ni.emissivemap,ni.bumpmap,ni.normalmap,ni.displacementmap,ni.gradientmap,ni.fog,ni.lights,{emissive:{value:new je(0)}}]),vertexShader:ei.meshtoon_vert,fragmentShader:ei.meshtoon_frag},matcap:{uniforms:Hn([ni.common,ni.bumpmap,ni.normalmap,ni.displacementmap,ni.fog,{matcap:{value:null}}]),vertexShader:ei.meshmatcap_vert,fragmentShader:ei.meshmatcap_frag},points:{uniforms:Hn([ni.points,ni.fog]),vertexShader:ei.points_vert,fragmentShader:ei.points_frag},dashed:{uniforms:Hn([ni.common,ni.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:ei.linedashed_vert,fragmentShader:ei.linedashed_frag},depth:{uniforms:Hn([ni.common,ni.displacementmap]),vertexShader:ei.depth_vert,fragmentShader:ei.depth_frag},normal:{uniforms:Hn([ni.common,ni.bumpmap,ni.normalmap,ni.displacementmap,{opacity:{value:1}}]),vertexShader:ei.normal_vert,fragmentShader:ei.normal_frag},sprite:{uniforms:Hn([ni.sprite,ni.fog]),vertexShader:ei.sprite_vert,fragmentShader:ei.sprite_frag},background:{uniforms:{uvTransform:{value:new ct},t2D:{value:null}},vertexShader:ei.background_vert,fragmentShader:ei.background_frag},cube:{uniforms:Hn([ni.envmap,{opacity:{value:1}}]),vertexShader:ei.cube_vert,fragmentShader:ei.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:ei.equirect_vert,fragmentShader:ei.equirect_frag},distanceRGBA:{uniforms:Hn([ni.common,ni.displacementmap,{referencePosition:{value:new xt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:ei.distanceRGBA_vert,fragmentShader:ei.distanceRGBA_frag},shadow:{uniforms:Hn([ni.lights,ni.fog,{color:{value:new je(0)},opacity:{value:1}}]),vertexShader:ei.shadow_vert,fragmentShader:ei.shadow_frag}};function ri(t,e,n,i,r){const s=new je(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,f,m){let g=!0===r.isScene?r.background:null;g&&g.isTexture&&(g=e.get(g));const v=t.xr,y=v.getSession&&v.getSession();y&&"additive"===y.environmentBlendMode&&(g=null),null===g?p(s,c):g&&g.isColor&&(p(g,1),m=!0),(t.autoClear||m)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),g&&(g.isCubeTexture||g.mapping===l)?(void 0===o&&(o=new Bn(new zn(1,1,1),new Gn({name:"BackgroundCubeMaterial",uniforms:Fn(ii.cube.uniforms),vertexShader:ii.cube.vertexShader,fragmentShader:ii.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=g,o.material.uniforms.flipEnvMap.value=g.isCubeTexture&&g._needsFlipEnvMap?-1:1,h===g&&u===g.version&&d===t.toneMapping||(o.material.needsUpdate=!0,h=g,u=g.version,d=t.toneMapping),n.unshift(o,o.geometry,o.material,0,0,null)):g&&g.isTexture&&(void 0===a&&(a=new Bn(new ti(2,2),new Gn({name:"BackgroundMaterial",uniforms:Fn(ii.background.uniforms),vertexShader:ii.background.vertexShader,fragmentShader:ii.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=g,!0===g.matrixAutoUpdate&&g.updateMatrix(),a.material.uniforms.uvTransform.value.copy(g.matrix),h===g&&u===g.version&&d===t.toneMapping||(a.material.needsUpdate=!0,h=g,u=g.version,d=t.toneMapping),n.unshift(a,a.geometry,a.material,0,0,null))}}}function si(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){const s=l[e];if(void 0!==s){const e=s.normalized,r=s.itemSize,a=n.get(s);if(void 0===a)continue;const l=a.buffer,c=a.type,h=a.bytesPerElement;if(s.isInterleavedBufferAttribute){const n=s.data,a=n.stride,u=s.offset;n&&n.isInstancedInterleavedBuffer?(m(i,n.meshPerAttribute),void 0===o._maxInstanceCount&&(o._maxInstanceCount=n.meshPerAttribute*n.count)):f(i),t.bindBuffer(34962,l),v(i,r,c,e,a*h,u*h)}else s.isInstancedBufferAttribute?(m(i,s.meshPerAttribute),void 0===o._maxInstanceCount&&(o._maxInstanceCount=s.meshPerAttribute*s.count)):f(i),t.bindBuffer(34962,l),v(i,r,c,e,0,0)}else if("instanceMatrix"===e){const e=n.get(r.instanceMatrix);if(void 0===e)continue;const s=e.buffer,a=e.type;m(i+0,1),m(i+1,1),m(i+2,1),m(i+3,1),t.bindBuffer(34962,s),t.vertexAttribPointer(i+0,4,a,!1,64,0),t.vertexAttribPointer(i+1,4,a,!1,64,16),t.vertexAttribPointer(i+2,4,a,!1,64,32),t.vertexAttribPointer(i+3,4,a,!1,64,48)}else if("instanceColor"===e){const e=n.get(r.instanceColor);if(void 0===e)continue;const s=e.buffer,a=e.type;m(i,1),t.bindBuffer(34962,s),t.vertexAttribPointer(i,3,a,!1,12,0)}else if(void 0!==h){const n=h[e];if(void 0!==n)switch(n.length){case 2:t.vertexAttrib2fv(i,n);break;case 3:t.vertexAttrib3fv(i,n);break;case 4:t.vertexAttrib4fv(i,n);break;default:t.vertexAttrib1fv(i,n)}}}}g()}(r,l,u,y),null!==x&&t.bindBuffer(34963,n.get(x).buffer))},reset:y,resetDefaultState:x,dispose:function(){y();for(const t in o){const e=o[t];for(const t in e){const n=e[t];for(const t in n)u(n[t].object),delete n[t];delete e[t]}delete o[t]}},releaseStatesOfGeometry:function(t){if(void 0===o[t.id])return;const e=o[t.id];for(const t in e){const n=e[t];for(const t in n)u(n[t].object),delete n[t];delete e[t]}delete o[t.id]},releaseStatesOfProgram:function(t){for(const e in o){const n=o[e];if(void 0===n[t.id])continue;const i=n[t.id];for(const t in i)u(i[t].object),delete i[t];delete n[t.id]}},initAttributes:p,enableAttribute:f,disableUnusedAttributes:g}}function ai(t,e,n,i){const r=i.isWebGL2;let s;this.setMode=function(t){s=t},this.render=function(e,i){t.drawArrays(s,e,i),n.update(i,s,1)},this.renderInstances=function(i,a,o){if(0===o)return;let l,c;if(r)l=t,c="drawArraysInstanced";else if(l=e.get("ANGLE_instanced_arrays"),c="drawArraysInstancedANGLE",null===l)return void console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");l[c](s,i,a,o),n.update(a,s,o)}}function oi(t,e,n){let i;function r(e){if("highp"===e){if(t.getShaderPrecisionFormat(35633,36338).precision>0&&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=!0===n.logarithmicDepthBuffer,c=t.getParameter(34930),h=t.getParameter(35660),u=t.getParameter(3379),d=t.getParameter(34076),p=t.getParameter(34921),f=t.getParameter(36347),m=t.getParameter(36348),g=t.getParameter(36349),v=h>0,y=s||e.has("OES_texture_float");return{isWebGL2:s,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:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:u,maxCubemapSize:d,maxAttributes:p,maxVertexUniforms:f,maxVaryings:m,maxFragmentUniforms:g,vertexTextures:v,floatFragmentTextures:y,floatVertexTextures:v&&y,maxSamples:s?t.getParameter(36183):0}}function li(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new Te,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=t.getRenderTarget(),o=new Xn(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}}}function hi(t){const e={};function n(n){if(void 0!==e[n])return e[n];let i;switch(n){case"WEBGL_depth_texture":i=t.getExtension("WEBGL_depth_texture")||t.getExtension("MOZ_WEBGL_depth_texture")||t.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":i=t.getExtension("EXT_texture_filter_anisotropic")||t.getExtension("MOZ_EXT_texture_filter_anisotropic")||t.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":i=t.getExtension("WEBGL_compressed_texture_s3tc")||t.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||t.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":i=t.getExtension("WEBGL_compressed_texture_pvrtc")||t.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;default:i=t.getExtension(n)}return e[n]=i,i}return{has:function(t){return null!==n(t)},init:function(t){t.isWebGL2?n("EXT_color_buffer_float"):(n("WEBGL_depth_texture"),n("OES_texture_float"),n("OES_texture_half_float"),n("OES_texture_half_float_linear"),n("OES_standard_derivatives"),n("OES_element_index_uint"),n("OES_vertex_array_object"),n("ANGLE_instanced_arrays")),n("OES_texture_float_linear"),n("EXT_color_buffer_half_float")},get:function(t){const e=n(t);return null===e&&console.warn("THREE.WebGLRenderer: "+t+" extension not supported."),e}}}function ui(t,e,n,i){const r={},s=new WeakMap;function a(t){const o=t.target;null!==o.index&&e.remove(o.index);for(const t in o.attributes)e.remove(o.attributes[t]);o.removeEventListener("dispose",a),delete r[o.id];const l=s.get(o);l&&(e.remove(l),s.delete(o)),i.releaseStatesOfGeometry(o),!0===o.isInstancedBufferGeometry&&delete o._maxInstanceCount,n.memory.geometries--}function o(t){const n=[],i=t.index,r=t.attributes.position;let a=0;if(null!==i){const t=i.array;a=i.version;for(let e=0,i=t.length;e65535?nn:tn)(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;t0)return t;const r=e*n;let s=Si[r];if(void 0===s&&(s=new Float32Array(r),Si[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 Ci(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n/gm;function Ir(t){return t.replace(Dr,Nr)}function Nr(t,e){const n=ei[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return Ir(n)}const Br=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,Or=/#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 zr(t){return t.replace(Or,Hr).replace(Br,Fr)}function Fr(t,e,n,i){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),Hr(t,e,n,i)}function Hr(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.rendererExtensionShaderTextureLod?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Rr).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 _,b,w=n.glslVersion?"#version "+n.glslVersion+"\n":"";n.isRawShaderMaterial?(_=[y].filter(Rr).join("\n"),_.length>0&&(_+="\n"),b=[v,y].filter(Rr).join("\n"),b.length>0&&(b+="\n")):(_=[Ur(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 "+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.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.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",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.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","#ifdef USE_MORPHTARGETS","\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(Rr).join("\n"),b=[v,Ur(n),"#define SHADER_NAME "+n.shaderName,y,n.alphaTest?"#define ALPHATEST "+n.alphaTest+(n.alphaTest%1?"":".0"):"","#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 "+f:"",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.specularMap?"#define USE_SPECULARMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.sheen?"#define USE_SHEEN":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",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?ei.tonemapping_pars_fragment:"",0!==n.toneMapping?Lr("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",ei.encodings_pars_fragment,n.map?Er("mapTexelToLinear",n.mapEncoding):"",n.matcap?Er("matcapTexelToLinear",n.matcapEncoding):"",n.envMap?Er("envMapTexelToLinear",n.envMapEncoding):"",n.emissiveMap?Er("emissiveMapTexelToLinear",n.emissiveMapEncoding):"",n.lightMap?Er("lightMapTexelToLinear",n.lightMapEncoding):"",Ar("linearToOutputTexel",n.outputEncoding),n.depthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Rr).join("\n")),h=Ir(h),h=Cr(h,n),h=Pr(h,n),u=Ir(u),u=Cr(u,n),u=Pr(u,n),h=zr(h),u=zr(u),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(w="#version 300 es\n",_=["#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+_,b=["#define varying in",n.glslVersion===it?"":"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"+b);const M=w+b+u,S=wr(a,35633,w+_+h),T=wr(a,35632,M);if(a.attachShader(x,S),a.attachShader(x,T),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(T).trim();let i=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){i=!1;const e=Tr(a,S,"vertex"),n=Tr(a,T,"fragment");console.error("THREE.WebGLProgram: shader error: ",a.getError(),"35715",a.getProgramParameter(x,35715),"gl.getProgramInfoLog",t,e,n)}else""!==t?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",t):""!==e&&""!==n||(r=!1);r&&(this.diagnostics={runnable:i,programLog:t,vertexShader:{log:e,prefix:_},fragmentShader:{log:n,prefix:b}})}let E,A;return a.deleteShader(S),a.deleteShader(T),this.getUniforms=function(){return void 0===E&&(E=new br(a,x)),E},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const n={},i=t.getProgramParameter(e,35721);for(let r=0;r0,maxBones:S,useVertexTexture:u,morphTargets:r.morphTargets,morphNormals:r.morphNormals,numDirLights:a.directional.length,numPointLights:a.point.length,numSpotLights:a.spot.length,numRectAreaLights:a.rectArea.length,numHemiLights:a.hemi.length,numDirLightShadows:a.directionalShadowMap.length,numPointLightShadows:a.pointShadowMap.length,numSpotLightShadows:a.spotShadowMap.length,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:r.dithering,shadowMapEnabled:t.shadowMap.enabled&&g.length>0,shadowMapType:t.shadowMap.type,toneMapping:r.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:r.premultipliedAlpha,alphaTest:r.alphaTest,doubleSided:2===r.side,flipSided:1===r.side,depthPacking:void 0!==r.depthPacking&&r.depthPacking,index0AttributeName:r.index0AttributeName,extensionDerivatives:r.extensions&&r.extensions.derivatives,extensionFragDepth:r.extensions&&r.extensions.fragDepth,extensionDrawBuffers:r.extensions&&r.extensions.drawBuffers,extensionShaderTextureLOD:r.extensions&&r.extensions.shaderTextureLOD,rendererExtensionFragDepth:o||n.has("EXT_frag_depth"),rendererExtensionDrawBuffers:o||n.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:o||n.has("EXT_shader_texture_lod"),customProgramCacheKey:r.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.fragmentShader),n.push(e.vertexShader)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);if(!1===e.isRawShaderMaterial){for(let t=0;t1&&i.sort(t||Wr),r.length>1&&r.sort(e||jr)}}}function Xr(t){let e=new WeakMap;return{get:function(n,i){let r;return!1===e.has(n)?(r=new qr(t),e.set(n,[r])):i>=e.get(n).length?(r=new qr(t),e.get(n).push(r)):r=e.get(n)[i],r},dispose:function(){e=new WeakMap}}}function Yr(){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 xt,color:new je};break;case"SpotLight":n={position:new xt,direction:new xt,color:new je,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new xt,color:new je,distance:0,decay:0};break;case"HemisphereLight":n={direction:new xt,skyColor:new je,groundColor:new je};break;case"RectAreaLight":n={color:new je,position:new xt,halfWidth:new xt,halfHeight:new xt}}return t[e.id]=n,n}}}let Zr=0;function Jr(t,e){return(e.castShadow?1:0)-(t.castShadow?1:0)}function Qr(t,e){const n=new Yr,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 xt);const s=new xt,a=new Jt,o=new Jt;return{setup:function(s){let a=0,o=0,l=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let c=0,h=0,u=0,d=0,p=0,f=0,m=0,g=0;s.sort(Jr);for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=ni.LTC_FLOAT_1,r.rectAreaLTC2=ni.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=ni.LTC_HALF_1,r.rectAreaLTC2=ni.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=a,r.ambient[1]=o,r.ambient[2]=l;const v=r.hash;v.directionalLength===c&&v.pointLength===h&&v.spotLength===u&&v.rectAreaLength===d&&v.hemiLength===p&&v.numDirectionalShadows===f&&v.numPointShadows===m&&v.numSpotShadows===g||(r.directional.length=c,r.spot.length=u,r.rectArea.length=d,r.point.length=h,r.hemi.length=p,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=m,r.pointShadowMap.length=m,r.spotShadow.length=g,r.spotShadowMap.length=g,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=m,r.spotShadowMatrix.length=g,v.directionalLength=c,v.pointLength=h,v.spotLength=u,v.rectAreaLength=d,v.hemiLength=p,v.numDirectionalShadows=f,v.numPointShadows=m,v.numSpotShadows=g,r.version=Zr++)},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 Kr(t,e),n.get(i).push(s)):s=n.get(i)[r],s},dispose:function(){n=new WeakMap}}}class ts extends Fe{constructor(t){super(),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,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.skinning=t.skinning,this.morphTargets=t.morphTargets,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}}ts.prototype.isMeshDepthMaterial=!0;class es extends Fe{constructor(t){super(),this.type="MeshDistanceMaterial",this.referencePosition=new xt,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,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.skinning=t.skinning,this.morphTargets=t.morphTargets,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}es.prototype.isMeshDistanceMaterial=!0;function ns(t,e,n){let i=new Qn;const r=new lt,s=new lt,a=new mt,o=[],l=[],c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new Gn({defines:{SAMPLE_RATE:2/8,HALF_SAMPLE_RATE:1/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\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 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, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),f=d.clone();f.defines.HORIZONTAL_PASS=1;const m=new vn;m.setAttribute("position",new Ze(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const v=new Bn(m,d),y=this;function x(n,i){const r=e.update(v);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),f.uniforms.shadow_pass.value=n.mapPass.texture,f.uniforms.resolution.value=n.mapSize,f.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,r,f,v,null)}function _(t,e,n){const i=t<<0|e<<1|n<<2;let r=o[i];return void 0===r&&(r=new ts({depthPacking:3201,morphTargets:t,skinning:e}),o[i]=r),r}function b(t,e,n){const i=t<<0|e<<1|n<<2;let r=l[i];return void 0===r&&(r=new es({morphTargets:t,skinning:e}),l[i]=r),r}function w(e,n,i,r,s,a,o){let l=null,h=_,d=e.customDepthMaterial;if(!0===r.isPointLight&&(h=b,d=e.customDistanceMaterial),void 0===d){let t=!1;!0===i.morphTargets&&(t=n.morphAttributes&&n.morphAttributes.position&&n.morphAttributes.position.length>0);let r=!1;!0===e.isSkinnedMesh&&(!0===i.skinning?r=!0:console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",e));l=h(t,r,!0===e.isInstancedMesh)}else l=d;if(t.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){const t=l.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=l.clone(),n[e]=r),l=r}return l.visible=i.visible,l.wireframe=i.wireframe,l.side=3===o?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],l.clipShadows=i.clipShadows,l.clippingPlanes=i.clippingPlanes,l.clipIntersection=i.clipIntersection,l.wireframeLinewidth=i.wireframeLinewidth,l.linewidth=i.linewidth,!0===r.isPointLight&&!0===l.isMeshDistanceMaterial&&(l.referencePosition.setFromMatrixPosition(r.matrixWorld),l.nearDistance=s,l.farDistance=a),l}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/f.x),r.x=s.x*f.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/f.y),r.y=s.y*f.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 gt(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.mapPass=new gt(r.x,r.y,t),u.camera.updateProjectionMatrix()}if(null===u.map){const t={minFilter:p,magFilter:p,format:E};u.map=new gt(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const m=u.getViewportCount();for(let t=0;t=1):-1!==R.indexOf("OpenGL ES")&&(L=parseFloat(/^OpenGL ES (\d)/.exec(R)[1]),A=L>=2);let C=null,P={};const D=new mt(0,0,t.canvas.width,t.canvas.height),I=new mt(0,0,t.canvas.width,t.canvas.height);function N(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?ot.floorPowerOfTwo:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===P&&(P=I(s,a));const o=n?I(s,a):P;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 ot.isPowerOfTwo(t.width)&&ot.isPowerOfTwo(t.height)}function O(t,e){return t.generateMipmaps&&e&&t.minFilter!==p&&t.minFilter!==g}function z(e,n,r,s){t.generateMipmap(e);i.get(n).__maxMipLevel=Math.log2(Math.max(r,s))}function F(n,i,r){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 s=i;return 6403===i&&(5126===r&&(s=33326),5131===r&&(s=33325),5121===r&&(s=33321)),6407===i&&(5126===r&&(s=34837),5131===r&&(s=34843),5121===r&&(s=32849)),6408===i&&(5126===r&&(s=34836),5131===r&&(s=34842),5121===r&&(s=32856)),33325!==s&&33326!==s&&34842!==s&&34836!==s||e.get("EXT_color_buffer_float"),s}function H(t){return t===p||t===f||t===m?9728:9729}function U(e){const n=e.target;n.removeEventListener("dispose",U),function(e){const n=i.get(e);if(void 0===n.__webglInit)return;t.deleteTexture(n.__webglTexture),i.remove(e)}(n),n.isVideoTexture&&C.delete(n),a.memory.textures--}function G(e){const n=e.target;n.removeEventListener("dispose",G),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);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);i.remove(n),i.remove(e)}(n),a.memory.textures--}let k=0;function V(t,e){const r=i.get(t);if(t.isVideoTexture&&function(t){const e=a.render.frame;C.get(t)!==e&&(C.set(t,e),t.update())}(t),t.version>0&&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 Z(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 W(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,i,r){if(6!==i.image.length)return;Y(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]:N(i.image[t],!1,!0,c);const u=h[0],d=B(u)||o,p=s.convert(i.format),f=s.convert(i.type),m=F(i.internalFormat,p,f);let g;if(X(34067,i,d),a){for(let t=0;t<6;t++){g=h[t].mipmaps;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 Y(e,n){void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",U),e.__webglTexture=t.createTexture(),a.memory.textures++)}function Z(e,i,r){let a=3553;i.isDataTexture2DArray&&(a=35866),i.isDataTexture3D&&(a=32879),Y(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=N(i.image,l,!1,x),h=B(c)||o,d=s.convert(i.format);let f,m=s.convert(i.type),v=F(i.internalFormat,d,m);X(a,i,h);const y=i.mipmaps;if(i.isDepthTexture)v=6402,o?v=i.type===w?36012:i.type===b?33190:i.type===S?35056:33189:i.type===w&&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=_,m=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,m=s.convert(i.type))),n.texImage2D(3553,0,v,c.width,c.height,0,d,m,null);else if(i.isDataTexture)if(y.length>0&&h){for(let t=0,e=y.length;t0&&h){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),k+=1,t},this.resetTextureUnits=function(){k=0},this.setTexture2D=V,this.setTexture2DArray=function(t,e){const r=i.get(t);t.version>0&&r.__version!==t.version?Z(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?Z(r,t,e):(n.activeTexture(33984+e),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=W,this.setupRenderTarget=function(e){const r=e.texture,l=i.get(e),c=i.get(r);e.addEventListener("dispose",G),c.__webglTexture=t.createTexture(),c.__version=r.version,a.memory.textures++;const h=!0===e.isWebGLCubeRenderTarget,u=!0===e.isWebGLMultisampleRenderTarget,d=r.isDataTexture3D||r.isDataTexture2DArray,p=B(e)||o;if(!o||r.format!==T||r.type!==w&&r.type!==M||(r.format=E,console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.")),h){l.__webglFramebuffer=[];for(let e=0;e<6;e++)l.__webglFramebuffer[e]=t.createFramebuffer()}else if(l.__webglFramebuffer=t.createFramebuffer(),u)if(o){l.__webglMultisampledFramebuffer=t.createFramebuffer(),l.__webglColorRenderbuffer=t.createRenderbuffer(),t.bindRenderbuffer(36161,l.__webglColorRenderbuffer);const i=s.convert(r.format),a=s.convert(r.type),o=F(r.internalFormat,i,a),c=$(e);t.renderbufferStorageMultisample(36161,c,o,e.width,e.height),n.bindFramebuffer(36160,l.__webglMultisampledFramebuffer),t.framebufferRenderbuffer(36160,36064,36161,l.__webglColorRenderbuffer),t.bindRenderbuffer(36161,null),e.depthBuffer&&(l.__webglDepthRenderbuffer=t.createRenderbuffer(),Q(l.__webglDepthRenderbuffer,e,!0)),n.bindFramebuffer(36160,null)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");if(h){n.bindTexture(34067,c.__webglTexture),X(34067,r,p);for(let t=0;t<6;t++)J(l.__webglFramebuffer[t],e,36064,34069+t);O(r,p)&&z(34067,r,e.width,e.height),n.bindTexture(34067,null)}else{let t=3553;if(d)if(o){t=r.isDataTexture3D?32879:35866}else console.warn("THREE.DataTexture3D and THREE.DataTexture2DArray only supported with WebGL2.");n.bindTexture(t,c.__webglTexture),X(t,r,p),J(l.__webglFramebuffer,e,36064,t),O(r,p)&&z(3553,r,e.width,e.height),n.bindTexture(3553,null)}e.depthBuffer&&K(e)},this.updateRenderTargetMipmap=function(t){const e=t.texture;if(O(e,B(t)||o)){const r=t.isWebGLCubeRenderTarget?34067:3553,s=i.get(e).__webglTexture;n.bindTexture(r,s),z(r,e,t.width,t.height),n.bindTexture(r,null)}},this.updateMultisampleRenderTarget=function(e){if(e.isWebGLMultisampleRenderTarget)if(o){const r=i.get(e);n.bindFramebuffer(36008,r.__webglMultisampledFramebuffer),n.bindFramebuffer(36009,r.__webglFramebuffer);const s=e.width,a=e.height;let o=16384;e.depthBuffer&&(o|=256),e.stencilBuffer&&(o|=1024),t.blitFramebuffer(0,0,s,a,0,0,s,a,o,9728),n.bindFramebuffer(36160,r.__webglMultisampledFramebuffer)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.")},this.safeSetTexture2D=function(t,e){t&&t.isWebGLRenderTarget&&(!1===tt&&(console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead."),tt=!0),t=t.texture),V(t,e)},this.safeSetTextureCube=function(t,e){t&&t.isWebGLCubeRenderTarget&&(!1===et&&(console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead."),et=!0),t=t.texture),W(t,e)}}function ss(t,e,n){const i=n.isWebGL2;return{convert:function(t){let n;if(t===x)return 5121;if(1017===t)return 32819;if(1018===t)return 32820;if(1019===t)return 33635;if(1010===t)return 5120;if(1011===t)return 5122;if(t===_)return 5123;if(1013===t)return 5124;if(t===b)return 5125;if(t===w)return 5126;if(t===M)return i?5131:(n=e.get("OES_texture_half_float"),null!==n?n.HALF_FLOAT_OES:null);if(1021===t)return 6406;if(t===T)return 6407;if(t===E)return 6408;if(1024===t)return 6409;if(1025===t)return 6410;if(t===A)return 6402;if(t===L)return 34041;if(1028===t)return 6403;if(1029===t)return 36244;if(1030===t)return 33319;if(1031===t)return 33320;if(1032===t)return 36248;if(1033===t)return 36249;if(t===R||t===C||t===P||t===D){if(n=e.get("WEBGL_compressed_texture_s3tc"),null===n)return null;if(t===R)return n.COMPRESSED_RGB_S3TC_DXT1_EXT;if(t===C)return n.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(t===P)return n.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(t===D)return n.COMPRESSED_RGBA_S3TC_DXT5_EXT}if(t===I||t===N||t===B||t===O){if(n=e.get("WEBGL_compressed_texture_pvrtc"),null===n)return null;if(t===I)return n.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(t===N)return n.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(t===B)return n.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(t===O)return n.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(36196===t)return n=e.get("WEBGL_compressed_texture_etc1"),null!==n?n.COMPRESSED_RGB_ETC1_WEBGL:null;if((t===z||t===F)&&(n=e.get("WEBGL_compressed_texture_etc"),null!==n)){if(t===z)return n.COMPRESSED_RGB8_ETC2;if(t===F)return n.COMPRESSED_RGBA8_ETC2_EAC}return 37808===t||37809===t||37810===t||37811===t||37812===t||37813===t||37814===t||37815===t||37816===t||37817===t||37818===t||37819===t||37820===t||37821===t||37840===t||37841===t||37842===t||37843===t||37844===t||37845===t||37846===t||37847===t||37848===t||37849===t||37850===t||37851===t||37852===t||37853===t?(n=e.get("WEBGL_compressed_texture_astc"),null!==n?t:null):36492===t?(n=e.get("EXT_texture_compression_bptc"),null!==n?t:null):t===S?i?34042:(n=e.get("WEBGL_depth_texture"),null!==n?n.UNSIGNED_INT_24_8_WEBGL:null):void 0}}}class as extends Vn{constructor(t=[]){super(),this.cameras=t}}as.prototype.isArrayCamera=!0;class os extends be{constructor(){super(),this.type="Group"}}function ls(){this._targetRay=null,this._grip=null,this._hand=null}function cs(t,e){const n=this,i=t.state;let r=null,s=1,a=null,o="local-floor",l=null;const c=[],h=new Map,u=new Vn;u.layers.enable(1),u.viewport=new mt;const d=new Vn;d.layers.enable(2),d.viewport=new mt;const p=[u,d],f=new as;f.layers.enable(1),f.layers.enable(2);let m=null,g=null;function v(t){const e=h.get(t.inputSource);e&&e.dispatchEvent({type:t.type,data:t.inputSource})}function y(){h.forEach((function(t,e){t.disconnect(e)})),h.clear(),m=null,g=null,i.bindXRFramebuffer(null),t.setRenderTarget(t.getRenderTarget()),S.stop(),n.isPresenting=!1,n.dispatchEvent({type:"sessionend"})}function x(t){const e=r.inputSources;for(let t=0;t0&&Rt(s,t,e),a.length>0&&Rt(a,t,e),null!==_&&(J.updateRenderTargetMipmap(_),J.updateMultisampleRenderTarget(_)),!0===t.isScene&&t.onAfterRender(m,t,e),q.buffers.depth.setTest(!0),q.buffers.depth.setMask(!0),q.buffers.color.setMask(!0),q.setPolygonOffset(!1),ft.resetDefaultState(),b=-1,S=null,f.pop(),d=f.length>0?f[f.length-1]:null,p.pop(),u=p.length>0?p[p.length-1]:null},this.getActiveCubeFace=function(){return v},this.getActiveMipmapLevel=function(){return y},this.getRenderTarget=function(){return _},this.setRenderTarget=function(t,e=0,n=0){_=t,v=e,y=n,t&&void 0===Z.get(t).__webglFramebuffer&&J.setupRenderTarget(t);let i=null,r=!1,s=!1;if(t){const n=t.texture;(n.isDataTexture3D||n.isDataTexture2DArray)&&(s=!0);const a=Z.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(i=a[e],r=!0):i=t.isWebGLMultisampleRenderTarget?Z.get(t).__webglMultisampledFramebuffer:a,T.copy(t.viewport),A.copy(t.scissor),L=t.scissorTest}else T.copy(N).multiplyScalar(P).floor(),A.copy(B).multiplyScalar(P).floor(),L=O;if(q.bindFramebuffer(36160,i),q.viewport(T),q.scissor(A),q.setScissorTest(L),r){const i=Z.get(t.texture);gt.framebufferTexture2D(36160,36064,34069+e,i.__webglTexture,n)}else if(s){const i=Z.get(t.texture),r=e||0;gt.framebufferTextureLayer(36160,36064,i.__webglTexture,n||0,r)}},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=Z.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){q.bindFramebuffer(36160,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==E&&pt.convert(o)!==gt.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===M&&(W.has("EXT_color_buffer_half_float")||j.isWebGL2&&W.has("EXT_color_buffer_float"));if(!(l===x||pt.convert(l)===gt.getParameter(35738)||l===w&&(j.isWebGL2||W.has("OES_texture_float")||W.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");36053===gt.checkFramebufferStatus(36160)?e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&>.readPixels(e,n,i,r,pt.convert(o),pt.convert(l),s):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{const t=null!==_?Z.get(_).__webglFramebuffer:null;q.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i),a=pt.convert(e.format);J.setTexture2D(e,0),gt.copyTexImage2D(3553,n,a,t.x,t.y,r,s,0),q.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=pt.convert(n.format),o=pt.convert(n.type);J.setTexture2D(n,0),gt.pixelStorei(37440,n.flipY),gt.pixelStorei(37441,n.premultiplyAlpha),gt.pixelStorei(3317,n.unpackAlignment),e.isDataTexture?gt.texSubImage2D(3553,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?gt.compressedTexSubImage2D(3553,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):gt.texSubImage2D(3553,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&>.generateMipmap(3553),q.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(m.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const{width:s,height:a,data:o}=n.image,l=pt.convert(i.format),c=pt.convert(i.type);let h;if(i.isDataTexture3D)J.setTexture3D(i,0),h=32879;else{if(!i.isDataTexture2DArray)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");J.setTexture2DArray(i,0),h=35866}gt.pixelStorei(37440,i.flipY),gt.pixelStorei(37441,i.premultiplyAlpha),gt.pixelStorei(3317,i.unpackAlignment);const u=gt.getParameter(3314),d=gt.getParameter(32878),p=gt.getParameter(3316),f=gt.getParameter(3315),g=gt.getParameter(32877);gt.pixelStorei(3314,s),gt.pixelStorei(32878,a),gt.pixelStorei(3316,t.min.x),gt.pixelStorei(3315,t.min.y),gt.pixelStorei(32877,t.min.z),gt.texSubImage3D(h,r,e.x,e.y,e.z,t.max.x-t.min.x+1,t.max.y-t.min.y+1,t.max.z-t.min.z+1,l,c,o),gt.pixelStorei(3314,u),gt.pixelStorei(32878,d),gt.pixelStorei(3316,p),gt.pixelStorei(3315,f),gt.pixelStorei(32877,g),0===r&&i.generateMipmaps&>.generateMipmap(h),q.unbindTexture()},this.initTexture=function(t){J.setTexture2D(t,0),q.unbindTexture()},this.resetState=function(){v=0,y=0,_=null,q.reset(),ft.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}os.prototype.isGroup=!0,Object.assign(ls.prototype,{constructor:ls,getHandSpace:function(){return null===this._hand&&(this._hand=new os,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand},getTargetRaySpace:function(){return null===this._targetRay&&(this._targetRay=new os,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1),this._targetRay},getGripSpace:function(){return null===this._grip&&(this._grip=new os,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1),this._grip},dispatchEvent:function(t){return null!==this._targetRay&&this._targetRay.dispatchEvent(t),null!==this._grip&&this._grip.dispatchEvent(t),null!==this._hand&&this._hand.dispatchEvent(t),this},disconnect:function(t){return this.dispatchEvent({type:"disconnected",data:t}),null!==this._targetRay&&(this._targetRay.visible=!1),null!==this._grip&&(this._grip.visible=!1),null!==this._hand&&(this._hand.visible=!1),this},update:function(t,e,n){let i=null,r=null,s=null;const a=this._targetRay,o=this._grip,l=this._hand;if(t&&"visible-blurred"!==e.session.visibilityState)if(null!==a&&(i=e.getPose(t.targetRaySpace,n),null!==i&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale))),l&&t.hand){s=!0;for(const i of t.hand.values()){const t=e.getJointPose(i,n);if(void 0===l.joints[i.jointName]){const t=new os;t.matrixAutoUpdate=!1,t.visible=!1,l.joints[i.jointName]=t,l.add(t)}const r=l.joints[i.jointName];null!==t&&(r.matrix.fromArray(t.transform.matrix),r.matrix.decompose(r.position,r.rotation,r.scale),r.jointRadius=t.radius),r.visible=null!==t}const i=l.joints["index-finger-tip"],r=l.joints["thumb-tip"],a=i.position.distanceTo(r.position),o=.02,c=.005;l.inputState.pinching&&a>o+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)));return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}}),Object.assign(cs.prototype,rt.prototype);class ds extends us{}ds.prototype.isWebGL1Renderer=!0;class ps{constructor(t,e=25e-5){this.name="",this.color=new je(t),this.density=e}clone(){return new ps(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}ps.prototype.isFogExp2=!0;class fs{constructor(t,e=1,n=1e3){this.name="",this.color=new je(t),this.near=e,this.far=n}clone(){return new fs(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}fs.prototype.isFog=!0;class ms 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.background&&(e.object.background=this.background.toJSON(t)),null!==this.environment&&(e.object.environment=this.environment.toJSON(t)),null!==this.fog&&(e.object.fog=this.fog.toJSON()),e}}function gs(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=ot.generateUUID()}ms.prototype.isScene=!0,Object.defineProperty(gs.prototype,"needsUpdate",{set:function(t){!0===t&&this.version++}}),Object.assign(gs.prototype,{isInterleavedBuffer:!0,onUploadCallback:function(){},setUsage:function(t){return this.usage=t,this},copy:function(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this},copyAt:function(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:bs.clone(),uv:Oe.getUV(bs,As,Ls,Rs,Cs,Ps,Ds,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 Ns(t,e,n,i,r,s){Ss.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(Ts.x=s*Ss.x-r*Ss.y,Ts.y=r*Ss.x+s*Ss.y):Ts.copy(Ss),t.copy(e),t.x+=Ts.x,t.y+=Ts.y,t.applyMatrix4(Es)}Is.prototype.isSprite=!0;const Bs=new xt,Os=new xt;class zs 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){Bs.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(Bs);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Bs.setFromMatrixPosition(t.matrixWorld),Os.setFromMatrixPosition(this.matrixWorld);const n=Bs.distanceTo(Os)/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:function(){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.")}}});const aa=new xt,oa=new xt;function la(t,e){sa.call(this,t,e),this.type="LineSegments"}la.prototype=Object.assign(Object.create(sa.prototype),{constructor:la,isLineSegments:!0,computeLineDistances:function(){const t=this.geometry;if(t.isBufferGeometry)if(null===t.index){const e=t.attributes.position,n=[];for(let t=0,i=e.count;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}ma.prototype=Object.assign(Object.create(be.prototype),{constructor:ma,isPoints:!0,copy:function(t){return be.prototype.copy.call(this,t),this.material=t.material,this.geometry=t.geometry,this},raycast:function(t,e){const n=this.geometry,i=this.matrixWorld,r=t.params.Points.threshold,s=n.drawRange;if(null===n.boundingSphere&&n.computeBoundingSphere(),pa.copy(n.boundingSphere),pa.applyMatrix4(i),pa.radius+=r,!1===t.ray.intersectsSphere(pa))return;ua.copy(i).invert(),da.copy(t.ray).applyMatrix4(ua);const a=r/((this.scale.x+this.scale.y+this.scale.z)/3),o=a*a;if(n.isBufferGeometry){const r=n.index,a=n.attributes.position;if(null!==r){for(let n=Math.max(0,s.start),l=Math.min(r.count,s.start+s.count);n0){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.")}}});class va extends pt{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)}}va.prototype.isVideoTexture=!0;class ya extends pt{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}}ya.prototype.isCompressedTexture=!0;class xa extends pt{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.needsUpdate=!0}}xa.prototype.isCanvasTexture=!0;class _a extends pt{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}}_a.prototype.isDepthTexture=!0;class ba extends vn{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 xt,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 sn(s,3)),this.setAttribute("normal",new sn(a,3)),this.setAttribute("uv",new sn(o,2))}}class wa extends vn{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 f=[],m=n/2;let g=0;function v(n){const r=p,s=new lt,f=new xt;let v=0;const y=!0===n?t:e,x=!0===n?1:-1;for(let t=1;t<=i;t++)h.push(0,m*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);f.x=y*r,f.y=m*x,f.z=y*n,h.push(f.x,f.y,f.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 sn(h,3)),this.setAttribute("normal",new sn(u,3)),this.setAttribute("uv",new sn(d,2))}}class Ma extends wa{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}}}class Sa extends vn{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 sn(r,3)),this.setAttribute("normal",new sn(r.slice(),3)),this.setAttribute("uv",new sn(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}}class Ta extends Sa{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}}}const Ea=new xt,Aa=new xt,La=new xt,Ra=new Oe;class Ca extends vn{constructor(t,e){if(super(),this.type="EdgesGeometry",this.parameters={thresholdAngle:e},e=void 0!==e?e:1,!0===t.isGeometry)return void console.error("THREE.EdgesGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");const n=Math.pow(10,4),i=Math.cos(ot.DEG2RAD*e),r=t.getIndex(),s=t.getAttribute("position"),a=r?r.count:s.count,o=[0,0,0],l=["a","b","c"],c=new Array(3),h={},u=[];for(let t=0;t80*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 Na(s,a,n,o,l,p),a};function Da(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=$a(s,t[s],t[s+1],a);return a&&Xa(a,a.next)&&(to(a),a=a.next),a}function Ia(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!Xa(i,i.next)&&0!==qa(i.prev,i,i.next))i=i.next;else{if(to(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Na(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=ka(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?Oa(t,i,r,s):Ba(t))e.push(o.i/n),e.push(t.i/n),e.push(l.i/n),to(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Na(t=za(Ia(t),e,n),e,n,i,r,s,2):2===a&&Fa(t,e,n,i,r,s):Na(Ia(t),e,n,i,r,s,1);break}}function Ba(t){const e=t.prev,n=t,i=t.next;if(qa(e,n,i)>=0)return!1;let r=t.next.next;for(;r!==t.prev;){if(Wa(e.x,e.y,n.x,n.y,i.x,i.y,r.x,r.y)&&qa(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function Oa(t,e,n,i){const r=t.prev,s=t,a=t.next;if(qa(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=ka(o,l,e,n,i),d=ka(c,h,e,n,i);let p=t.prevZ,f=t.nextZ;for(;p&&p.z>=u&&f&&f.z<=d;){if(p!==t.prev&&p!==t.next&&Wa(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&qa(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,f!==t.prev&&f!==t.next&&Wa(r.x,r.y,s.x,s.y,a.x,a.y,f.x,f.y)&&qa(f.prev,f,f.next)>=0)return!1;f=f.nextZ}for(;p&&p.z>=u;){if(p!==t.prev&&p!==t.next&&Wa(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&qa(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;f&&f.z<=d;){if(f!==t.prev&&f!==t.next&&Wa(r.x,r.y,s.x,s.y,a.x,a.y,f.x,f.y)&&qa(f.prev,f,f.next)>=0)return!1;f=f.nextZ}return!0}function za(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!Xa(r,s)&&Ya(r,i,i.next,s)&&Qa(r,s)&&Qa(s,r)&&(e.push(r.i/n),e.push(i.i/n),e.push(s.i/n),to(i),to(i.next),i=t=s),i=i.next}while(i!==t);return Ia(i)}function Fa(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&ja(a,t)){let o=Ka(a,t);return a=Ia(a,a.next),o=Ia(o,o.next),Na(a,e,n,i,r,s),void Na(o,e,n,i,r,s)}t=t.next}a=a.next}while(a!==t)}function Ha(t,e){return t.x-e.x}function Ua(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&&Wa(rs.x||n.x===s.x&&Ga(s,n)))&&(s=n,u=h)),n=n.next}while(n!==o);return s}(t,e)){const n=Ka(e,t);Ia(e,e.next),Ia(n,n.next)}}function Ga(t,e){return qa(t.prev,t,e.prev)<0&&qa(e.next,t,t.next)<0}function ka(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 Va(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 ja(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&&Ya(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(Qa(t,e)&&Qa(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)&&(qa(t.prev,t,e.prev)||qa(t,e.prev,e))||Xa(t,e)&&qa(t.prev,t,t.next)>0&&qa(e.prev,e,e.next)>0)}function qa(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function Xa(t,e){return t.x===e.x&&t.y===e.y}function Ya(t,e,n,i){const r=Ja(qa(t,e,n)),s=Ja(qa(t,e,i)),a=Ja(qa(n,i,t)),o=Ja(qa(n,i,e));return r!==s&&a!==o||(!(0!==r||!Za(t,n,e))||(!(0!==s||!Za(t,i,e))||(!(0!==a||!Za(n,t,i))||!(0!==o||!Za(n,e,i)))))}function Za(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 Ja(t){return t>0?1:t<0?-1:0}function Qa(t,e){return qa(t.prev,t,t.next)<0?qa(t,e,t.next)>=0&&qa(t,t.prev,e)>=0:qa(t,e,t.prev)<0||qa(t,t.next,e)<0}function Ka(t,e){const n=new eo(t.i,t.x,t.y),i=new eo(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 $a(t,e,n,i){const r=new eo(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 to(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 eo(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}const no={area:function(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 ro(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,f=e.y+a/u,m=((n.x-c/d-p)*c-(n.y+l/d-f)*l)/(a*c-o*l);i=p+a*m-t.x,r=f+o*m-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;t=0?(t(i-o,p,h),u.subVectors(c,h)):(t(i+o,p,h),u.subVectors(h,c)),p-o>=0?(t(i,p-o,h),d.subVectors(c,h)):(t(i,p+o,h),d.subVectors(h,c)),l.crossVectors(u,d).normalize(),s.push(l.x,l.y,l.z),a.push(i,p)}}for(let t=0;t0)&&d.push(e,r,l),(t!==n-1||o=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=Io.arraySlice(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=Io.arraySlice(t.resultBuffer,e,n)}if("quaternion"===r){(new yt).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=Io.arraySlice(n,r,s),this.values=Io.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&&Io.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=Io.arraySlice(this.times),e=Io.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=Io.arraySlice(t,0,s),this.values=Io.arraySlice(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=Io.arraySlice(this.times,0),e=Io.arraySlice(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Fo.prototype.TimeBufferType=Float32Array,Fo.prototype.ValueBufferType=Float32Array,Fo.prototype.DefaultInterpolation=U;class Ho extends Fo{}Ho.prototype.ValueTypeName="bool",Ho.prototype.ValueBufferType=Array,Ho.prototype.DefaultInterpolation=H,Ho.prototype.InterpolantFactoryMethodLinear=void 0,Ho.prototype.InterpolantFactoryMethodSmooth=void 0;class Uo extends Fo{}Uo.prototype.ValueTypeName="color";class Go extends Fo{}function ko(t,e,n,i){No.call(this,t,e,n,i)}Go.prototype.ValueTypeName="number",ko.prototype=Object.assign(Object.create(No.prototype),{constructor:ko,interpolate_:function(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)yt.slerpFlat(r,0,s,l-a,s,l,o);return r}});class Vo extends Fo{InterpolantFactoryMethodLinear(t){return new ko(this.times,this.values,this.getValueSize(),t)}}Vo.prototype.ValueTypeName="quaternion",Vo.prototype.DefaultInterpolation=U,Vo.prototype.InterpolantFactoryMethodSmooth=void 0;class Wo extends Fo{}Wo.prototype.ValueTypeName="string",Wo.prototype.ValueBufferType=Array,Wo.prototype.DefaultInterpolation=H,Wo.prototype.InterpolantFactoryMethodLinear=void 0,Wo.prototype.InterpolantFactoryMethodSmooth=void 0;class jo extends Fo{}jo.prototype.ValueTypeName="vector";class qo{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=ot.generateUUID(),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(Xo(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(Fo.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=[];Io.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;t0||0===t.search(/^data\:image\/jpeg/);r.format=i?T:E,r.needsUpdate=!0,void 0!==e&&e(r)}),n,i),r}}),Object.assign(sl.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)},getPoints:function(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e},getSpacedPoints:function(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e},getLength:function(){const t=this.getLengths();return t[t.length-1]},getLengths:function(t){if(void 0===t&&(t=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){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:function(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 xt);return o.copy(a).sub(s).normalize(),o},getTangentAt:function(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)},computeFrenetFrames:function(t,e){const n=new xt,i=[],r=[],s=[],a=new xt,o=new Jt;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new xt),i[e].normalize()}r[0]=new xt,s[0]=new xt;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(ot.clamp(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(ot.clamp(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:function(){return(new this.constructor).copy(this)},copy:function(t){return this.arcLengthDivisions=t.arcLengthDivisions,this},toJSON:function(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t},fromJSON:function(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}});class al extends sl{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]:(cl.subVectors(i[0],i[1]).add(i[0]),a=cl);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(fl(a,o.x,l.x,c.x,h.x),fl(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=e){const t=n[i]-e,r=this.curves[i],s=r.getLength(),a=0===s?0:1-t/s;return r.getPointAt(a)}i++}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 Al extends El{constructor(t){super(t),this.uuid=ot.generateUUID(),this.type="Shape",this.holes=[]}getPointsHoles(t){const e=[];for(let n=0,i=this.holes.length;n0: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 je).setHex(r.value);break;case"v2":i.uniforms[e].value=(new lt).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new xt).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new mt).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new ct).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new Jt).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.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.transmission&&(i.transmission=t.transmission),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),i}setTextures(t){return this.textures=t,this}}const Zl={decodeText:function(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;nNumber.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=no.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 Al,l.curves=o.curves,c.push(l),c;let h=!r(s[0].getPoints());h=t?!h:h;const u=[],d=[];let p,f,m=[],g=0;d[g]=void 0,m[g]=[];for(let e=0,n=s.length;e1){let t=!1;const e=[];for(let t=0,e=d.length;t0&&(t||(m=u))}for(let t=0,e=d.length;t0){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){yt.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;yt.multiplyQuaternionsFlat(t,s,t,e,t,n),yt.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 Ec="\\[\\]\\.:\\/",Ac=new RegExp("[\\[\\]\\.:\\/]","g"),Lc="[^\\[\\]\\.:\\/]",Rc="[^"+Ec.replace("\\.","")+"]",Cc=/((?:WC+[\/:])*)/.source.replace("WC",Lc),Pc=/(WCOD+)?/.source.replace("WCOD",Rc),Dc=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",Lc),Ic=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",Lc),Nc=new RegExp("^"+Cc+Pc+Dc+Ic+"$"),Bc=["material","materials","bones"];function Oc(t,e,n){const i=n||zc.parseTrackName(e);this._targetGroup=t,this._bindings=t.subscribe_(e,i)}function zc(t,e,n){this.path=e,this.parsedPath=n||zc.parseTrackName(e),this.node=zc.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t}Object.assign(Oc.prototype,{getValue:function(t,e){this.bind();const n=this._targetGroup.nCachedObjects_,i=this._bindings[n];void 0!==i&&i.getValue(t,e)},setValue:function(t,e){const n=this._bindings;for(let i=this._targetGroup.nCachedObjects_,r=n.length;i!==r;++i)n[i].setValue(t,e)},bind:function(){const t=this._bindings;for(let e=this._targetGroup.nCachedObjects_,n=t.length;e!==n;++e)t[e].bind()},unbind:function(){const t=this._bindings;for(let e=this._targetGroup.nCachedObjects_,n=t.length;e!==n;++e)t[e].unbind()}}),Object.assign(zc,{Composite:Oc,create:function(t,e,n){return t&&t.isAnimationObjectGroup?new zc.Composite(t,e,n):new zc(t,e,n)},sanitizeNodeName:function(t){return t.replace(/\s/g,"_").replace(Ac,"")},parseTrackName:function(t){const e=Nc.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!==Bc.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},findNode:function(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 zc(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()}}}Fc.prototype.isAnimationObjectGroup=!0;class Hc{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;switch(this.blendMode){case q:for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);break;case j:default: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 Uc 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 Tc(zc.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 void 0===e&&(console.warn("THREE.Box2: .getParameter() target is now required"),e=new lt),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 void 0===e&&(console.warn("THREE.Box2: .clampPoint() target is now required"),e=new lt),e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return Xc.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)}}Yc.prototype.isBox2=!0;const Zc=new xt,Jc=new xt;class Qc{constructor(t=new xt,e=new xt){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 void 0===t&&(console.warn("THREE.Line3: .getCenter() target is now required"),t=new xt),t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return void 0===t&&(console.warn("THREE.Line3: .delta() target is now required"),t=new xt),t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return void 0===e&&(console.warn("THREE.Line3: .at() target is now required"),e=new xt),this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Zc.subVectors(t,this.start),Jc.subVectors(this.end,this.start);const n=Jc.dot(Jc);let i=Jc.dot(Zc)/n;return e&&(i=ot.clamp(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return void 0===n&&(console.warn("THREE.Line3: .closestPointToPoint() target is now required"),n=new xt),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)}}function Kc(t){be.call(this),this.material=t,this.render=function(){},this.hasPositions=!1,this.hasNormals=!1,this.hasColors=!1,this.hasUvs=!1,this.positionArray=null,this.normalArray=null,this.colorArray=null,this.uvArray=null,this.count=0}Kc.prototype=Object.create(be.prototype),Kc.prototype.constructor=Kc,Kc.prototype.isImmediateRenderObject=!0;const $c=new xt;const th=new xt,eh=new Jt,nh=new Jt;class ih extends la{constructor(t){const e=rh(t),n=new vn,i=[],r=[],s=new je(0,0,1),a=new je(0,1,0);for(let t=0;t>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)}},Sh=Math.pow(2,8),Th=[.125,.215,.35,.446,.526,.582],Eh=5+Th.length,Ah=20,Lh={[X]:0,[Y]:1,[J]:2,[Q]:3,[K]:4,[$]:5,[Z]:6},Rh=new qe({side:1,depthWrite:!1,depthTest:!1}),Ch=new Bn(new zn,Rh),Ph=new Gl,{_lodPlanes:Dh,_sizeLods:Ih,_sigmas:Nh}=kh(),Bh=new je;let Oh=null;const zh=(1+Math.sqrt(5))/2,Fh=1/zh,Hh=[new xt(1,1,1),new xt(-1,1,1),new xt(1,1,-1),new xt(-1,1,-1),new xt(0,zh,Fh),new xt(0,zh,-Fh),new xt(Fh,0,zh),new xt(-Fh,0,zh),new xt(zh,Fh,0),new xt(-zh,Fh,0)];function Uh(t){const e=Math.max(t.r,t.g,t.b),n=Math.min(Math.max(Math.ceil(Math.log2(e)),-128),127);t.multiplyScalar(Math.pow(2,-n));return(n+128)/255}function Gh(t){return void 0!==t&&t.type===x&&(t.encoding===X||t.encoding===Y||t.encoding===Z)}function kh(){const t=[],e=[],n=[];let i=8;for(let r=0;r4?a=Th[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,f=2,m=1,g=new Float32Array(p*d*u),v=new Float32Array(f*d*u),y=new Float32Array(m*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,f*d*t);const r=[t,t,t,t,t,t];y.set(r,m*d*t)}const x=new vn;x.setAttribute("position",new Ze(g,p)),x.setAttribute("uv",new Ze(v,f)),x.setAttribute("faceIndex",new Ze(y,m)),t.push(x),i>4&&i--}return{_lodPlanes:t,_sizeLods:e,_sigmas:n}}function Vh(t){const e=new gt(3*Sh,3*Sh,t);return e.texture.mapping=l,e.texture.name="PMREM.cubeUv",e.scissorTest=!0,e}function Wh(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function jh(){const t=new lt(1,1);return new Mo({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null},texelSize:{value:t},inputEncoding:{value:Lh[3e3]},outputEncoding:{value:Lh[3e3]}},vertexShader:Xh(),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${Yh()}\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 qh(){return new Mo({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},inputEncoding:{value:Lh[3e3]},outputEncoding:{value:Lh[3e3]}},vertexShader:Xh(),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${Yh()}\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 Xh(){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 Yh(){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"}sl.create=function(t,e){return console.log("THREE.Curve.create() has been deprecated"),t.prototype=Object.create(sl.prototype),t.prototype.constructor=t,t.prototype.getPoint=e,t},El.prototype.fromPoints=function(t){return console.warn("THREE.Path: .fromPoints() has been renamed to .setFromPoints()."),this.setFromPoints(t)},lh.prototype.setColors=function(){console.error("THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.")},ih.prototype.update=function(){console.error("THREE.SkeletonHelper: update() no longer needs to be called.")},Qo.prototype.extractUrlBase=function(t){return console.warn("THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead."),Zl.extractUrlBase(t)},Qo.Handlers={add:function(){console.error("THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.")},get:function(){console.error("THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.")}},Yc.prototype.center=function(t){return console.warn("THREE.Box2: .center() has been renamed to .getCenter()."),this.getCenter(t)},Yc.prototype.empty=function(){return console.warn("THREE.Box2: .empty() has been renamed to .isEmpty()."),this.isEmpty()},Yc.prototype.isIntersectionBox=function(t){return console.warn("THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox()."),this.intersectsBox(t)},Yc.prototype.size=function(t){return console.warn("THREE.Box2: .size() has been renamed to .getSize()."),this.getSize(t)},wt.prototype.center=function(t){return console.warn("THREE.Box3: .center() has been renamed to .getCenter()."),this.getCenter(t)},wt.prototype.empty=function(){return console.warn("THREE.Box3: .empty() has been renamed to .isEmpty()."),this.isEmpty()},wt.prototype.isIntersectionBox=function(t){return console.warn("THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox()."),this.intersectsBox(t)},wt.prototype.isIntersectionSphere=function(t){return console.warn("THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere()."),this.intersectsSphere(t)},wt.prototype.size=function(t){return console.warn("THREE.Box3: .size() has been renamed to .getSize()."),this.getSize(t)},Gt.prototype.empty=function(){return console.warn("THREE.Sphere: .empty() has been renamed to .isEmpty()."),this.isEmpty()},Qn.prototype.setFromMatrix=function(t){return console.warn("THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix()."),this.setFromProjectionMatrix(t)},Qc.prototype.center=function(t){return console.warn("THREE.Line3: .center() has been renamed to .getCenter()."),this.getCenter(t)},ot.random16=function(){return console.warn("THREE.Math: .random16() has been deprecated. Use Math.random() instead."),Math.random()},ot.nearestPowerOfTwo=function(t){return console.warn("THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo()."),ot.floorPowerOfTwo(t)},ot.nextPowerOfTwo=function(t){return console.warn("THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo()."),ot.ceilPowerOfTwo(t)},ct.prototype.flattenToArrayOffset=function(t,e){return console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead."),this.toArray(t,e)},ct.prototype.multiplyVector3=function(t){return console.warn("THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead."),t.applyMatrix3(this)},ct.prototype.multiplyVector3Array=function(){console.error("THREE.Matrix3: .multiplyVector3Array() has been removed.")},ct.prototype.applyToBufferAttribute=function(t){return console.warn("THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead."),t.applyMatrix3(this)},ct.prototype.applyToVector3Array=function(){console.error("THREE.Matrix3: .applyToVector3Array() has been removed.")},ct.prototype.getInverse=function(t){return console.warn("THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead."),this.copy(t).invert()},Jt.prototype.extractPosition=function(t){return console.warn("THREE.Matrix4: .extractPosition() has been renamed to .copyPosition()."),this.copyPosition(t)},Jt.prototype.flattenToArrayOffset=function(t,e){return console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead."),this.toArray(t,e)},Jt.prototype.getPosition=function(){return console.warn("THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead."),(new xt).setFromMatrixColumn(this,3)},Jt.prototype.setRotationFromQuaternion=function(t){return console.warn("THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion()."),this.makeRotationFromQuaternion(t)},Jt.prototype.multiplyToArray=function(){console.warn("THREE.Matrix4: .multiplyToArray() has been removed.")},Jt.prototype.multiplyVector3=function(t){return console.warn("THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},Jt.prototype.multiplyVector4=function(t){return console.warn("THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},Jt.prototype.multiplyVector3Array=function(){console.error("THREE.Matrix4: .multiplyVector3Array() has been removed.")},Jt.prototype.rotateAxis=function(t){console.warn("THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead."),t.transformDirection(this)},Jt.prototype.crossVector=function(t){return console.warn("THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},Jt.prototype.translate=function(){console.error("THREE.Matrix4: .translate() has been removed.")},Jt.prototype.rotateX=function(){console.error("THREE.Matrix4: .rotateX() has been removed.")},Jt.prototype.rotateY=function(){console.error("THREE.Matrix4: .rotateY() has been removed.")},Jt.prototype.rotateZ=function(){console.error("THREE.Matrix4: .rotateZ() has been removed.")},Jt.prototype.rotateByAxis=function(){console.error("THREE.Matrix4: .rotateByAxis() has been removed.")},Jt.prototype.applyToBufferAttribute=function(t){return console.warn("THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},Jt.prototype.applyToVector3Array=function(){console.error("THREE.Matrix4: .applyToVector3Array() has been removed.")},Jt.prototype.makeFrustum=function(t,e,n,i,r,s){return console.warn("THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead."),this.makePerspective(t,e,i,n,r,s)},Jt.prototype.getInverse=function(t){return console.warn("THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead."),this.copy(t).invert()},Te.prototype.isIntersectionLine=function(t){return console.warn("THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine()."),this.intersectsLine(t)},yt.prototype.multiplyVector3=function(t){return console.warn("THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead."),t.applyQuaternion(this)},yt.prototype.inverse=function(){return console.warn("THREE.Quaternion: .inverse() has been renamed to invert()."),this.invert()},Zt.prototype.isIntersectionBox=function(t){return console.warn("THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox()."),this.intersectsBox(t)},Zt.prototype.isIntersectionPlane=function(t){return console.warn("THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane()."),this.intersectsPlane(t)},Zt.prototype.isIntersectionSphere=function(t){return console.warn("THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere()."),this.intersectsSphere(t)},Oe.prototype.area=function(){return console.warn("THREE.Triangle: .area() has been renamed to .getArea()."),this.getArea()},Oe.prototype.barycoordFromPoint=function(t,e){return console.warn("THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord()."),this.getBarycoord(t,e)},Oe.prototype.midpoint=function(t){return console.warn("THREE.Triangle: .midpoint() has been renamed to .getMidpoint()."),this.getMidpoint(t)},Oe.prototypenormal=function(t){return console.warn("THREE.Triangle: .normal() has been renamed to .getNormal()."),this.getNormal(t)},Oe.prototype.plane=function(t){return console.warn("THREE.Triangle: .plane() has been renamed to .getPlane()."),this.getPlane(t)},Oe.barycoordFromPoint=function(t,e,n,i,r){return console.warn("THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord()."),Oe.getBarycoord(t,e,n,i,r)},Oe.normal=function(t,e,n,i){return console.warn("THREE.Triangle: .normal() has been renamed to .getNormal()."),Oe.getNormal(t,e,n,i)},Al.prototype.extractAllPoints=function(t){return console.warn("THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead."),this.extractPoints(t)},Al.prototype.extrude=function(t){return console.warn("THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead."),new so(this,t)},Al.prototype.makeGeometry=function(t){return console.warn("THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead."),new po(this,t)},lt.prototype.fromAttribute=function(t,e,n){return console.warn("THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute()."),this.fromBufferAttribute(t,e,n)},lt.prototype.distanceToManhattan=function(t){return console.warn("THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo()."),this.manhattanDistanceTo(t)},lt.prototype.lengthManhattan=function(){return console.warn("THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength()."),this.manhattanLength()},xt.prototype.setEulerFromRotationMatrix=function(){console.error("THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.")},xt.prototype.setEulerFromQuaternion=function(){console.error("THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.")},xt.prototype.getPositionFromMatrix=function(t){return console.warn("THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition()."),this.setFromMatrixPosition(t)},xt.prototype.getScaleFromMatrix=function(t){return console.warn("THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale()."),this.setFromMatrixScale(t)},xt.prototype.getColumnFromMatrix=function(t,e){return console.warn("THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn()."),this.setFromMatrixColumn(e,t)},xt.prototype.applyProjection=function(t){return console.warn("THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead."),this.applyMatrix4(t)},xt.prototype.fromAttribute=function(t,e,n){return console.warn("THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute()."),this.fromBufferAttribute(t,e,n)},xt.prototype.distanceToManhattan=function(t){return console.warn("THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo()."),this.manhattanDistanceTo(t)},xt.prototype.lengthManhattan=function(){return console.warn("THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength()."),this.manhattanLength()},mt.prototype.fromAttribute=function(t,e,n){return console.warn("THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute()."),this.fromBufferAttribute(t,e,n)},mt.prototype.lengthManhattan=function(){return console.warn("THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength()."),this.manhattanLength()},be.prototype.getChildByName=function(t){return console.warn("THREE.Object3D: .getChildByName() has been renamed to .getObjectByName()."),this.getObjectByName(t)},be.prototype.renderDepth=function(){console.warn("THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.")},be.prototype.translate=function(t,e){return console.warn("THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead."),this.translateOnAxis(e,t)},be.prototype.getWorldRotation=function(){console.error("THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.")},be.prototype.applyMatrix=function(t){return console.warn("THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4()."),this.applyMatrix4(t)},Object.defineProperties(be.prototype,{eulerOrder:{get:function(){return console.warn("THREE.Object3D: .eulerOrder is now .rotation.order."),this.rotation.order},set:function(t){console.warn("THREE.Object3D: .eulerOrder is now .rotation.order."),this.rotation.order=t}},useQuaternion:{get:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")},set:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")}}}),Bn.prototype.setDrawMode=function(){console.error("THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.")},Object.defineProperties(Bn.prototype,{drawMode:{get:function(){return console.error("THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode."),0},set:function(){console.error("THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.")}}}),Vs.prototype.initBones=function(){console.error("THREE.SkinnedMesh: initBones() has been removed.")},Object.defineProperty(sl.prototype,"__arcLengthDivisions",{get:function(){return console.warn("THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions."),this.arcLengthDivisions},set:function(t){console.warn("THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions."),this.arcLengthDivisions=t}}),Vn.prototype.setLens=function(t,e){console.warn("THREE.PerspectiveCamera.setLens is deprecated. Use .setFocalLength and .filmGauge for a photographic setup."),void 0!==e&&(this.filmGauge=e),this.setFocalLength(t)},Object.defineProperties(Ll.prototype,{onlyShadow:{set:function(){console.warn("THREE.Light: .onlyShadow has been removed.")}},shadowCameraFov:{set:function(t){console.warn("THREE.Light: .shadowCameraFov is now .shadow.camera.fov."),this.shadow.camera.fov=t}},shadowCameraLeft:{set:function(t){console.warn("THREE.Light: .shadowCameraLeft is now .shadow.camera.left."),this.shadow.camera.left=t}},shadowCameraRight:{set:function(t){console.warn("THREE.Light: .shadowCameraRight is now .shadow.camera.right."),this.shadow.camera.right=t}},shadowCameraTop:{set:function(t){console.warn("THREE.Light: .shadowCameraTop is now .shadow.camera.top."),this.shadow.camera.top=t}},shadowCameraBottom:{set:function(t){console.warn("THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom."),this.shadow.camera.bottom=t}},shadowCameraNear:{set:function(t){console.warn("THREE.Light: .shadowCameraNear is now .shadow.camera.near."),this.shadow.camera.near=t}},shadowCameraFar:{set:function(t){console.warn("THREE.Light: .shadowCameraFar is now .shadow.camera.far."),this.shadow.camera.far=t}},shadowCameraVisible:{set:function(){console.warn("THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.")}},shadowBias:{set:function(t){console.warn("THREE.Light: .shadowBias is now .shadow.bias."),this.shadow.bias=t}},shadowDarkness:{set:function(){console.warn("THREE.Light: .shadowDarkness has been removed.")}},shadowMapWidth:{set:function(t){console.warn("THREE.Light: .shadowMapWidth is now .shadow.mapSize.width."),this.shadow.mapSize.width=t}},shadowMapHeight:{set:function(t){console.warn("THREE.Light: .shadowMapHeight is now .shadow.mapSize.height."),this.shadow.mapSize.height=t}}}),Object.defineProperties(Ze.prototype,{length:{get:function(){return console.warn("THREE.BufferAttribute: .length has been deprecated. Use .count instead."),this.array.length}},dynamic:{get:function(){return console.warn("THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead."),this.usage===nt},set:function(){console.warn("THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead."),this.setUsage(nt)}}}),Ze.prototype.setDynamic=function(t){return console.warn("THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead."),this.setUsage(!0===t?nt:et),this},Ze.prototype.copyIndicesArray=function(){console.error("THREE.BufferAttribute: .copyIndicesArray() has been removed.")},Ze.prototype.setArray=function(){console.error("THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers")},vn.prototype.addIndex=function(t){console.warn("THREE.BufferGeometry: .addIndex() has been renamed to .setIndex()."),this.setIndex(t)},vn.prototype.addAttribute=function(t,e){return console.warn("THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute()."),e&&e.isBufferAttribute||e&&e.isInterleavedBufferAttribute?"index"===t?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),this.setIndex(e),this):this.setAttribute(t,e):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),this.setAttribute(t,new Ze(arguments[1],arguments[2])))},vn.prototype.addDrawCall=function(t,e,n){void 0!==n&&console.warn("THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset."),console.warn("THREE.BufferGeometry: .addDrawCall() is now .addGroup()."),this.addGroup(t,e)},vn.prototype.clearDrawCalls=function(){console.warn("THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups()."),this.clearGroups()},vn.prototype.computeOffsets=function(){console.warn("THREE.BufferGeometry: .computeOffsets() has been removed.")},vn.prototype.removeAttribute=function(t){return console.warn("THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute()."),this.deleteAttribute(t)},vn.prototype.applyMatrix=function(t){return console.warn("THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4()."),this.applyMatrix4(t)},Object.defineProperties(vn.prototype,{drawcalls:{get:function(){return console.error("THREE.BufferGeometry: .drawcalls has been renamed to .groups."),this.groups}},offsets:{get:function(){return console.warn("THREE.BufferGeometry: .offsets has been renamed to .groups."),this.groups}}}),Object.defineProperties(Jl.prototype,{maxInstancedCount:{get:function(){return console.warn("THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount."),this.instanceCount},set:function(t){console.warn("THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount."),this.instanceCount=t}}}),Object.defineProperties(Wc.prototype,{linePrecision:{get:function(){return console.warn("THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead."),this.params.Line.threshold},set:function(t){console.warn("THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead."),this.params.Line.threshold=t}}}),Object.defineProperties(gs.prototype,{dynamic:{get:function(){return console.warn("THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead."),this.usage===nt},set:function(t){console.warn("THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead."),this.setUsage(t)}}}),gs.prototype.setDynamic=function(t){return console.warn("THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead."),this.setUsage(!0===t?nt:et),this},gs.prototype.setArray=function(){console.error("THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers")},so.prototype.getArrays=function(){console.error("THREE.ExtrudeGeometry: .getArrays() has been removed.")},so.prototype.addShapeList=function(){console.error("THREE.ExtrudeGeometry: .addShapeList() has been removed.")},so.prototype.addShape=function(){console.error("THREE.ExtrudeGeometry: .addShape() has been removed.")},ms.prototype.dispose=function(){console.error("THREE.Scene: .dispose() has been removed.")},Gc.prototype.onUpdate=function(){return console.warn("THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead."),this},Object.defineProperties(Fe.prototype,{wrapAround:{get:function(){console.warn("THREE.Material: .wrapAround has been removed.")},set:function(){console.warn("THREE.Material: .wrapAround has been removed.")}},overdraw:{get:function(){console.warn("THREE.Material: .overdraw has been removed.")},set:function(){console.warn("THREE.Material: .overdraw has been removed.")}},wrapRGB:{get:function(){return console.warn("THREE.Material: .wrapRGB has been removed."),new je}},shading:{get:function(){console.error("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead.")},set:function(t){console.warn("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead."),this.flatShading=1===t}},stencilMask:{get:function(){return console.warn("THREE."+this.type+": .stencilMask has been removed. Use .stencilFuncMask instead."),this.stencilFuncMask},set:function(t){console.warn("THREE."+this.type+": .stencilMask has been removed. Use .stencilFuncMask instead."),this.stencilFuncMask=t}}}),Object.defineProperties(To.prototype,{transparency:{get:function(){return console.warn("THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission."),this.transmission},set:function(t){console.warn("THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission."),this.transmission=t}}}),Object.defineProperties(Gn.prototype,{derivatives:{get:function(){return console.warn("THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives."),this.extensions.derivatives},set:function(t){console.warn("THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives."),this.extensions.derivatives=t}}}),us.prototype.clearTarget=function(t,e,n,i){console.warn("THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead."),this.setRenderTarget(t),this.clear(e,n,i)},us.prototype.animate=function(t){console.warn("THREE.WebGLRenderer: .animate() is now .setAnimationLoop()."),this.setAnimationLoop(t)},us.prototype.getCurrentRenderTarget=function(){return console.warn("THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget()."),this.getRenderTarget()},us.prototype.getMaxAnisotropy=function(){return console.warn("THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy()."),this.capabilities.getMaxAnisotropy()},us.prototype.getPrecision=function(){return console.warn("THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision."),this.capabilities.precision},us.prototype.resetGLState=function(){return console.warn("THREE.WebGLRenderer: .resetGLState() is now .state.reset()."),this.state.reset()},us.prototype.supportsFloatTextures=function(){return console.warn("THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( 'OES_texture_float' )."),this.extensions.get("OES_texture_float")},us.prototype.supportsHalfFloatTextures=function(){return console.warn("THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( 'OES_texture_half_float' )."),this.extensions.get("OES_texture_half_float")},us.prototype.supportsStandardDerivatives=function(){return console.warn("THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( 'OES_standard_derivatives' )."),this.extensions.get("OES_standard_derivatives")},us.prototype.supportsCompressedTextureS3TC=function(){return console.warn("THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( 'WEBGL_compressed_texture_s3tc' )."),this.extensions.get("WEBGL_compressed_texture_s3tc")},us.prototype.supportsCompressedTexturePVRTC=function(){return console.warn("THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( 'WEBGL_compressed_texture_pvrtc' )."),this.extensions.get("WEBGL_compressed_texture_pvrtc")},us.prototype.supportsBlendMinMax=function(){return console.warn("THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( 'EXT_blend_minmax' )."),this.extensions.get("EXT_blend_minmax")},us.prototype.supportsVertexTextures=function(){return console.warn("THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures."),this.capabilities.vertexTextures},us.prototype.supportsInstancedArrays=function(){return console.warn("THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( 'ANGLE_instanced_arrays' )."),this.extensions.get("ANGLE_instanced_arrays")},us.prototype.enableScissorTest=function(t){console.warn("THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest()."),this.setScissorTest(t)},us.prototype.initMaterial=function(){console.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")},us.prototype.addPrePlugin=function(){console.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")},us.prototype.addPostPlugin=function(){console.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")},us.prototype.updateShadowMap=function(){console.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")},us.prototype.setFaceCulling=function(){console.warn("THREE.WebGLRenderer: .setFaceCulling() has been removed.")},us.prototype.allocTextureUnit=function(){console.warn("THREE.WebGLRenderer: .allocTextureUnit() has been removed.")},us.prototype.setTexture=function(){console.warn("THREE.WebGLRenderer: .setTexture() has been removed.")},us.prototype.setTexture2D=function(){console.warn("THREE.WebGLRenderer: .setTexture2D() has been removed.")},us.prototype.setTextureCube=function(){console.warn("THREE.WebGLRenderer: .setTextureCube() has been removed.")},us.prototype.getActiveMipMapLevel=function(){return console.warn("THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel()."),this.getActiveMipmapLevel()},Object.defineProperties(us.prototype,{shadowMapEnabled:{get:function(){return this.shadowMap.enabled},set:function(t){console.warn("THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled."),this.shadowMap.enabled=t}},shadowMapType:{get:function(){return this.shadowMap.type},set:function(t){console.warn("THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type."),this.shadowMap.type=t}},shadowMapCullFace:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.")}},context:{get:function(){return console.warn("THREE.WebGLRenderer: .context has been removed. Use .getContext() instead."),this.getContext()}},vr:{get:function(){return console.warn("THREE.WebGLRenderer: .vr has been renamed to .xr"),this.xr}},gammaInput:{get:function(){return console.warn("THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead."),!1},set:function(){console.warn("THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.")}},gammaOutput:{get:function(){return console.warn("THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead."),!1},set:function(t){console.warn("THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead."),this.outputEncoding=!0===t?Y:X}},toneMappingWhitePoint:{get:function(){return console.warn("THREE.WebGLRenderer: .toneMappingWhitePoint has been removed."),1},set:function(){console.warn("THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.")}}}),Object.defineProperties(ns.prototype,{cullFace:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.")}},renderReverseSided:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.")}},renderSingleSided:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.")}}}),Object.defineProperties(gt.prototype,{wrapS:{get:function(){return console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS."),this.texture.wrapS},set:function(t){console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS."),this.texture.wrapS=t}},wrapT:{get:function(){return console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT."),this.texture.wrapT},set:function(t){console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT."),this.texture.wrapT=t}},magFilter:{get:function(){return console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter."),this.texture.magFilter},set:function(t){console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter."),this.texture.magFilter=t}},minFilter:{get:function(){return console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter."),this.texture.minFilter},set:function(t){console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter."),this.texture.minFilter=t}},anisotropy:{get:function(){return console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy."),this.texture.anisotropy},set:function(t){console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy."),this.texture.anisotropy=t}},offset:{get:function(){return console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset."),this.texture.offset},set:function(t){console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset."),this.texture.offset=t}},repeat:{get:function(){return console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat."),this.texture.repeat},set:function(t){console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat."),this.texture.repeat=t}},format:{get:function(){return console.warn("THREE.WebGLRenderTarget: .format is now .texture.format."),this.texture.format},set:function(t){console.warn("THREE.WebGLRenderTarget: .format is now .texture.format."),this.texture.format=t}},type:{get:function(){return console.warn("THREE.WebGLRenderTarget: .type is now .texture.type."),this.texture.type},set:function(t){console.warn("THREE.WebGLRenderTarget: .type is now .texture.type."),this.texture.type=t}},generateMipmaps:{get:function(){return console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps."),this.texture.generateMipmaps},set:function(t){console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps."),this.texture.generateMipmaps=t}}}),xc.prototype.load=function(t){console.warn("THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.");const e=this;return(new lc).load(t,(function(t){e.setBuffer(t)})),this},Sc.prototype.getData=function(){return console.warn("THREE.AudioAnalyser: .getData() is now .getFrequencyData()."),this.getFrequencyData()},jn.prototype.updateCubeMap=function(t,e){return console.warn("THREE.CubeCamera: .updateCubeMap() is now .update()."),this.update(t,e)},jn.prototype.clear=function(t,e,n,i){return console.warn("THREE.CubeCamera: .clear() is now .renderTarget.clear()."),this.renderTarget.clear(t,e,n,i)},ut.crossOrigin=void 0,ut.loadTexture=function(t,e,n,i){console.warn("THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.");const r=new rl;r.setCrossOrigin(this.crossOrigin);const s=r.load(t,n,void 0,i);return e&&(s.mapping=e),s},ut.loadTextureCube=function(t,e,n,i){console.warn("THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.");const r=new nl;r.setCrossOrigin(this.crossOrigin);const s=r.load(t,n,void 0,i);return e&&(s.mapping=e),s},ut.loadCompressedTexture=function(){console.error("THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.")},ut.loadCompressedTextureCube=function(){console.error("THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.")};const Zh={createMultiMaterialObject:function(){console.error("THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js")},detach:function(){console.error("THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js")},attach:function(){console.error("THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js")}};"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:e}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=e),t.ACESFilmicToneMapping=4,t.AddEquation=n,t.AddOperation=2,t.AdditiveAnimationBlendMode=q,t.AdditiveBlending=2,t.AlphaFormat=1021,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=Wl,t.AmbientLightProbe=hc,t.AnimationClip=qo,t.AnimationLoader=class extends Qo{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new $o(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=[];for(let n=0;n.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{vh.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(vh,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=xc,t.AudioAnalyser=Sc,t.AudioContext=oc,t.AudioListener=class extends be{constructor(){super(),this.type="AudioListener",this.context=oc.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new pc}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(mc,gc,vc),yc.set(0,0,-1).applyQuaternion(gc),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(mc.x,t),e.positionY.linearRampToValueAtTime(mc.y,t),e.positionZ.linearRampToValueAtTime(mc.z,t),e.forwardX.linearRampToValueAtTime(yc.x,t),e.forwardY.linearRampToValueAtTime(yc.y,t),e.forwardZ.linearRampToValueAtTime(yc.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(mc.x,mc.y,mc.z),e.setOrientation(yc.x,yc.y,yc.z,n.x,n.y,n.z)}},t.AudioLoader=lc,t.AxesHelper=_h,t.AxisHelper=function(t){return console.warn("THREE.AxisHelper has been renamed to THREE.AxesHelper."),new _h(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 il(t)},t.Bone=Ws,t.BooleanKeyframeTrack=Ho,t.BoundingBoxHelper=function(t,e){return console.warn("THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead."),new gh(t,e)},t.Box2=Yc,t.Box3=wt,t.Box3Helper=class extends la{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 vn;i.setIndex(new Ze(n,1)),i.setAttribute("position",new sn([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 $s({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=zn,t.BoxGeometry=zn,t.BoxHelper=gh,t.BufferAttribute=Ze,t.BufferGeometry=vn,t.BufferGeometryLoader=Kl,t.ByteType=1010,t.Cache=Yo,t.Camera=kn,t.CameraHelper=class extends la{constructor(t){const e=new vn,n=new $s({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={},a=new je(16755200),o=new je(16711680),l=new je(43775),c=new je(16777215),h=new je(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 sn(i,3)),e.setAttribute("color",new sn(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;ph.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),fh("c",e,t,ph,0,0,-1),fh("t",e,t,ph,0,0,1),fh("n1",e,t,ph,-1,-1,-1),fh("n2",e,t,ph,1,-1,-1),fh("n3",e,t,ph,-1,1,-1),fh("n4",e,t,ph,1,1,-1),fh("f1",e,t,ph,-1,-1,1),fh("f2",e,t,ph,1,-1,1),fh("f3",e,t,ph,-1,1,1),fh("f4",e,t,ph,1,1,1),fh("u1",e,t,ph,.7,1.1,-1),fh("u2",e,t,ph,-.7,1.1,-1),fh("u3",e,t,ph,0,2,-1),fh("cf1",e,t,ph,-1,0,1),fh("cf2",e,t,ph,1,0,1),fh("cf3",e,t,ph,0,-1,1),fh("cf4",e,t,ph,0,1,1),fh("cn1",e,t,ph,-1,0,-1),fh("cn2",e,t,ph,1,0,-1),fh("cn3",e,t,ph,0,-1,-1),fh("cn4",e,t,ph,0,1,-1),t.getAttribute("position").needsUpdate=!0}},t.CanvasRenderer=function(){console.error("THREE.CanvasRenderer has been removed")},t.CanvasTexture=xa,t.CatmullRomCurve3=pl,t.CineonToneMapping=3,t.CircleBufferGeometry=ba,t.CircleGeometry=ba,t.ClampToEdgeWrapping=u,t.Clock=pc,t.Color=je,t.ColorKeyframeTrack=Uo,t.CompressedTexture=ya,t.CompressedTextureLoader=tl,t.ConeBufferGeometry=Ma,t.ConeGeometry=Ma,t.CubeCamera=jn,t.CubeReflectionMapping=r,t.CubeRefractionMapping=s,t.CubeTexture=qn,t.CubeTextureLoader=nl,t.CubeUVReflectionMapping=l,t.CubeUVRefractionMapping=c,t.CubicBezierCurve=vl,t.CubicBezierCurve3=yl,t.CubicInterpolant=Bo,t.CullFaceBack=1,t.CullFaceFront=2,t.CullFaceFrontBack=3,t.CullFaceNone=0,t.Curve=sl,t.CurvePath=Tl,t.CustomBlending=5,t.CustomToneMapping=5,t.CylinderBufferGeometry=wa,t.CylinderGeometry=wa,t.Cylindrical=class{constructor(t=1,e=0,n=0){return this.radius=t,this.theta=e,this.y=n,this}set(t,e,n){return this.radius=t,this.theta=e,this.y=n,this}copy(t){return this.radius=t.radius,this.theta=t.theta,this.y=t.y,this}setFromVector3(t){return this.setFromCartesianCoords(t.x,t.y,t.z)}setFromCartesianCoords(t,e,n){return this.radius=Math.sqrt(t*t+n*n),this.theta=Math.atan2(t,n),this.y=e,this}clone(){return(new this.constructor).copy(this)}},t.DataTexture=Yn,t.DataTexture2DArray=yi,t.DataTexture3D=xi,t.DataTextureLoader=il,t.DataUtils=Mh,t.DecrementStencilOp=7683,t.DecrementWrapStencilOp=34056,t.DefaultLoadingManager=Jo,t.DepthFormat=A,t.DepthStencilFormat=L,t.DepthTexture=_a,t.DirectionalLight=Vl,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 vn;i.setAttribute("position",new sn([-e,e,0,e,e,0,e,-e,0,-e,-e,0,-e,e,0],3));const r=new $s({fog:!1,toneMapped:!1});this.lightPlane=new sa(i,r),this.add(this.lightPlane),i=new vn,i.setAttribute("position",new sn([0,0,0,0,0,1],3)),this.targetLine=new sa(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(){ch.setFromMatrixPosition(this.light.matrixWorld),hh.setFromMatrixPosition(this.light.target.matrixWorld),uh.subVectors(hh,ch),this.lightPlane.lookAt(hh),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(hh),this.targetLine.scale.z=uh.length()}},t.DiscreteInterpolant=zo,t.DodecahedronBufferGeometry=Ta,t.DodecahedronGeometry=Ta,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 Ze(t,e).setUsage(nt)},t.DynamicCopyUsage=35050,t.DynamicDrawUsage=nt,t.DynamicReadUsage=35049,t.EdgesGeometry=Ca,t.EdgesHelper=function(t,e){return console.warn("THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead."),new la(new Ca(t.geometry),new $s({color:void 0!==e?e:16777215}))},t.EllipseCurve=al,t.EqualDepth=4,t.EqualStencilFunc=514,t.EquirectangularReflectionMapping=a,t.EquirectangularRefractionMapping=o,t.Euler=ae,t.EventDispatcher=rt,t.ExtrudeBufferGeometry=so,t.ExtrudeGeometry=so,t.FaceColors=1,t.FileLoader=$o,t.FlatShading=1,t.Float16BufferAttribute=rn,t.Float32Attribute=function(t,e){return console.warn("THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead."),new sn(t,e)},t.Float32BufferAttribute=sn,t.Float64Attribute=function(t,e){return console.warn("THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead."),new an(t,e)},t.Float64BufferAttribute=an,t.FloatType=w,t.Fog=fs,t.FogExp2=ps,t.Font=rc,t.FontLoader=class extends Qo{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new $o(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(t){let n;try{n=JSON.parse(t)}catch(e){console.warn("THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead."),n=JSON.parse(t.substring(65,t.length-2))}const i=r.parse(n);e&&e(i)}),n,i)}parse(t){return new rc(t)}},t.FrontSide=0,t.Frustum=Qn,t.GLBufferAttribute=Vc,t.GLSL1="100",t.GLSL3=it,t.GammaEncoding=Z,t.GreaterDepth=6,t.GreaterEqualDepth=5,t.GreaterEqualStencilFunc=518,t.GreaterStencilFunc=516,t.GridHelper=lh,t.Group=os,t.HalfFloatType=M,t.HemisphereLight=Rl,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 co(e);i.rotateY(.5*Math.PI),this.material=new qe({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 Ze(s,3)),this.add(new Bn(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");ah.copy(this.light.color),oh.copy(this.light.groundColor);for(let t=0,n=e.count;t0){const n=new Zo(e);r=new el(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e\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})}(Ah),this._equirectShader=null,this._cubemapShader=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){Oh=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=qh(),this._compileMaterial(this._cubemapShader))}compileEquirectangularShader(){null===this._equirectShader&&(this._equirectShader=jh(),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?Sh:0,Sh,Sh),o.setRenderTarget(i),u&&o.render(Ch,r),o.render(t,r)}o.toneMapping=h,o.outputEncoding=c,o.autoClear=l}_textureToCubeUV(t,e){const n=this._renderer;t.isCubeTexture?null==this._cubemapShader&&(this._cubemapShader=qh()):null==this._equirectShader&&(this._equirectShader=jh());const i=t.isCubeTexture?this._cubemapShader:this._equirectShader,r=new Bn(Dh[0],i),s=i.uniforms;s.envMap.value=t,t.isCubeTexture||s.texelSize.value.set(1/t.image.width,1/t.image.height),s.inputEncoding.value=Lh[t.encoding],s.outputEncoding.value=Lh[e.texture.encoding],Wh(e,0,0,3*Sh,2*Sh),n.setRenderTarget(e),n.render(r,Ph)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;eAh&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${f} samples when the maximum is set to 20`);const m=[];let g=0;for(let t=0;t4?i-8+4:0),3*v,2*v),o.setRenderTarget(e),o.render(c,Ph)}},t.ParametricBufferGeometry=ho,t.ParametricGeometry=ho,t.Particle=function(t){return console.warn("THREE.Particle has been renamed to THREE.Sprite."),new Is(t)},t.ParticleBasicMaterial=function(t){return console.warn("THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial."),new ha(t)},t.ParticleSystem=function(t,e){return console.warn("THREE.ParticleSystem has been renamed to THREE.Points."),new ma(t,e)},t.ParticleSystemMaterial=function(t){return console.warn("THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial."),new ha(t)},t.Path=El,t.PerspectiveCamera=Vn,t.Plane=Te,t.PlaneBufferGeometry=ti,t.PlaneGeometry=ti,t.PlaneHelper=class extends sa{constructor(t,e=1,n=16776960){const i=n,r=new vn;r.setAttribute("position",new sn([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,0,1,0,0,0],3)),r.computeBoundingSphere(),super(r,new $s({color:i,toneMapped:!1})),this.type="PlaneHelper",this.plane=t,this.size=e;const s=new vn;s.setAttribute("position",new sn([1,1,1,-1,1,1,-1,-1,1,1,1,1,-1,-1,1,1,-1,1],3)),s.computeBoundingSphere(),this.add(new Bn(s,new qe({color:i,opacity:.2,transparent:!0,depthWrite:!1,toneMapped:!1})))}updateMatrixWorld(t){let e=-this.plane.constant;Math.abs(e)<1e-8&&(e=1e-8),this.scale.set(.5*this.size,.5*this.size,e),this.children[0].material.side=e<0?1:0,this.lookAt(this.plane.normal),super.updateMatrixWorld(t)}},t.PointCloud=function(t,e){return console.warn("THREE.PointCloud has been renamed to THREE.Points."),new ma(t,e)},t.PointCloudMaterial=function(t){return console.warn("THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial."),new ha(t)},t.PointLight=Ul,t.PointLightHelper=class extends Bn{constructor(t,e,n){super(new fo(e,4,2),new qe({wireframe:!0,fog:!1,toneMapped:!1})),this.light=t,this.light.updateMatrixWorld(),this.color=n,this.type="PointLightHelper",this.matrix=this.light.matrixWorld,this.matrixAutoUpdate=!1,this.update()}dispose(){this.geometry.dispose(),this.material.dispose()}update(){void 0!==this.color?this.material.color.set(this.color):this.material.color.copy(this.light.color)}},t.Points=ma,t.PointsMaterial=ha,t.PolarGridHelper=class extends la{constructor(t=10,e=16,n=8,i=64,r=4473924,s=8947848){r=new je(r),s=new je(s);const a=[],o=[];for(let n=0;n<=e;n++){const i=n/e*(2*Math.PI),l=Math.sin(i)*t,c=Math.cos(i)*t;a.push(0,0,0),a.push(l,0,c);const h=1&n?r:s;o.push(h.r,h.g,h.b),o.push(h.r,h.g,h.b)}for(let e=0;e<=n;e++){const l=1&e?r:s,c=t-t/n*e;for(let t=0;t>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}}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],w=i[5],b=i[8];return r[0]=s*m+a*v+o*_,r[3]=s*f+a*y+o*w,r[6]=s*g+a*x+o*b,r[1]=l*m+c*v+h*_,r[4]=l*f+c*y+h*w,r[7]=l*g+c*x+h*b,r[2]=u*m+d*v+p*_,r[5]=u*f+d*y+p*w,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)}}let xt;yt.prototype.isMatrix3=!0;class _t{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===xt&&(xt=document.createElementNS("http://www.w3.org/1999/xhtml","canvas")),xt.width=t.width,xt.height=t.height;const n=xt.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=xt}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 wt=0;class bt extends rt{constructor(t=bt.DEFAULT_IMAGE,e=bt.DEFAULT_MAPPING,n=1001,i=1001,r=1006,s=1008,a=1023,o=1009,l=1,c=3e3){super(),Object.defineProperty(this,"id",{value:wt++}),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.version=0,this.onUpdate=null}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}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 Mt(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap?_t.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."),{})}bt.DEFAULT_IMAGE=void 0,bt.DEFAULT_MAPPING=i,bt.prototype.isTexture=!0;class St{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)}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(){}}At.prototype.isQuaternion=!0;class Lt{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(Ct.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(Ct.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 Rt.copy(this).projectOnVector(t),this.sub(Rt)}reflect(t){return this.sub(Rt.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}}Lt.prototype.isVector3=!0;const Rt=new Lt,Ct=new At;class Pt{constructor(t=new Lt(1/0,1/0,1/0),e=new Lt(-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 void 0===e&&(console.warn("THREE.Box3: .getParameter() target is now required"),e=new Lt),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,It),It.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(Ut),kt.subVectors(this.max,Ut),Bt.subVectors(t.a,Ut),zt.subVectors(t.b,Ut),Ft.subVectors(t.c,Ut),Ot.subVectors(zt,Bt),Ht.subVectors(Ft,zt),Gt.subVectors(Bt,Ft);let e=[0,-Ot.z,Ot.y,0,-Ht.z,Ht.y,0,-Gt.z,Gt.y,Ot.z,0,-Ot.x,Ht.z,0,-Ht.x,Gt.z,0,-Gt.x,-Ot.y,Ot.x,0,-Ht.y,Ht.x,0,-Gt.y,Gt.x,0];return!!jt(e,Bt,zt,Ft,kt)&&(e=[1,0,0,0,1,0,0,0,1],!!jt(e,Bt,zt,Ft,kt)&&(Vt.crossVectors(Ot,Ht),e=[Vt.x,Vt.y,Vt.z],jt(e,Bt,zt,Ft,kt)))}clampPoint(t,e){return void 0===e&&(console.warn("THREE.Box3: .clampPoint() target is now required"),e=new Lt),e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return It.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return void 0===t&&console.error("THREE.Box3: .getBoundingSphere() target is now required"),this.getCenter(t.center),t.radius=.5*this.getSize(It).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()||(Dt[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Dt[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Dt[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Dt[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Dt[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Dt[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Dt[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Dt[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Dt)),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)}}Pt.prototype.isBox3=!0;const Dt=[new Lt,new Lt,new Lt,new Lt,new Lt,new Lt,new Lt,new Lt],It=new Lt,Nt=new Pt,Bt=new Lt,zt=new Lt,Ft=new Lt,Ot=new Lt,Ht=new Lt,Gt=new Lt,Ut=new Lt,kt=new Lt,Vt=new Lt,Wt=new Lt;function jt(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Wt.fromArray(t,s);const a=r.x*Math.abs(Wt.x)+r.y*Math.abs(Wt.y)+r.z*Math.abs(Wt.z),o=e.dot(Wt),l=n.dot(Wt),c=i.dot(Wt);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const qt=new Pt,Xt=new Lt,Yt=new Lt,Zt=new Lt;class Jt{constructor(t=new Lt,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):qt.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 void 0===t&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),t=new Pt),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){Zt.subVectors(t,this.center);const e=Zt.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.add(Zt.multiplyScalar(n/t)),this.radius+=n}return this}union(t){return Yt.subVectors(t.center,this.center).normalize().multiplyScalar(t.radius),this.expandByPoint(Xt.copy(t.center).add(Yt)),this.expandByPoint(Xt.copy(t.center).sub(Yt)),this}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Qt=new Lt,Kt=new Lt,$t=new Lt,te=new Lt,ee=new Lt,ne=new Lt,ie=new Lt;class re{constructor(t=new Lt,e=new Lt(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 void 0===e&&(console.warn("THREE.Ray: .at() target is now required"),e=new Lt),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,Qt)),this}closestPointToPoint(t,e){void 0===e&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),e=new Lt),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=Qt.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Qt.copy(this.direction).multiplyScalar(e).add(this.origin),Qt.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){Kt.copy(t).add(e).multiplyScalar(.5),$t.copy(e).sub(t).normalize(),te.copy(this.origin).sub(Kt);const r=.5*t.distanceTo(e),s=-this.direction.dot($t),a=te.dot(this.direction),o=-te.dot($t),l=te.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($t).multiplyScalar(u).add(Kt),d}intersectSphere(t,e){Qt.subVectors(t.center,this.origin);const n=Qt.dot(this.direction),i=Qt.dot(Qt)-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,Qt)}intersectTriangle(t,e,n,i,r){ee.subVectors(e,t),ne.subVectors(n,t),ie.crossVectors(ee,ne);let s,a=this.direction.dot(ie);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}te.subVectors(this.origin,t);const o=s*this.direction.dot(ne.crossVectors(te,ne));if(o<0)return null;const l=s*this.direction.dot(ee.cross(te));if(l<0)return null;if(o+l>a)return null;const c=-s*te.dot(ie);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 se{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 se).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/ae.setFromMatrixColumn(t,0).length(),r=1/ae.setFromMatrixColumn(t,1).length(),s=1/ae.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(le,t,ce)}lookAt(t,e,n){const i=this.elements;return de.subVectors(t,e),0===de.lengthSq()&&(de.z=1),de.normalize(),he.crossVectors(n,de),0===he.lengthSq()&&(1===Math.abs(n.z)?de.x+=1e-4:de.z+=1e-4,de.normalize(),he.crossVectors(n,de)),he.normalize(),ue.crossVectors(de,he),i[0]=he.x,i[4]=ue.x,i[8]=de.x,i[1]=he.y,i[5]=ue.y,i[9]=de.y,i[2]=he.z,i[6]=ue.z,i[10]=de.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],w=i[0],b=i[4],M=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],B=i[11],z=i[15];return r[0]=s*w+a*T+o*R+l*I,r[4]=s*b+a*E+o*C+l*N,r[8]=s*M+a*A+o*P+l*B,r[12]=s*S+a*L+o*D+l*z,r[1]=c*w+h*T+u*R+d*I,r[5]=c*b+h*E+u*C+d*N,r[9]=c*M+h*A+u*P+d*B,r[13]=c*S+h*L+u*D+d*z,r[2]=p*w+m*T+f*R+g*I,r[6]=p*b+m*E+f*C+g*N,r[10]=p*M+m*A+f*P+g*B,r[14]=p*S+m*L+f*D+g*z,r[3]=v*w+y*T+x*R+_*I,r[7]=v*b+y*E+x*C+_*N,r[11]=v*M+y*A+x*P+_*B,r[15]=v*S+y*L+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,w=e*v+n*y+i*x+r*_;if(0===w)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const b=1/w;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){return this.set(1,e,n,0,t,1,n,0,t,e,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,w=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)*w,i[5]=(1-(u+g))*w,i[6]=(f+v)*w,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=ae.set(i[0],i[1],i[2]).length();const s=ae.set(i[4],i[5],i[6]).length(),a=ae.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],oe.copy(this);const o=1/r,l=1/s,c=1/a;return oe.elements[0]*=o,oe.elements[1]*=o,oe.elements[2]*=o,oe.elements[4]*=l,oe.elements[5]*=l,oe.elements[6]*=l,oe.elements[8]*=c,oe.elements[9]*=c,oe.elements[10]*=c,e.setFromRotationMatrix(oe),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}}se.prototype.isMatrix4=!0;const ae=new Lt,oe=new se,le=new Lt(0,0,0),ce=new Lt(1,1,1),he=new Lt,ue=new Lt,de=new Lt,pe=new se,me=new At;class fe{constructor(t=0,e=0,n=0,i=fe.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){return this._x=t,this._y=e,this._z=n,this._order=i||this._order,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,n){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=e||this._order){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,!1!==n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return pe.makeRotationFromQuaternion(t),this.setFromRotationMatrix(pe,e,n)}setFromVector3(t,e){return this.set(t.x,t.y,t.z,e||this._order)}reorder(t){return me.setFromEuler(this),this.setFromQuaternion(me,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 Lt(this._x,this._y,this._z)}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}}fe.prototype.isEuler=!0,fe.DefaultOrder="XYZ",fe.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class ge{constructor(){this.mask=1}set(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;e1?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 void 0===t&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),t=new Lt),t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||Ie.getNormalMatrix(t),i=this.coplanarPoint(Pe).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)}}Ne.prototype.isPlane=!0;const Be=new Lt,ze=new Lt,Fe=new Lt,Oe=new Lt,He=new Lt,Ge=new Lt,Ue=new Lt,ke=new Lt,Ve=new Lt,We=new Lt;class je{constructor(t=new Lt,e=new Lt,n=new Lt){this.a=t,this.b=e,this.c=n}static getNormal(t,e,n,i){void 0===i&&(console.warn("THREE.Triangle: .getNormal() target is now required"),i=new Lt),i.subVectors(n,e),Be.subVectors(t,e),i.cross(Be);const r=i.lengthSq();return r>0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){Be.subVectors(i,e),ze.subVectors(n,e),Fe.subVectors(t,e);const s=Be.dot(Be),a=Be.dot(ze),o=Be.dot(Fe),l=ze.dot(ze),c=ze.dot(Fe),h=s*l-a*a;if(void 0===r&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),r=new Lt),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,Oe),Oe.x>=0&&Oe.y>=0&&Oe.x+Oe.y<=1}static getUV(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,Oe),o.set(0,0),o.addScaledVector(r,Oe.x),o.addScaledVector(s,Oe.y),o.addScaledVector(a,Oe.z),o}static isFrontFacing(t,e,n,i){return Be.subVectors(n,e),ze.subVectors(t,e),Be.cross(ze).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}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 Be.subVectors(this.c,this.b),ze.subVectors(this.a,this.b),.5*Be.cross(ze).length()}getMidpoint(t){return void 0===t&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),t=new Lt),t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return je.getNormal(this.a,this.b,this.c,t)}getPlane(t){return void 0===t&&(console.warn("THREE.Triangle: .getPlane() target is now required"),t=new Ne),t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return je.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return je.getUV(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return je.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return je.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){void 0===e&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),e=new Lt);const n=this.a,i=this.b,r=this.c;let s,a;He.subVectors(i,n),Ge.subVectors(r,n),ke.subVectors(t,n);const o=He.dot(ke),l=Ge.dot(ke);if(o<=0&&l<=0)return e.copy(n);Ve.subVectors(t,i);const c=He.dot(Ve),h=Ge.dot(Ve);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(He,s);We.subVectors(t,r);const d=He.dot(We),p=Ge.dot(We);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(Ge,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return Ue.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Ue,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(He,s).addScaledVector(Ge,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let qe=0;function Xe(){Object.defineProperty(this,"id",{value:qe++}),this.uuid=ct(),this.name="",this.type="Material",this.fog=!0,this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,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.alphaTest=0,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0}Xe.prototype=Object.assign(Object.create(rt.prototype),{constructor:Xe,isMaterial:!0,onBuild:function(){},onBeforeCompile:function(){},customProgramCacheKey:function(){return this.onBeforeCompile.toString()},setValues:function(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:function(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),this.sheen&&this.sheen.isColor&&(n.sheen=this.sheen.getHex()),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.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.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.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),!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.morphTargets&&(n.morphTargets=!0),!0===this.morphNormals&&(n.morphNormals=!0),!0===this.skinning&&(n.skinning=!0),!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:function(){return(new this.constructor).copy(this)},copy:function(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.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:function(){this.dispatchEvent({type:"dispose"})}}),Object.defineProperty(Xe.prototype,"needsUpdate",{set:function(t){!0===t&&this.version++}});const Ye={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},Ze={h:0,s:0,l:0},Je={h:0,s:0,l:0};function Qe(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 Ke(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function $e(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}class tn{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=Qe(r,i,t+1/3),this.g=Qe(r,i,t),this.b=Qe(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=Ye[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=Ke(t.r),this.g=Ke(t.g),this.b=Ke(t.b),this}copyLinearToSRGB(t){return this.r=$e(t.r),this.g=$e(t.g),this.b=$e(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){void 0===t&&(console.warn("THREE.Color: .getHSL() target is now required"),t={h:0,s:0,l:0});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+(ne&&(e=t[n]);return e}const vn={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function yn(t,e){return new vn[t](e)}let xn=0;const _n=new se,wn=new Ce,bn=new Lt,Mn=new Pt,Sn=new Pt,Tn=new Lt;class En extends rt{constructor(){super(),Object.defineProperty(this,"id",{value:xn++}),this.uuid=ct(),this.name="",this.type="BufferGeometry",this.index=null,this.attributes={},this.morphAttributes={},this.morphTargetsRelative=!1,this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.drawRange={start:0,count:1/0},this.userData={}}getIndex(){return this.index}setIndex(t){return Array.isArray(t)?this.index=new(gn(t)>65535?dn:hn)(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}rotateX(t){return _n.makeRotationX(t),this.applyMatrix4(_n),this}rotateY(t){return _n.makeRotationY(t),this.applyMatrix4(_n),this}rotateZ(t){return _n.makeRotationZ(t),this.applyMatrix4(_n),this}translate(t,e,n){return _n.makeTranslation(t,e,n),this.applyMatrix4(_n),this}scale(t,e,n){return _n.makeScale(t,e,n),this.applyMatrix4(_n),this}lookAt(t){return wn.lookAt(t),wn.updateMatrix(),this.applyMatrix4(wn.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(bn).negate(),this.translate(bn.x,bn.y,bn.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 En).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(),Rn.copy(n.boundingSphere),Rn.applyMatrix4(r),!1===t.ray.intersectsSphere(Rn))return;if(An.copy(r).invert(),Ln.copy(t.ray).applyMatrix4(An),null!==n.boundingBox&&!1===Ln.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:Vn.clone(),object:t}}(t,e,n,i,Cn,Pn,Dn,kn);if(p){o&&(Hn.fromBufferAttribute(o,c),Gn.fromBufferAttribute(o,h),Un.fromBufferAttribute(o,u),p.uv=je.getUV(kn,Cn,Pn,Dn,Hn,Gn,Un,new vt)),l&&(Hn.fromBufferAttribute(l,c),Gn.fromBufferAttribute(l,h),Un.fromBufferAttribute(l,u),p.uv2=je.getUV(kn,Cn,Pn,Dn,Hn,Gn,Un,new vt));const t={a:c,b:h,c:u,normal:new Lt,materialIndex:0};je.getNormal(Cn,Pn,Dn,t.normal),p.face=t}return p}Wn.prototype.isMesh=!0;class qn extends En{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,w=p/2,b=m/2,M=f+1,S=g+1;let T=0,E=0;const A=new Lt;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}}Jn.prototype.isShaderMaterial=!0;class Qn extends Ce{constructor(){super(),this.type="Camera",this.matrixWorldInverse=new se,this.projectionMatrix=new se,this.projectionMatrixInverse=new se}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){void 0===t&&(console.warn("THREE.Camera: .getWorldDirection() target is now required"),t=new Lt),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)}}Qn.prototype.isCamera=!0;class Kn extends Qn{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}}Kn.prototype.isPerspectiveCamera=!0;const $n=90;class ti extends Ce{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 Kn($n,1,t,e);i.layers=this.layers,i.up.set(0,-1,0),i.lookAt(new Lt(1,0,0)),this.add(i);const r=new Kn($n,1,t,e);r.layers=this.layers,r.up.set(0,-1,0),r.lookAt(new Lt(-1,0,0)),this.add(r);const s=new Kn($n,1,t,e);s.layers=this.layers,s.up.set(0,0,1),s.lookAt(new Lt(0,1,0)),this.add(s);const a=new Kn($n,1,t,e);a.layers=this.layers,a.up.set(0,0,-1),a.lookAt(new Lt(0,-1,0)),this.add(a);const o=new Kn($n,1,t,e);o.layers=this.layers,o.up.set(0,-1,0),o.lookAt(new Lt(0,0,1)),this.add(o);const l=new Kn($n,1,t,e);l.layers=this.layers,l.up.set(0,-1,0),l.lookAt(new Lt(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 ei extends bt{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=void 0!==o?o:T,l,c,h),this._needsFlipEnvMap=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}ei.prototype.isCubeTexture=!0;class ni extends Tt{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 ei(void 0,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),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 qn(5,5,5),r=new Jn({name:"CubemapFromEquirect",uniforms:Xn(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Wn(i,r),a=e.minFilter;e.minFilter===y&&(e.minFilter=g);return new ti(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)}}ni.prototype.isWebGLCubeRenderTarget=!0;class ii extends bt{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={data:t||null,width:e||1,height:n||1},this.magFilter=void 0!==l?l:p,this.minFilter=void 0!==c?c:p,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1,this.needsUpdate=!0}}ii.prototype.isDataTexture=!0;const ri=new Jt,si=new Lt;class ai{constructor(t=new Ne,e=new Ne,n=new Ne,i=new Ne,r=new Ne,s=new Ne){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(),ri.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(ri)}intersectsSprite(t){return ri.center.set(0,0,0),ri.radius=.7071067811865476,ri.applyMatrix4(t.matrixWorld),this.intersectsSphere(ri)}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,si.y=i.normal.y>0?t.max.y:t.min.y,si.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(si)<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 oi(){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 li(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 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 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}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.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}\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_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\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 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 max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\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 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}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\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}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\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#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\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\tuniform int maxMipLevel;\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 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\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\tfogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\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 fogDepth;\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 texture2D( gradientMap, coord ).rgb;\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\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\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 );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\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\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * 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 );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\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 GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\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 getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.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 getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.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 getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.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 GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_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_Diffuse_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;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, 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_Diffuse_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.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\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 = sheen;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat specularRoughness;\n\tvec3 specularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\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.specularRoughness;\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#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_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_Diffuse_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 CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * 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 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\tgetPointDirectLightIrradiance( 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\tgetSpotDirectLightIrradiance( 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\tgetDirectionalDirectLightIrradiance( 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 );\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 );\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 += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\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\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\t\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\t\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\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",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 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",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; }",transmissionmap_fragment:"#ifdef USE_TRANSMISSIONMAP\n\ttotalTransmission *= texture2D( transmissionMap, vUv ).r;\n#endif",transmissionmap_pars_fragment:"#ifdef USE_TRANSMISSIONMAP\n\tuniform sampler2D transmissionMap;\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 )\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_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}",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}",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}",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}",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 \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}",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}",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 \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}",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}",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}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \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}",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 \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\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\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}",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 \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_Diffuse_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_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\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 \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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\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\tvViewPosition = - mvPosition.xyz;\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 \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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}",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 \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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\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 \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#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\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}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSMISSION\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSMISSION\n\tuniform float transmission;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#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\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#ifdef TRANSMISSION\n\t\tfloat totalTransmission = transmission;\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\t#include \n\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#ifdef TRANSMISSION\n\t\tdiffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#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\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#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\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}",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#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\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}",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#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\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#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\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}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}",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}",shadow_vert:"#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}",sprite_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\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\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}"},ui={common:{diffuse:{value:new tn(15658734)},opacity:{value:1},map:{value:null},uvTransform:{value:new yt},uv2Transform:{value:new yt},alphaMap:{value:null}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},refractionRatio:{value:.98},maxMipLevel:{value:0}},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 tn(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 tn(15658734)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},uvTransform:{value:new yt}},sprite:{diffuse:{value:new tn(15658734)},opacity:{value:1},center:{value:new vt(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},uvTransform:{value:new yt}}},di={basic:{uniforms:Yn([ui.common,ui.specularmap,ui.envmap,ui.aomap,ui.lightmap,ui.fog]),vertexShader:hi.meshbasic_vert,fragmentShader:hi.meshbasic_frag},lambert:{uniforms:Yn([ui.common,ui.specularmap,ui.envmap,ui.aomap,ui.lightmap,ui.emissivemap,ui.fog,ui.lights,{emissive:{value:new tn(0)}}]),vertexShader:hi.meshlambert_vert,fragmentShader:hi.meshlambert_frag},phong:{uniforms:Yn([ui.common,ui.specularmap,ui.envmap,ui.aomap,ui.lightmap,ui.emissivemap,ui.bumpmap,ui.normalmap,ui.displacementmap,ui.fog,ui.lights,{emissive:{value:new tn(0)},specular:{value:new tn(1118481)},shininess:{value:30}}]),vertexShader:hi.meshphong_vert,fragmentShader:hi.meshphong_frag},standard:{uniforms:Yn([ui.common,ui.envmap,ui.aomap,ui.lightmap,ui.emissivemap,ui.bumpmap,ui.normalmap,ui.displacementmap,ui.roughnessmap,ui.metalnessmap,ui.fog,ui.lights,{emissive:{value:new tn(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:hi.meshphysical_vert,fragmentShader:hi.meshphysical_frag},toon:{uniforms:Yn([ui.common,ui.aomap,ui.lightmap,ui.emissivemap,ui.bumpmap,ui.normalmap,ui.displacementmap,ui.gradientmap,ui.fog,ui.lights,{emissive:{value:new tn(0)}}]),vertexShader:hi.meshtoon_vert,fragmentShader:hi.meshtoon_frag},matcap:{uniforms:Yn([ui.common,ui.bumpmap,ui.normalmap,ui.displacementmap,ui.fog,{matcap:{value:null}}]),vertexShader:hi.meshmatcap_vert,fragmentShader:hi.meshmatcap_frag},points:{uniforms:Yn([ui.points,ui.fog]),vertexShader:hi.points_vert,fragmentShader:hi.points_frag},dashed:{uniforms:Yn([ui.common,ui.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:hi.linedashed_vert,fragmentShader:hi.linedashed_frag},depth:{uniforms:Yn([ui.common,ui.displacementmap]),vertexShader:hi.depth_vert,fragmentShader:hi.depth_frag},normal:{uniforms:Yn([ui.common,ui.bumpmap,ui.normalmap,ui.displacementmap,{opacity:{value:1}}]),vertexShader:hi.normal_vert,fragmentShader:hi.normal_frag},sprite:{uniforms:Yn([ui.sprite,ui.fog]),vertexShader:hi.sprite_vert,fragmentShader:hi.sprite_frag},background:{uniforms:{uvTransform:{value:new yt},t2D:{value:null}},vertexShader:hi.background_vert,fragmentShader:hi.background_frag},cube:{uniforms:Yn([ui.envmap,{opacity:{value:1}}]),vertexShader:hi.cube_vert,fragmentShader:hi.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:hi.equirect_vert,fragmentShader:hi.equirect_frag},distanceRGBA:{uniforms:Yn([ui.common,ui.displacementmap,{referencePosition:{value:new Lt},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:hi.distanceRGBA_vert,fragmentShader:hi.distanceRGBA_frag},shadow:{uniforms:Yn([ui.lights,ui.fog,{color:{value:new tn(0)},opacity:{value:1}}]),vertexShader:hi.shadow_vert,fragmentShader:hi.shadow_frag}};function pi(t,e,n,i,r){const s=new tn(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,m,f){let g=!0===r.isScene?r.background:null;g&&g.isTexture&&(g=e.get(g));const v=t.xr,y=v.getSession&&v.getSession();y&&"additive"===y.environmentBlendMode&&(g=null),null===g?p(s,c):g&&g.isColor&&(p(g,1),f=!0),(t.autoClear||f)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),g&&(g.isCubeTexture||g.mapping===l)?(void 0===o&&(o=new Wn(new qn(1,1,1),new Jn({name:"BackgroundCubeMaterial",uniforms:Xn(di.cube.uniforms),vertexShader:di.cube.vertexShader,fragmentShader:di.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=g,o.material.uniforms.flipEnvMap.value=g.isCubeTexture&&g._needsFlipEnvMap?-1:1,h===g&&u===g.version&&d===t.toneMapping||(o.material.needsUpdate=!0,h=g,u=g.version,d=t.toneMapping),n.unshift(o,o.geometry,o.material,0,0,null)):g&&g.isTexture&&(void 0===a&&(a=new Wn(new ci(2,2),new Jn({name:"BackgroundMaterial",uniforms:Xn(di.background.uniforms),vertexShader:di.background.vertexShader,fragmentShader:di.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=g,!0===g.matrixAutoUpdate&&g.updateMatrix(),a.material.uniforms.uvTransform.value.copy(g.matrix),h===g&&u===g.version&&d===t.toneMapping||(a.material.needsUpdate=!0,h=g,u=g.version,d=t.toneMapping),n.unshift(a,a.geometry,a.material,0,0,null))}}}function mi(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){const s=l[e];if(void 0!==s){const e=s.normalized,r=s.itemSize,a=n.get(s);if(void 0===a)continue;const l=a.buffer,c=a.type,h=a.bytesPerElement;if(s.isInterleavedBufferAttribute){const n=s.data,a=n.stride,u=s.offset;n&&n.isInstancedInterleavedBuffer?(f(i,n.meshPerAttribute),void 0===o._maxInstanceCount&&(o._maxInstanceCount=n.meshPerAttribute*n.count)):m(i),t.bindBuffer(34962,l),v(i,r,c,e,a*h,u*h)}else s.isInstancedBufferAttribute?(f(i,s.meshPerAttribute),void 0===o._maxInstanceCount&&(o._maxInstanceCount=s.meshPerAttribute*s.count)):m(i),t.bindBuffer(34962,l),v(i,r,c,e,0,0)}else if("instanceMatrix"===e){const e=n.get(r.instanceMatrix);if(void 0===e)continue;const s=e.buffer,a=e.type;f(i+0,1),f(i+1,1),f(i+2,1),f(i+3,1),t.bindBuffer(34962,s),t.vertexAttribPointer(i+0,4,a,!1,64,0),t.vertexAttribPointer(i+1,4,a,!1,64,16),t.vertexAttribPointer(i+2,4,a,!1,64,32),t.vertexAttribPointer(i+3,4,a,!1,64,48)}else if("instanceColor"===e){const e=n.get(r.instanceColor);if(void 0===e)continue;const s=e.buffer,a=e.type;f(i,1),t.bindBuffer(34962,s),t.vertexAttribPointer(i,3,a,!1,12,0)}else if(void 0!==h){const n=h[e];if(void 0!==n)switch(n.length){case 2:t.vertexAttrib2fv(i,n);break;case 3:t.vertexAttrib3fv(i,n);break;case 4:t.vertexAttrib4fv(i,n);break;default:t.vertexAttrib1fv(i,n)}}}}g()}(r,l,u,y),null!==x&&t.bindBuffer(34963,n.get(x).buffer))},reset:y,resetDefaultState:x,dispose:function(){y();for(const t in o){const e=o[t];for(const t in e){const n=e[t];for(const t in n)u(n[t].object),delete n[t];delete e[t]}delete o[t]}},releaseStatesOfGeometry:function(t){if(void 0===o[t.id])return;const e=o[t.id];for(const t in e){const n=e[t];for(const t in n)u(n[t].object),delete n[t];delete e[t]}delete o[t.id]},releaseStatesOfProgram:function(t){for(const e in o){const n=o[e];if(void 0===n[t.id])continue;const i=n[t.id];for(const t in i)u(i[t].object),delete i[t];delete n[t.id]}},initAttributes:p,enableAttribute:m,disableUnusedAttributes:g}}function fi(t,e,n,i){const r=i.isWebGL2;let s;this.setMode=function(t){s=t},this.render=function(e,i){t.drawArrays(s,e,i),n.update(i,s,1)},this.renderInstances=function(i,a,o){if(0===o)return;let l,c;if(r)l=t,c="drawArraysInstanced";else if(l=e.get("ANGLE_instanced_arrays"),c="drawArraysInstancedANGLE",null===l)return void console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");l[c](s,i,a,o),n.update(a,s,o)}}function gi(t,e,n){let i;function r(e){if("highp"===e){if(t.getShaderPrecisionFormat(35633,36338).precision>0&&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=!0===n.logarithmicDepthBuffer,c=t.getParameter(34930),h=t.getParameter(35660),u=t.getParameter(3379),d=t.getParameter(34076),p=t.getParameter(34921),m=t.getParameter(36347),f=t.getParameter(36348),g=t.getParameter(36349),v=h>0,y=s||e.has("OES_texture_float");return{isWebGL2:s,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:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:u,maxCubemapSize:d,maxAttributes:p,maxVertexUniforms:m,maxVaryings:f,maxFragmentUniforms:g,vertexTextures:v,floatFragmentTextures:y,floatVertexTextures:v&&y,maxSamples:s?t.getParameter(36183):0}}function vi(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new Ne,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 ni(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}}}function xi(t){const e={};function n(n){if(void 0!==e[n])return e[n];let i;switch(n){case"WEBGL_depth_texture":i=t.getExtension("WEBGL_depth_texture")||t.getExtension("MOZ_WEBGL_depth_texture")||t.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":i=t.getExtension("EXT_texture_filter_anisotropic")||t.getExtension("MOZ_EXT_texture_filter_anisotropic")||t.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":i=t.getExtension("WEBGL_compressed_texture_s3tc")||t.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||t.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":i=t.getExtension("WEBGL_compressed_texture_pvrtc")||t.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;default:i=t.getExtension(n)}return e[n]=i,i}return{has:function(t){return null!==n(t)},init:function(t){t.isWebGL2?n("EXT_color_buffer_float"):(n("WEBGL_depth_texture"),n("OES_texture_float"),n("OES_texture_half_float"),n("OES_texture_half_float_linear"),n("OES_standard_derivatives"),n("OES_element_index_uint"),n("OES_vertex_array_object"),n("ANGLE_instanced_arrays")),n("OES_texture_float_linear"),n("EXT_color_buffer_half_float")},get:function(t){const e=n(t);return null===e&&console.warn("THREE.WebGLRenderer: "+t+" extension not supported."),e}}}function _i(t,e,n,i){const r={},s=new WeakMap;function a(t){const o=t.target;null!==o.index&&e.remove(o.index);for(const t in o.attributes)e.remove(o.attributes[t]);o.removeEventListener("dispose",a),delete r[o.id];const l=s.get(o);l&&(e.remove(l),s.delete(o)),i.releaseStatesOfGeometry(o),!0===o.isInstancedBufferGeometry&&delete o._maxInstanceCount,n.memory.geometries--}function o(t){const n=[],i=t.index,r=t.attributes.position;let a=0;if(null!==i){const t=i.array;a=i.version;for(let e=0,i=t.length;e65535?dn:hn)(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;t0)return t;const r=e*n;let s=Ii[r];if(void 0===s&&(s=new Float32Array(r),Ii[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 Hi(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n/gm;function kr(t){return t.replace(Ur,Vr)}function Vr(t,e){const n=hi[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return kr(n)}const Wr=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,jr=/#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 qr(t){return t.replace(jr,Yr).replace(Wr,Xr)}function Xr(t,e,n,i){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),Yr(t,e,n,i)}function Yr(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.rendererExtensionShaderTextureLod?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Or).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 _,w,b=n.glslVersion?"#version "+n.glslVersion+"\n":"";n.isRawShaderMaterial?(_=[y].filter(Or).join("\n"),_.length>0&&(_+="\n"),w=[v,y].filter(Or).join("\n"),w.length>0&&(w+="\n")):(_=[Zr(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.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",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.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","#ifdef USE_MORPHTARGETS","\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(Or).join("\n"),w=[v,Zr(n),"#define SHADER_NAME "+n.shaderName,y,n.alphaTest?"#define ALPHATEST "+n.alphaTest+(n.alphaTest%1?"":".0"):"","#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.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.sheen?"#define USE_SHEEN":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",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?hi.tonemapping_pars_fragment:"",0!==n.toneMapping?Fr("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",hi.encodings_pars_fragment,n.map?Br("mapTexelToLinear",n.mapEncoding):"",n.matcap?Br("matcapTexelToLinear",n.matcapEncoding):"",n.envMap?Br("envMapTexelToLinear",n.envMapEncoding):"",n.emissiveMap?Br("emissiveMapTexelToLinear",n.emissiveMapEncoding):"",n.lightMap?Br("lightMapTexelToLinear",n.lightMapEncoding):"",zr("linearToOutputTexel",n.outputEncoding),n.depthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Or).join("\n")),h=kr(h),h=Hr(h,n),h=Gr(h,n),u=kr(u),u=Hr(u,n),u=Gr(u,n),h=qr(h),u=qr(u),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(b="#version 300 es\n",_=["#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+_,w=["#define varying in",n.glslVersion===it?"":"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"+w);const M=b+w+u,S=Pr(a,35633,b+_+h),T=Pr(a,35632,M);if(a.attachShader(x,S),a.attachShader(x,T),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(T).trim();let i=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){i=!1;const e=Nr(a,S,"vertex"),n=Nr(a,T,"fragment");console.error("THREE.WebGLProgram: shader error: ",a.getError(),"35715",a.getProgramParameter(x,35715),"gl.getProgramInfoLog",t,e,n)}else""!==t?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",t):""!==e&&""!==n||(r=!1);r&&(this.diagnostics={runnable:i,programLog:t,vertexShader:{log:e,prefix:_},fragmentShader:{log:n,prefix:w}})}let E,A;return a.deleteShader(S),a.deleteShader(T),this.getUniforms=function(){return void 0===E&&(E=new Cr(a,x)),E},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const n={},i=t.getProgramParameter(e,35721);for(let r=0;r0,maxBones:S,useVertexTexture:u,morphTargets:r.morphTargets,morphNormals:r.morphNormals,numDirLights:a.directional.length,numPointLights:a.point.length,numSpotLights:a.spot.length,numRectAreaLights:a.rectArea.length,numHemiLights:a.hemi.length,numDirLightShadows:a.directionalShadowMap.length,numPointLightShadows:a.pointShadowMap.length,numSpotLightShadows:a.spotShadowMap.length,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:r.dithering,shadowMapEnabled:t.shadowMap.enabled&&g.length>0,shadowMapType:t.shadowMap.type,toneMapping:r.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:r.premultipliedAlpha,alphaTest:r.alphaTest,doubleSided:2===r.side,flipSided:1===r.side,depthPacking:void 0!==r.depthPacking&&r.depthPacking,index0AttributeName:r.index0AttributeName,extensionDerivatives:r.extensions&&r.extensions.derivatives,extensionFragDepth:r.extensions&&r.extensions.fragDepth,extensionDrawBuffers:r.extensions&&r.extensions.drawBuffers,extensionShaderTextureLOD:r.extensions&&r.extensions.shaderTextureLOD,rendererExtensionFragDepth:o||n.has("EXT_frag_depth"),rendererExtensionDrawBuffers:o||n.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:o||n.has("EXT_shader_texture_lod"),customProgramCacheKey:r.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.fragmentShader),n.push(e.vertexShader)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);if(!1===e.isRawShaderMaterial){for(let t=0;t1&&i.sort(t||$r),r.length>1&&r.sort(e||ts)}}}function ns(t){let e=new WeakMap;return{get:function(n,i){let r;return!1===e.has(n)?(r=new es(t),e.set(n,[r])):i>=e.get(n).length?(r=new es(t),e.get(n).push(r)):r=e.get(n)[i],r},dispose:function(){e=new WeakMap}}}function is(){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 Lt,color:new tn};break;case"SpotLight":n={position:new Lt,direction:new Lt,color:new tn,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new Lt,color:new tn,distance:0,decay:0};break;case"HemisphereLight":n={direction:new Lt,skyColor:new tn,groundColor:new tn};break;case"RectAreaLight":n={color:new tn,position:new Lt,halfWidth:new Lt,halfHeight:new Lt}}return t[e.id]=n,n}}}let rs=0;function ss(t,e){return(e.castShadow?1:0)-(t.castShadow?1:0)}function as(t,e){const n=new is,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 Lt);const s=new Lt,a=new se,o=new se;return{setup:function(s){let a=0,o=0,l=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let c=0,h=0,u=0,d=0,p=0,m=0,f=0,g=0;s.sort(ss);for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=ui.LTC_FLOAT_1,r.rectAreaLTC2=ui.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=ui.LTC_HALF_1,r.rectAreaLTC2=ui.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=a,r.ambient[1]=o,r.ambient[2]=l;const v=r.hash;v.directionalLength===c&&v.pointLength===h&&v.spotLength===u&&v.rectAreaLength===d&&v.hemiLength===p&&v.numDirectionalShadows===m&&v.numPointShadows===f&&v.numSpotShadows===g||(r.directional.length=c,r.spot.length=u,r.rectArea.length=d,r.point.length=h,r.hemi.length=p,r.directionalShadow.length=m,r.directionalShadowMap.length=m,r.pointShadow.length=f,r.pointShadowMap.length=f,r.spotShadow.length=g,r.spotShadowMap.length=g,r.directionalShadowMatrix.length=m,r.pointShadowMatrix.length=f,r.spotShadowMatrix.length=g,v.directionalLength=c,v.pointLength=h,v.spotLength=u,v.rectAreaLength=d,v.hemiLength=p,v.numDirectionalShadows=m,v.numPointShadows=f,v.numSpotShadows=g,r.version=rs++)},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 cs extends Xe{constructor(t){super(),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,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.skinning=t.skinning,this.morphTargets=t.morphTargets,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}}cs.prototype.isMeshDepthMaterial=!0;class hs extends Xe{constructor(t){super(),this.type="MeshDistanceMaterial",this.referencePosition=new Lt,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,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.skinning=t.skinning,this.morphTargets=t.morphTargets,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}hs.prototype.isMeshDistanceMaterial=!0;function us(t,e,n){let i=new ai;const r=new vt,s=new vt,a=new St,o=[],l=[],c={},h=n.maxTextureSize,u={0:1,1:0,2:2},d=new Jn({defines:{SAMPLE_RATE:2/8,HALF_SAMPLE_RATE:1/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\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\tfor ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 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, i ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean * HALF_SAMPLE_RATE;\n\tsquared_mean = squared_mean * HALF_SAMPLE_RATE;\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 En;f.setAttribute("position",new sn(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const v=new Wn(f,d),y=this;function x(n,i){const r=e.update(v);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 _(t,e,n){const i=t<<0|e<<1|n<<2;let r=o[i];return void 0===r&&(r=new cs({depthPacking:3201,morphTargets:t,skinning:e}),o[i]=r),r}function w(t,e,n){const i=t<<0|e<<1|n<<2;let r=l[i];return void 0===r&&(r=new hs({morphTargets:t,skinning:e}),l[i]=r),r}function b(e,n,i,r,s,a,o){let l=null,h=_,d=e.customDepthMaterial;if(!0===r.isPointLight&&(h=w,d=e.customDistanceMaterial),void 0===d){let t=!1;!0===i.morphTargets&&(t=n.morphAttributes&&n.morphAttributes.position&&n.morphAttributes.position.length>0);let r=!1;!0===e.isSkinnedMesh&&(!0===i.skinning?r=!0:console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",e));l=h(t,r,!0===e.isInstancedMesh)}else l=d;if(t.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){const t=l.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=l.clone(),n[e]=r),l=r}return l.visible=i.visible,l.wireframe=i.wireframe,l.side=3===o?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],l.clipShadows=i.clipShadows,l.clippingPlanes=i.clippingPlanes,l.clipIntersection=i.clipIntersection,l.wireframeLinewidth=i.wireframeLinewidth,l.linewidth=i.linewidth,!0===r.isPointLight&&!0===l.isMeshDistanceMaterial&&(l.referencePosition.setFromMatrixPosition(r.matrixWorld),l.nearDistance=s,l.farDistance=a),l}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 Tt(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.mapPass=new Tt(r.x,r.y,t),u.camera.updateProjectionMatrix()}if(null===u.map){const t={minFilter:p,magFilter:p,format:E};u.map=new Tt(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")&&(L=parseFloat(/^OpenGL ES (\d)/.exec(R)[1]),A=L>=2);let C=null,P={};const D=new St(0,0,t.canvas.width,t.canvas.height),I=new St(0,0,t.canvas.width,t.canvas.height);function N(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===P&&(P=I(s,a));const o=n?I(s,a):P;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 z(t,e){return t.generateMipmaps&&e&&t.minFilter!==p&&t.minFilter!==g}function F(e,n,r,s){t.generateMipmap(e);i.get(n).__maxMipLevel=Math.log2(Math.max(r,s))}function O(n,i,r){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 s=i;return 6403===i&&(5126===r&&(s=33326),5131===r&&(s=33325),5121===r&&(s=33321)),6407===i&&(5126===r&&(s=34837),5131===r&&(s=34843),5121===r&&(s=32849)),6408===i&&(5126===r&&(s=34836),5131===r&&(s=34842),5121===r&&(s=32856)),33325!==s&&33326!==s&&34842!==s&&34836!==s||e.get("EXT_color_buffer_float"),s}function H(t){return t===p||t===m||t===f?9728:9729}function G(e){const n=e.target;n.removeEventListener("dispose",G),function(e){const n=i.get(e);if(void 0===n.__webglInit)return;t.deleteTexture(n.__webglTexture),i.remove(e)}(n),n.isVideoTexture&&C.delete(n),a.memory.textures--}function U(e){const n=e.target;n.removeEventListener("dispose",U),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);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);i.remove(n),i.remove(e)}(n),a.memory.textures--}let k=0;function V(t,e){const r=i.get(t);if(t.isVideoTexture&&function(t){const e=a.render.frame;C.get(t)!==e&&(C.set(t,e),t.update())}(t),t.version>0&&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 Z(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 W(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,i,r){if(6!==i.image.length)return;Y(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]:N(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=O(i.internalFormat,p,m);let g;if(X(34067,i,d),a){for(let t=0;t<6;t++){g=h[t].mipmaps;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 Y(e,n){void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",G),e.__webglTexture=t.createTexture(),a.memory.textures++)}function Z(e,i,r){let a=3553;i.isDataTexture2DArray&&(a=35866),i.isDataTexture3D&&(a=32879),Y(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=N(i.image,l,!1,x),h=B(c)||o,d=s.convert(i.format);let m,f=s.convert(i.type),v=O(i.internalFormat,d,f);X(a,i,h);const y=i.mipmaps;if(i.isDepthTexture)v=6402,o?v=i.type===b?36012:i.type===w?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!==w&&(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))),n.texImage2D(3553,0,v,c.width,c.height,0,d,f,null);else if(i.isDataTexture)if(y.length>0&&h){for(let t=0,e=y.length;t0&&h){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),k+=1,t},this.resetTextureUnits=function(){k=0},this.setTexture2D=V,this.setTexture2DArray=function(t,e){const r=i.get(t);t.version>0&&r.__version!==t.version?Z(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?Z(r,t,e):(n.activeTexture(33984+e),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=W,this.setupRenderTarget=function(e){const r=e.texture,l=i.get(e),c=i.get(r);e.addEventListener("dispose",U),c.__webglTexture=t.createTexture(),c.__version=r.version,a.memory.textures++;const h=!0===e.isWebGLCubeRenderTarget,u=!0===e.isWebGLMultisampleRenderTarget,d=r.isDataTexture3D||r.isDataTexture2DArray,p=B(e)||o;if(!o||r.format!==T||r.type!==b&&r.type!==M||(r.format=E,console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.")),h){l.__webglFramebuffer=[];for(let e=0;e<6;e++)l.__webglFramebuffer[e]=t.createFramebuffer()}else if(l.__webglFramebuffer=t.createFramebuffer(),u)if(o){l.__webglMultisampledFramebuffer=t.createFramebuffer(),l.__webglColorRenderbuffer=t.createRenderbuffer(),t.bindRenderbuffer(36161,l.__webglColorRenderbuffer);const i=s.convert(r.format),a=s.convert(r.type),o=O(r.internalFormat,i,a),c=$(e);t.renderbufferStorageMultisample(36161,c,o,e.width,e.height),n.bindFramebuffer(36160,l.__webglMultisampledFramebuffer),t.framebufferRenderbuffer(36160,36064,36161,l.__webglColorRenderbuffer),t.bindRenderbuffer(36161,null),e.depthBuffer&&(l.__webglDepthRenderbuffer=t.createRenderbuffer(),Q(l.__webglDepthRenderbuffer,e,!0)),n.bindFramebuffer(36160,null)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");if(h){n.bindTexture(34067,c.__webglTexture),X(34067,r,p);for(let t=0;t<6;t++)J(l.__webglFramebuffer[t],e,36064,34069+t);z(r,p)&&F(34067,r,e.width,e.height),n.bindTexture(34067,null)}else{let t=3553;if(d)if(o){t=r.isDataTexture3D?32879:35866}else console.warn("THREE.DataTexture3D and THREE.DataTexture2DArray only supported with WebGL2.");n.bindTexture(t,c.__webglTexture),X(t,r,p),J(l.__webglFramebuffer,e,36064,t),z(r,p)&&F(3553,r,e.width,e.height),n.bindTexture(3553,null)}e.depthBuffer&&K(e)},this.updateRenderTargetMipmap=function(t){const e=t.texture;if(z(e,B(t)||o)){const r=t.isWebGLCubeRenderTarget?34067:3553,s=i.get(e).__webglTexture;n.bindTexture(r,s),F(r,e,t.width,t.height),n.bindTexture(r,null)}},this.updateMultisampleRenderTarget=function(e){if(e.isWebGLMultisampleRenderTarget)if(o){const r=e.width,s=e.height;let a=16384;e.depthBuffer&&(a|=256),e.stencilBuffer&&(a|=1024);const o=i.get(e);n.bindFramebuffer(36008,o.__webglMultisampledFramebuffer),n.bindFramebuffer(36009,o.__webglFramebuffer),t.blitFramebuffer(0,0,r,s,0,0,r,s,a,9728),n.bindFramebuffer(36008,null),n.bindFramebuffer(36009,o.__webglMultisampledFramebuffer)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.")},this.safeSetTexture2D=function(t,e){t&&t.isWebGLRenderTarget&&(!1===tt&&(console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead."),tt=!0),t=t.texture),V(t,e)},this.safeSetTextureCube=function(t,e){t&&t.isWebGLCubeRenderTarget&&(!1===et&&(console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead."),et=!0),t=t.texture),W(t,e)}}function ms(t,e,n){const i=n.isWebGL2;return{convert:function(t){let n;if(t===x)return 5121;if(1017===t)return 32819;if(1018===t)return 32820;if(1019===t)return 33635;if(1010===t)return 5120;if(1011===t)return 5122;if(t===_)return 5123;if(1013===t)return 5124;if(t===w)return 5125;if(t===b)return 5126;if(t===M)return i?5131:(n=e.get("OES_texture_half_float"),null!==n?n.HALF_FLOAT_OES:null);if(1021===t)return 6406;if(t===T)return 6407;if(t===E)return 6408;if(1024===t)return 6409;if(1025===t)return 6410;if(t===A)return 6402;if(t===L)return 34041;if(1028===t)return 6403;if(1029===t)return 36244;if(1030===t)return 33319;if(1031===t)return 33320;if(1032===t)return 36248;if(1033===t)return 36249;if(t===R||t===C||t===P||t===D){if(n=e.get("WEBGL_compressed_texture_s3tc"),null===n)return null;if(t===R)return n.COMPRESSED_RGB_S3TC_DXT1_EXT;if(t===C)return n.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(t===P)return n.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(t===D)return n.COMPRESSED_RGBA_S3TC_DXT5_EXT}if(t===I||t===N||t===B||t===z){if(n=e.get("WEBGL_compressed_texture_pvrtc"),null===n)return null;if(t===I)return n.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(t===N)return n.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(t===B)return n.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(t===z)return n.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(36196===t)return n=e.get("WEBGL_compressed_texture_etc1"),null!==n?n.COMPRESSED_RGB_ETC1_WEBGL:null;if((t===F||t===O)&&(n=e.get("WEBGL_compressed_texture_etc"),null!==n)){if(t===F)return n.COMPRESSED_RGB8_ETC2;if(t===O)return n.COMPRESSED_RGBA8_ETC2_EAC}return 37808===t||37809===t||37810===t||37811===t||37812===t||37813===t||37814===t||37815===t||37816===t||37817===t||37818===t||37819===t||37820===t||37821===t||37840===t||37841===t||37842===t||37843===t||37844===t||37845===t||37846===t||37847===t||37848===t||37849===t||37850===t||37851===t||37852===t||37853===t?(n=e.get("WEBGL_compressed_texture_astc"),null!==n?t:null):36492===t?(n=e.get("EXT_texture_compression_bptc"),null!==n?t:null):t===S?i?34042:(n=e.get("WEBGL_depth_texture"),null!==n?n.UNSIGNED_INT_24_8_WEBGL:null):void 0}}}class fs extends Kn{constructor(t=[]){super(),this.cameras=t}}fs.prototype.isArrayCamera=!0;class gs extends Ce{constructor(){super(),this.type="Group"}}gs.prototype.isGroup=!0;const vs={type:"move"};class ys{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return null===this._hand&&(this._hand=new gs,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return null===this._targetRay&&(this._targetRay=new gs,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new Lt,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new Lt),this._targetRay}getGripSpace(){return null===this._grip&&(this._grip=new gs,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new Lt,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new Lt),this._grip}dispatchEvent(t){return null!==this._targetRay&&this._targetRay.dispatchEvent(t),null!==this._grip&&this._grip.dispatchEvent(t),null!==this._hand&&this._hand.dispatchEvent(t),this}disconnect(t){return this.dispatchEvent({type:"disconnected",data:t}),null!==this._targetRay&&(this._targetRay.visible=!1),null!==this._grip&&(this._grip.visible=!1),null!==this._hand&&(this._hand.visible=!1),this}update(t,e,n){let i=null,r=null,s=null;const a=this._targetRay,o=this._grip,l=this._hand;if(t&&"visible-blurred"!==e.session.visibilityState)if(null!==a&&(i=e.getPose(t.targetRaySpace,n),null!==i&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(vs))),l&&t.hand){s=!0;for(const i of t.hand.values()){const t=e.getJointPose(i,n);if(void 0===l.joints[i.jointName]){const t=new gs;t.matrixAutoUpdate=!1,t.visible=!1,l.joints[i.jointName]=t,l.add(t)}const r=l.joints[i.jointName];null!==t&&(r.matrix.fromArray(t.transform.matrix),r.matrix.decompose(r.position,r.rotation,r.scale),r.jointRadius=t.radius),r.visible=null!==t}const i=l.joints["index-finger-tip"],r=l.joints["thumb-tip"],a=i.position.distanceTo(r.position),o=.02,c=.005;l.inputState.pinching&&a>o+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 xs extends rt{constructor(t,e){super();const n=this,i=t.state;let r=null,s=1,a=null,o="local-floor",l=null;const c=[],h=new Map,u=new Kn;u.layers.enable(1),u.viewport=new St;const d=new Kn;d.layers.enable(2),d.viewport=new St;const p=[u,d],m=new fs;m.layers.enable(1),m.layers.enable(2);let f=null,g=null;function v(t){const e=h.get(t.inputSource);e&&e.dispatchEvent({type:t.type,data:t.inputSource})}function y(){h.forEach((function(t,e){t.disconnect(e)})),h.clear(),f=null,g=null,i.bindXRFramebuffer(null),t.setRenderTarget(t.getRenderTarget()),S.stop(),n.isPresenting=!1,n.dispatchEvent({type:"sessionend"})}function x(t){const e=r.inputSources;for(let t=0;t0&&Rt(s,t,e),a.length>0&&Rt(a,t,e),null!==_&&(J.updateRenderTargetMipmap(_),J.updateMultisampleRenderTarget(_)),!0===t.isScene&&t.onAfterRender(f,t,e),q.buffers.depth.setTest(!0),q.buffers.depth.setMask(!0),q.buffers.color.setMask(!0),q.setPolygonOffset(!1),dt.resetDefaultState(),w=-1,S=null,m.pop(),d=m.length>0?m[m.length-1]:null,p.pop(),u=p.length>0?p[p.length-1]:null},this.getActiveCubeFace=function(){return v},this.getActiveMipmapLevel=function(){return y},this.getRenderTarget=function(){return _},this.setRenderTarget=function(t,e=0,n=0){_=t,v=e,y=n,t&&void 0===Z.get(t).__webglFramebuffer&&J.setupRenderTarget(t);let i=null,r=!1,s=!1;if(t){const n=t.texture;(n.isDataTexture3D||n.isDataTexture2DArray)&&(s=!0);const a=Z.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(i=a[e],r=!0):i=t.isWebGLMultisampleRenderTarget?Z.get(t).__webglMultisampledFramebuffer:a,T.copy(t.viewport),A.copy(t.scissor),L=t.scissorTest}else T.copy(N).multiplyScalar(P).floor(),A.copy(B).multiplyScalar(P).floor(),L=z;if(q.bindFramebuffer(36160,i),q.viewport(T),q.scissor(A),q.setScissorTest(L),r){const i=Z.get(t.texture);pt.framebufferTexture2D(36160,36064,34069+e,i.__webglTexture,n)}else if(s){const i=Z.get(t.texture),r=e||0;pt.framebufferTextureLayer(36160,36064,i.__webglTexture,n||0,r)}},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=Z.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){q.bindFramebuffer(36160,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==E&&ut.convert(o)!==pt.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===M&&(W.has("EXT_color_buffer_half_float")||j.isWebGL2&&W.has("EXT_color_buffer_float"));if(!(l===x||ut.convert(l)===pt.getParameter(35738)||l===b&&(j.isWebGL2||W.has("OES_texture_float")||W.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");36053===pt.checkFramebufferStatus(36160)?e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&pt.readPixels(e,n,i,r,ut.convert(o),ut.convert(l),s):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{const t=null!==_?Z.get(_).__webglFramebuffer:null;q.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i),a=ut.convert(e.format);J.setTexture2D(e,0),pt.copyTexImage2D(3553,n,a,t.x,t.y,r,s,0),q.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=ut.convert(n.format),o=ut.convert(n.type);J.setTexture2D(n,0),pt.pixelStorei(37440,n.flipY),pt.pixelStorei(37441,n.premultiplyAlpha),pt.pixelStorei(3317,n.unpackAlignment),e.isDataTexture?pt.texSubImage2D(3553,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?pt.compressedTexSubImage2D(3553,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):pt.texSubImage2D(3553,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&&pt.generateMipmap(3553),q.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(f.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const{width:s,height:a,data:o}=n.image,l=ut.convert(i.format),c=ut.convert(i.type);let h;if(i.isDataTexture3D)J.setTexture3D(i,0),h=32879;else{if(!i.isDataTexture2DArray)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");J.setTexture2DArray(i,0),h=35866}pt.pixelStorei(37440,i.flipY),pt.pixelStorei(37441,i.premultiplyAlpha),pt.pixelStorei(3317,i.unpackAlignment);const u=pt.getParameter(3314),d=pt.getParameter(32878),p=pt.getParameter(3316),m=pt.getParameter(3315),g=pt.getParameter(32877);pt.pixelStorei(3314,s),pt.pixelStorei(32878,a),pt.pixelStorei(3316,t.min.x),pt.pixelStorei(3315,t.min.y),pt.pixelStorei(32877,t.min.z),pt.texSubImage3D(h,r,e.x,e.y,e.z,t.max.x-t.min.x+1,t.max.y-t.min.y+1,t.max.z-t.min.z+1,l,c,o),pt.pixelStorei(3314,u),pt.pixelStorei(32878,d),pt.pixelStorei(3316,p),pt.pixelStorei(3315,m),pt.pixelStorei(32877,g),0===r&&i.generateMipmaps&&pt.generateMipmap(h),q.unbindTexture()},this.initTexture=function(t){J.setTexture2D(t,0),q.unbindTexture()},this.resetState=function(){v=0,y=0,_=null,q.reset(),dt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}class bs extends ws{}bs.prototype.isWebGL1Renderer=!0;class Ms{constructor(t,e=25e-5){this.name="",this.color=new tn(t),this.density=e}clone(){return new Ms(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}Ms.prototype.isFogExp2=!0;class Ss{constructor(t,e=1,n=1e3){this.name="",this.color=new tn(t),this.near=e,this.far=n}clone(){return new Ss(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}Ss.prototype.isFog=!0;class Ts extends Ce{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.background&&(e.object.background=this.background.toJSON(t)),null!==this.environment&&(e.object.environment=this.environment.toJSON(t)),null!==this.fog&&(e.object.fog=this.fog.toJSON()),e}}Ts.prototype.isScene=!0;class Es{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(),this.onUploadCallback=function(){}}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:Ps.clone(),uv:je.getUV(Ps,Fs,Os,Hs,Gs,Us,ks,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 Ws(t,e,n,i,r,s){Ns.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(Bs.x=s*Ns.x-r*Ns.y,Bs.y=r*Ns.x+s*Ns.y):Bs.copy(Ns),t.copy(e),t.x+=Bs.x,t.y+=Bs.y,t.applyMatrix4(zs)}Vs.prototype.isSprite=!0;const js=new Lt,qs=new Lt;class Xs extends Ce{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){js.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(js);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){js.setFromMatrixPosition(t.matrixWorld),qs.setFromMatrixPosition(this.matrixWorld);const n=js.distanceTo(qs)/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.")}}}fa.prototype.isLine=!0;const ga=new Lt,va=new Lt;class ya extends fa{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 Ea(t,e,n,i,r,s,a){const o=ba.distanceSqToPoint(t);if(or.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}Ta.prototype.isPoints=!0;class Aa extends bt{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)}}Aa.prototype.isVideoTexture=!0;class La extends bt{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}}La.prototype.isCompressedTexture=!0;class Ra extends bt{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.needsUpdate=!0}}Ra.prototype.isCanvasTexture=!0;class Ca extends bt{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}}Ca.prototype.isDepthTexture=!0;class Pa extends En{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 Lt,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 mn(s,3)),this.setAttribute("normal",new mn(a,3)),this.setAttribute("uv",new mn(o,2))}}class Da extends En{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 Lt;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 mn(h,3)),this.setAttribute("normal",new mn(u,3)),this.setAttribute("uv",new mn(d,2))}}class Ia extends Da{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}}}class Na extends En{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 mn(r,3)),this.setAttribute("normal",new mn(r.slice(),3)),this.setAttribute("uv",new mn(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}}class Ba extends Na{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}}}const za=new Lt,Fa=new Lt,Oa=new Lt,Ha=new je;class Ga extends En{constructor(t,e){if(super(),this.type="EdgesGeometry",this.parameters={thresholdAngle:e},e=void 0!==e?e:1,!0===t.isGeometry)return void console.error("THREE.EdgesGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.");const n=Math.pow(10,4),i=Math.cos(ot*e),r=t.getIndex(),s=t.getAttribute("position"),a=r?r.count:s.count,o=[0,0,0],l=["a","b","c"],c=new Array(3),h={},u=[];for(let t=0;t80*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 Wa(s,a,n,o,l,p),a};function ka(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=co(s,t[s],t[s+1],a);return a&&io(a,a.next)&&(ho(a),a=a.next),a}function Va(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!io(i,i.next)&&0!==no(i.prev,i,i.next))i=i.next;else{if(ho(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Wa(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=Ka(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?qa(t,i,r,s):ja(t))e.push(o.i/n),e.push(t.i/n),e.push(l.i/n),ho(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Wa(t=Xa(Va(t),e,n),e,n,i,r,s,2):2===a&&Ya(t,e,n,i,r,s):Wa(Va(t),e,n,i,r,s,1);break}}function ja(t){const e=t.prev,n=t,i=t.next;if(no(e,n,i)>=0)return!1;let r=t.next.next;for(;r!==t.prev;){if(to(e.x,e.y,n.x,n.y,i.x,i.y,r.x,r.y)&&no(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function qa(t,e,n,i){const r=t.prev,s=t,a=t.next;if(no(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=Ka(o,l,e,n,i),d=Ka(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&&to(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&no(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,m!==t.prev&&m!==t.next&&to(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&no(m.prev,m,m.next)>=0)return!1;m=m.nextZ}for(;p&&p.z>=u;){if(p!==t.prev&&p!==t.next&&to(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&no(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;m&&m.z<=d;){if(m!==t.prev&&m!==t.next&&to(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&no(m.prev,m,m.next)>=0)return!1;m=m.nextZ}return!0}function Xa(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!io(r,s)&&ro(r,i,i.next,s)&&oo(r,s)&&oo(s,r)&&(e.push(r.i/n),e.push(i.i/n),e.push(s.i/n),ho(i),ho(i.next),i=t=s),i=i.next}while(i!==t);return Va(i)}function Ya(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&eo(a,t)){let o=lo(a,t);return a=Va(a,a.next),o=Va(o,o.next),Wa(a,e,n,i,r,s),void Wa(o,e,n,i,r,s)}t=t.next}a=a.next}while(a!==t)}function Za(t,e){return t.x-e.x}function Ja(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&&to(rs.x||n.x===s.x&&Qa(s,n)))&&(s=n,u=h)),n=n.next}while(n!==o);return s}(t,e)){const n=lo(e,t);Va(e,e.next),Va(n,n.next)}}function Qa(t,e){return no(t.prev,t,e.prev)<0&&no(e.next,t,t.next)<0}function Ka(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 $a(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 eo(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&&ro(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(oo(t,e)&&oo(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)&&(no(t.prev,t,e.prev)||no(t,e.prev,e))||io(t,e)&&no(t.prev,t,t.next)>0&&no(e.prev,e,e.next)>0)}function no(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function io(t,e){return t.x===e.x&&t.y===e.y}function ro(t,e,n,i){const r=ao(no(t,e,n)),s=ao(no(t,e,i)),a=ao(no(n,i,t)),o=ao(no(n,i,e));return r!==s&&a!==o||(!(0!==r||!so(t,n,e))||(!(0!==s||!so(t,i,e))||(!(0!==a||!so(n,t,i))||!(0!==o||!so(n,e,i)))))}function so(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 ao(t){return t>0?1:t<0?-1:0}function oo(t,e){return no(t.prev,t,t.next)<0?no(t,e,t.next)>=0&&no(t,t.prev,e)>=0:no(t,e,t.prev)<0||no(t,t.next,e)<0}function lo(t,e){const n=new uo(t.i,t.x,t.y),i=new uo(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 co(t,e,n,i){const r=new uo(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 ho(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 uo(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 po{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 fo(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;t=0?(t(i-o,p,h),u.subVectors(c,h)):(t(i+o,p,h),u.subVectors(h,c)),p-o>=0?(t(i,p-o,h),d.subVectors(c,h)):(t(i,p+o,h),d.subVectors(h,c)),l.crossVectors(u,d).normalize(),s.push(l.x,l.y,l.z),a.push(i,p)}}for(let t=0;t0)&&d.push(e,r,l),(t!==n-1||o=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=Vo.arraySlice(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=Vo.arraySlice(t.resultBuffer,e,n)}if("quaternion"===r){(new At).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=Vo.arraySlice(n,r,s),this.values=Vo.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&&Vo.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=Vo.arraySlice(this.times),e=Vo.arraySlice(this.values),n=this.getValueSize(),i=this.getInterpolation()===U,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=Vo.arraySlice(t,0,s),this.values=Vo.arraySlice(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=Vo.arraySlice(this.times,0),e=Vo.arraySlice(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Yo.prototype.TimeBufferType=Float32Array,Yo.prototype.ValueBufferType=Float32Array,Yo.prototype.DefaultInterpolation=G;class Zo extends Yo{}Zo.prototype.ValueTypeName="bool",Zo.prototype.ValueBufferType=Array,Zo.prototype.DefaultInterpolation=H,Zo.prototype.InterpolantFactoryMethodLinear=void 0,Zo.prototype.InterpolantFactoryMethodSmooth=void 0;class Jo extends Yo{}Jo.prototype.ValueTypeName="color";class Qo extends Yo{}Qo.prototype.ValueTypeName="number";class Ko extends Wo{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)At.slerpFlat(r,0,s,l-a,s,l,o);return r}}class $o extends Yo{InterpolantFactoryMethodLinear(t){return new Ko(this.times,this.values,this.getValueSize(),t)}}$o.prototype.ValueTypeName="quaternion",$o.prototype.DefaultInterpolation=G,$o.prototype.InterpolantFactoryMethodSmooth=void 0;class tl extends Yo{}tl.prototype.ValueTypeName="string",tl.prototype.ValueBufferType=Array,tl.prototype.DefaultInterpolation=H,tl.prototype.InterpolantFactoryMethodLinear=void 0,tl.prototype.InterpolantFactoryMethodSmooth=void 0;class el extends Yo{}el.prototype.ValueTypeName="vector";class nl{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(il(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(Yo.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=[];Vo.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;t0||0===t.search(/^data\:image\/jpeg/);r.format=i?T:E,r.needsUpdate=!0,void 0!==e&&e(r)}),n,i),r}}class ml{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){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 Lt);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 Lt,i=[],r=[],s=[],a=new Lt,o=new se;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new Lt),i[e].normalize()}r[0]=new Lt,s[0]=new Lt;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 fl extends ml{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]:(yl.subVectors(i[0],i[1]).add(i[0]),a=yl);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(Ml(a,o.x,l.x,c.x,h.x),Ml(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=e){const t=n[i]-e,r=this.curves[i],s=r.getLength(),a=0===s?0:1-t/s;return r.getPointAt(a)}i++}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 zl extends Bl{constructor(t){super(t),this.uuid=ct(),this.type="Shape",this.holes=[]}getPointsHoles(t){const e=[];for(let n=0,i=this.holes.length;n0: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 tn).setHex(r.value);break;case"v2":i.uniforms[e].value=(new vt).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Lt).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new St).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new yt).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new se).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.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.transmission&&(i.transmission=t.transmission),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),i}setTextures(t){return this.textures=t,this}}class rc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;nNumber.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=po.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 zl,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;t0){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){At.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;At.multiplyQuaternionsFlat(t,s,t,e,t,n),At.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 Bc="\\[\\]\\.:\\/",zc=new RegExp("[\\[\\]\\.:\\/]","g"),Fc="[^\\[\\]\\.:\\/]",Oc="[^"+Bc.replace("\\.","")+"]",Hc=/((?:WC+[\/:])*)/.source.replace("WC",Fc),Gc=/(WCOD+)?/.source.replace("WCOD",Oc),Uc=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",Fc),kc=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",Fc),Vc=new RegExp("^"+Hc+Gc+Uc+kc+"$"),Wc=["material","materials","bones"];class jc{constructor(t,e,n){this.path=e,this.parsedPath=n||jc.parseTrackName(e),this.node=jc.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 jc.Composite(t,e,n):new jc(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(zc,"")}static parseTrackName(t){const e=Vc.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!==Wc.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 jc(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()}}}qc.prototype.isAnimationObjectGroup=!0;class Xc{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;switch(this.blendMode){case q:for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);break;case j:default: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 Yc 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 Nc(jc.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 void 0===e&&(console.warn("THREE.Box2: .getParameter() target is now required"),e=new vt),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 void 0===e&&(console.warn("THREE.Box2: .clampPoint() target is now required"),e=new vt),e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return th.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)}}eh.prototype.isBox2=!0;const nh=new Lt,ih=new Lt;class rh{constructor(t=new Lt,e=new Lt){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 void 0===t&&(console.warn("THREE.Line3: .getCenter() target is now required"),t=new Lt),t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return void 0===t&&(console.warn("THREE.Line3: .delta() target is now required"),t=new Lt),t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return void 0===e&&(console.warn("THREE.Line3: .at() target is now required"),e=new Lt),this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){nh.subVectors(t,this.start),ih.subVectors(this.end,this.start);const n=ih.dot(ih);let i=ih.dot(nh)/n;return e&&(i=ht(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return void 0===n&&(console.warn("THREE.Line3: .closestPointToPoint() target is now required"),n=new Lt),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)}}class sh extends Ce{constructor(t){super(),this.material=t,this.render=function(){},this.hasPositions=!1,this.hasNormals=!1,this.hasColors=!1,this.hasUvs=!1,this.positionArray=null,this.normalArray=null,this.colorArray=null,this.uvArray=null,this.count=0}}sh.prototype.isImmediateRenderObject=!0;const ah=new Lt;const oh=new Lt,lh=new se,ch=new se;class hh extends ya{constructor(t){const e=uh(t),n=new En,i=[],r=[],s=new tn(0,0,1),a=new tn(0,1,0);for(let t=0;t4?a=Ph[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 En;x.setAttribute("position",new sn(g,p)),x.setAttribute("uv",new sn(v,m)),x.setAttribute("faceIndex",new sn(y,f)),t.push(x),i>4&&i--}return{_lodPlanes:t,_sizeLods:e,_sigmas:n}}function Zh(t){const e=new Tt(3*Ch,3*Ch,t);return e.texture.mapping=l,e.texture.name="PMREM.cubeUv",e.scissorTest=!0,e}function Jh(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function Qh(){const t=new vt(1,1);return new Io({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null},texelSize:{value:t},inputEncoding:{value:Nh[3e3]},outputEncoding:{value:Nh[3e3]}},vertexShader:$h(),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${tu()}\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 Kh(){return new Io({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},inputEncoding:{value:Nh[3e3]},outputEncoding:{value:Nh[3e3]}},vertexShader:$h(),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${tu()}\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 $h(){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 tu(){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"}ml.create=function(t,e){return console.log("THREE.Curve.create() has been deprecated"),t.prototype=Object.create(ml.prototype),t.prototype.constructor=t,t.prototype.getPoint=e,t},Bl.prototype.fromPoints=function(t){return console.warn("THREE.Path: .fromPoints() has been renamed to .setFromPoints()."),this.setFromPoints(t)},fh.prototype.setColors=function(){console.error("THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.")},hh.prototype.update=function(){console.error("THREE.SkeletonHelper: update() no longer needs to be called.")},ol.prototype.extractUrlBase=function(t){return console.warn("THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead."),rc.extractUrlBase(t)},ol.Handlers={add:function(){console.error("THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.")},get:function(){console.error("THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.")}},eh.prototype.center=function(t){return console.warn("THREE.Box2: .center() has been renamed to .getCenter()."),this.getCenter(t)},eh.prototype.empty=function(){return console.warn("THREE.Box2: .empty() has been renamed to .isEmpty()."),this.isEmpty()},eh.prototype.isIntersectionBox=function(t){return console.warn("THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox()."),this.intersectsBox(t)},eh.prototype.size=function(t){return console.warn("THREE.Box2: .size() has been renamed to .getSize()."),this.getSize(t)},Pt.prototype.center=function(t){return console.warn("THREE.Box3: .center() has been renamed to .getCenter()."),this.getCenter(t)},Pt.prototype.empty=function(){return console.warn("THREE.Box3: .empty() has been renamed to .isEmpty()."),this.isEmpty()},Pt.prototype.isIntersectionBox=function(t){return console.warn("THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox()."),this.intersectsBox(t)},Pt.prototype.isIntersectionSphere=function(t){return console.warn("THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere()."),this.intersectsSphere(t)},Pt.prototype.size=function(t){return console.warn("THREE.Box3: .size() has been renamed to .getSize()."),this.getSize(t)},Jt.prototype.empty=function(){return console.warn("THREE.Sphere: .empty() has been renamed to .isEmpty()."),this.isEmpty()},ai.prototype.setFromMatrix=function(t){return console.warn("THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix()."),this.setFromProjectionMatrix(t)},rh.prototype.center=function(t){return console.warn("THREE.Line3: .center() has been renamed to .getCenter()."),this.getCenter(t)},yt.prototype.flattenToArrayOffset=function(t,e){return console.warn("THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead."),this.toArray(t,e)},yt.prototype.multiplyVector3=function(t){return console.warn("THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead."),t.applyMatrix3(this)},yt.prototype.multiplyVector3Array=function(){console.error("THREE.Matrix3: .multiplyVector3Array() has been removed.")},yt.prototype.applyToBufferAttribute=function(t){return console.warn("THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead."),t.applyMatrix3(this)},yt.prototype.applyToVector3Array=function(){console.error("THREE.Matrix3: .applyToVector3Array() has been removed.")},yt.prototype.getInverse=function(t){return console.warn("THREE.Matrix3: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead."),this.copy(t).invert()},se.prototype.extractPosition=function(t){return console.warn("THREE.Matrix4: .extractPosition() has been renamed to .copyPosition()."),this.copyPosition(t)},se.prototype.flattenToArrayOffset=function(t,e){return console.warn("THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead."),this.toArray(t,e)},se.prototype.getPosition=function(){return console.warn("THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead."),(new Lt).setFromMatrixColumn(this,3)},se.prototype.setRotationFromQuaternion=function(t){return console.warn("THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion()."),this.makeRotationFromQuaternion(t)},se.prototype.multiplyToArray=function(){console.warn("THREE.Matrix4: .multiplyToArray() has been removed.")},se.prototype.multiplyVector3=function(t){return console.warn("THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},se.prototype.multiplyVector4=function(t){return console.warn("THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},se.prototype.multiplyVector3Array=function(){console.error("THREE.Matrix4: .multiplyVector3Array() has been removed.")},se.prototype.rotateAxis=function(t){console.warn("THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead."),t.transformDirection(this)},se.prototype.crossVector=function(t){return console.warn("THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},se.prototype.translate=function(){console.error("THREE.Matrix4: .translate() has been removed.")},se.prototype.rotateX=function(){console.error("THREE.Matrix4: .rotateX() has been removed.")},se.prototype.rotateY=function(){console.error("THREE.Matrix4: .rotateY() has been removed.")},se.prototype.rotateZ=function(){console.error("THREE.Matrix4: .rotateZ() has been removed.")},se.prototype.rotateByAxis=function(){console.error("THREE.Matrix4: .rotateByAxis() has been removed.")},se.prototype.applyToBufferAttribute=function(t){return console.warn("THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead."),t.applyMatrix4(this)},se.prototype.applyToVector3Array=function(){console.error("THREE.Matrix4: .applyToVector3Array() has been removed.")},se.prototype.makeFrustum=function(t,e,n,i,r,s){return console.warn("THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead."),this.makePerspective(t,e,i,n,r,s)},se.prototype.getInverse=function(t){return console.warn("THREE.Matrix4: .getInverse() has been removed. Use matrixInv.copy( matrix ).invert(); instead."),this.copy(t).invert()},Ne.prototype.isIntersectionLine=function(t){return console.warn("THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine()."),this.intersectsLine(t)},At.prototype.multiplyVector3=function(t){return console.warn("THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead."),t.applyQuaternion(this)},At.prototype.inverse=function(){return console.warn("THREE.Quaternion: .inverse() has been renamed to invert()."),this.invert()},re.prototype.isIntersectionBox=function(t){return console.warn("THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox()."),this.intersectsBox(t)},re.prototype.isIntersectionPlane=function(t){return console.warn("THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane()."),this.intersectsPlane(t)},re.prototype.isIntersectionSphere=function(t){return console.warn("THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere()."),this.intersectsSphere(t)},je.prototype.area=function(){return console.warn("THREE.Triangle: .area() has been renamed to .getArea()."),this.getArea()},je.prototype.barycoordFromPoint=function(t,e){return console.warn("THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord()."),this.getBarycoord(t,e)},je.prototype.midpoint=function(t){return console.warn("THREE.Triangle: .midpoint() has been renamed to .getMidpoint()."),this.getMidpoint(t)},je.prototypenormal=function(t){return console.warn("THREE.Triangle: .normal() has been renamed to .getNormal()."),this.getNormal(t)},je.prototype.plane=function(t){return console.warn("THREE.Triangle: .plane() has been renamed to .getPlane()."),this.getPlane(t)},je.barycoordFromPoint=function(t,e,n,i,r){return console.warn("THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord()."),je.getBarycoord(t,e,n,i,r)},je.normal=function(t,e,n,i){return console.warn("THREE.Triangle: .normal() has been renamed to .getNormal()."),je.getNormal(t,e,n,i)},zl.prototype.extractAllPoints=function(t){return console.warn("THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead."),this.extractPoints(t)},zl.prototype.extrude=function(t){return console.warn("THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead."),new go(this,t)},zl.prototype.makeGeometry=function(t){return console.warn("THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead."),new Mo(this,t)},vt.prototype.fromAttribute=function(t,e,n){return console.warn("THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute()."),this.fromBufferAttribute(t,e,n)},vt.prototype.distanceToManhattan=function(t){return console.warn("THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo()."),this.manhattanDistanceTo(t)},vt.prototype.lengthManhattan=function(){return console.warn("THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength()."),this.manhattanLength()},Lt.prototype.setEulerFromRotationMatrix=function(){console.error("THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.")},Lt.prototype.setEulerFromQuaternion=function(){console.error("THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.")},Lt.prototype.getPositionFromMatrix=function(t){return console.warn("THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition()."),this.setFromMatrixPosition(t)},Lt.prototype.getScaleFromMatrix=function(t){return console.warn("THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale()."),this.setFromMatrixScale(t)},Lt.prototype.getColumnFromMatrix=function(t,e){return console.warn("THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn()."),this.setFromMatrixColumn(e,t)},Lt.prototype.applyProjection=function(t){return console.warn("THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead."),this.applyMatrix4(t)},Lt.prototype.fromAttribute=function(t,e,n){return console.warn("THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute()."),this.fromBufferAttribute(t,e,n)},Lt.prototype.distanceToManhattan=function(t){return console.warn("THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo()."),this.manhattanDistanceTo(t)},Lt.prototype.lengthManhattan=function(){return console.warn("THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength()."),this.manhattanLength()},St.prototype.fromAttribute=function(t,e,n){return console.warn("THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute()."),this.fromBufferAttribute(t,e,n)},St.prototype.lengthManhattan=function(){return console.warn("THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength()."),this.manhattanLength()},Ce.prototype.getChildByName=function(t){return console.warn("THREE.Object3D: .getChildByName() has been renamed to .getObjectByName()."),this.getObjectByName(t)},Ce.prototype.renderDepth=function(){console.warn("THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.")},Ce.prototype.translate=function(t,e){return console.warn("THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead."),this.translateOnAxis(e,t)},Ce.prototype.getWorldRotation=function(){console.error("THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.")},Ce.prototype.applyMatrix=function(t){return console.warn("THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4()."),this.applyMatrix4(t)},Object.defineProperties(Ce.prototype,{eulerOrder:{get:function(){return console.warn("THREE.Object3D: .eulerOrder is now .rotation.order."),this.rotation.order},set:function(t){console.warn("THREE.Object3D: .eulerOrder is now .rotation.order."),this.rotation.order=t}},useQuaternion:{get:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")},set:function(){console.warn("THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.")}}}),Wn.prototype.setDrawMode=function(){console.error("THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.")},Object.defineProperties(Wn.prototype,{drawMode:{get:function(){return console.error("THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode."),0},set:function(){console.error("THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.")}}}),$s.prototype.initBones=function(){console.error("THREE.SkinnedMesh: initBones() has been removed.")},Kn.prototype.setLens=function(t,e){console.warn("THREE.PerspectiveCamera.setLens is deprecated. Use .setFocalLength and .filmGauge for a photographic setup."),void 0!==e&&(this.filmGauge=e),this.setFocalLength(t)},Object.defineProperties(Fl.prototype,{onlyShadow:{set:function(){console.warn("THREE.Light: .onlyShadow has been removed.")}},shadowCameraFov:{set:function(t){console.warn("THREE.Light: .shadowCameraFov is now .shadow.camera.fov."),this.shadow.camera.fov=t}},shadowCameraLeft:{set:function(t){console.warn("THREE.Light: .shadowCameraLeft is now .shadow.camera.left."),this.shadow.camera.left=t}},shadowCameraRight:{set:function(t){console.warn("THREE.Light: .shadowCameraRight is now .shadow.camera.right."),this.shadow.camera.right=t}},shadowCameraTop:{set:function(t){console.warn("THREE.Light: .shadowCameraTop is now .shadow.camera.top."),this.shadow.camera.top=t}},shadowCameraBottom:{set:function(t){console.warn("THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom."),this.shadow.camera.bottom=t}},shadowCameraNear:{set:function(t){console.warn("THREE.Light: .shadowCameraNear is now .shadow.camera.near."),this.shadow.camera.near=t}},shadowCameraFar:{set:function(t){console.warn("THREE.Light: .shadowCameraFar is now .shadow.camera.far."),this.shadow.camera.far=t}},shadowCameraVisible:{set:function(){console.warn("THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.")}},shadowBias:{set:function(t){console.warn("THREE.Light: .shadowBias is now .shadow.bias."),this.shadow.bias=t}},shadowDarkness:{set:function(){console.warn("THREE.Light: .shadowDarkness has been removed.")}},shadowMapWidth:{set:function(t){console.warn("THREE.Light: .shadowMapWidth is now .shadow.mapSize.width."),this.shadow.mapSize.width=t}},shadowMapHeight:{set:function(t){console.warn("THREE.Light: .shadowMapHeight is now .shadow.mapSize.height."),this.shadow.mapSize.height=t}}}),Object.defineProperties(sn.prototype,{length:{get:function(){return console.warn("THREE.BufferAttribute: .length has been deprecated. Use .count instead."),this.array.length}},dynamic:{get:function(){return console.warn("THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead."),this.usage===nt},set:function(){console.warn("THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead."),this.setUsage(nt)}}}),sn.prototype.setDynamic=function(t){return console.warn("THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead."),this.setUsage(!0===t?nt:et),this},sn.prototype.copyIndicesArray=function(){console.error("THREE.BufferAttribute: .copyIndicesArray() has been removed.")},sn.prototype.setArray=function(){console.error("THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers")},En.prototype.addIndex=function(t){console.warn("THREE.BufferGeometry: .addIndex() has been renamed to .setIndex()."),this.setIndex(t)},En.prototype.addAttribute=function(t,e){return console.warn("THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute()."),e&&e.isBufferAttribute||e&&e.isInterleavedBufferAttribute?"index"===t?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),this.setIndex(e),this):this.setAttribute(t,e):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),this.setAttribute(t,new sn(arguments[1],arguments[2])))},En.prototype.addDrawCall=function(t,e,n){void 0!==n&&console.warn("THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset."),console.warn("THREE.BufferGeometry: .addDrawCall() is now .addGroup()."),this.addGroup(t,e)},En.prototype.clearDrawCalls=function(){console.warn("THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups()."),this.clearGroups()},En.prototype.computeOffsets=function(){console.warn("THREE.BufferGeometry: .computeOffsets() has been removed.")},En.prototype.removeAttribute=function(t){return console.warn("THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute()."),this.deleteAttribute(t)},En.prototype.applyMatrix=function(t){return console.warn("THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4()."),this.applyMatrix4(t)},Object.defineProperties(En.prototype,{drawcalls:{get:function(){return console.error("THREE.BufferGeometry: .drawcalls has been renamed to .groups."),this.groups}},offsets:{get:function(){return console.warn("THREE.BufferGeometry: .offsets has been renamed to .groups."),this.groups}}}),Es.prototype.setDynamic=function(t){return console.warn("THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead."),this.setUsage(!0===t?nt:et),this},Es.prototype.setArray=function(){console.error("THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers")},go.prototype.getArrays=function(){console.error("THREE.ExtrudeGeometry: .getArrays() has been removed.")},go.prototype.addShapeList=function(){console.error("THREE.ExtrudeGeometry: .addShapeList() has been removed.")},go.prototype.addShape=function(){console.error("THREE.ExtrudeGeometry: .addShape() has been removed.")},Ts.prototype.dispose=function(){console.error("THREE.Scene: .dispose() has been removed.")},Zc.prototype.onUpdate=function(){return console.warn("THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead."),this},Object.defineProperties(Xe.prototype,{wrapAround:{get:function(){console.warn("THREE.Material: .wrapAround has been removed.")},set:function(){console.warn("THREE.Material: .wrapAround has been removed.")}},overdraw:{get:function(){console.warn("THREE.Material: .overdraw has been removed.")},set:function(){console.warn("THREE.Material: .overdraw has been removed.")}},wrapRGB:{get:function(){return console.warn("THREE.Material: .wrapRGB has been removed."),new tn}},shading:{get:function(){console.error("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead.")},set:function(t){console.warn("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead."),this.flatShading=1===t}},stencilMask:{get:function(){return console.warn("THREE."+this.type+": .stencilMask has been removed. Use .stencilFuncMask instead."),this.stencilFuncMask},set:function(t){console.warn("THREE."+this.type+": .stencilMask has been removed. Use .stencilFuncMask instead."),this.stencilFuncMask=t}}}),Object.defineProperties(Jn.prototype,{derivatives:{get:function(){return console.warn("THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives."),this.extensions.derivatives},set:function(t){console.warn("THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives."),this.extensions.derivatives=t}}}),ws.prototype.clearTarget=function(t,e,n,i){console.warn("THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead."),this.setRenderTarget(t),this.clear(e,n,i)},ws.prototype.animate=function(t){console.warn("THREE.WebGLRenderer: .animate() is now .setAnimationLoop()."),this.setAnimationLoop(t)},ws.prototype.getCurrentRenderTarget=function(){return console.warn("THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget()."),this.getRenderTarget()},ws.prototype.getMaxAnisotropy=function(){return console.warn("THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy()."),this.capabilities.getMaxAnisotropy()},ws.prototype.getPrecision=function(){return console.warn("THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision."),this.capabilities.precision},ws.prototype.resetGLState=function(){return console.warn("THREE.WebGLRenderer: .resetGLState() is now .state.reset()."),this.state.reset()},ws.prototype.supportsFloatTextures=function(){return console.warn("THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( 'OES_texture_float' )."),this.extensions.get("OES_texture_float")},ws.prototype.supportsHalfFloatTextures=function(){return console.warn("THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( 'OES_texture_half_float' )."),this.extensions.get("OES_texture_half_float")},ws.prototype.supportsStandardDerivatives=function(){return console.warn("THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( 'OES_standard_derivatives' )."),this.extensions.get("OES_standard_derivatives")},ws.prototype.supportsCompressedTextureS3TC=function(){return console.warn("THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( 'WEBGL_compressed_texture_s3tc' )."),this.extensions.get("WEBGL_compressed_texture_s3tc")},ws.prototype.supportsCompressedTexturePVRTC=function(){return console.warn("THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( 'WEBGL_compressed_texture_pvrtc' )."),this.extensions.get("WEBGL_compressed_texture_pvrtc")},ws.prototype.supportsBlendMinMax=function(){return console.warn("THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( 'EXT_blend_minmax' )."),this.extensions.get("EXT_blend_minmax")},ws.prototype.supportsVertexTextures=function(){return console.warn("THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures."),this.capabilities.vertexTextures},ws.prototype.supportsInstancedArrays=function(){return console.warn("THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( 'ANGLE_instanced_arrays' )."),this.extensions.get("ANGLE_instanced_arrays")},ws.prototype.enableScissorTest=function(t){console.warn("THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest()."),this.setScissorTest(t)},ws.prototype.initMaterial=function(){console.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")},ws.prototype.addPrePlugin=function(){console.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")},ws.prototype.addPostPlugin=function(){console.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")},ws.prototype.updateShadowMap=function(){console.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")},ws.prototype.setFaceCulling=function(){console.warn("THREE.WebGLRenderer: .setFaceCulling() has been removed.")},ws.prototype.allocTextureUnit=function(){console.warn("THREE.WebGLRenderer: .allocTextureUnit() has been removed.")},ws.prototype.setTexture=function(){console.warn("THREE.WebGLRenderer: .setTexture() has been removed.")},ws.prototype.setTexture2D=function(){console.warn("THREE.WebGLRenderer: .setTexture2D() has been removed.")},ws.prototype.setTextureCube=function(){console.warn("THREE.WebGLRenderer: .setTextureCube() has been removed.")},ws.prototype.getActiveMipMapLevel=function(){return console.warn("THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel()."),this.getActiveMipmapLevel()},Object.defineProperties(ws.prototype,{shadowMapEnabled:{get:function(){return this.shadowMap.enabled},set:function(t){console.warn("THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled."),this.shadowMap.enabled=t}},shadowMapType:{get:function(){return this.shadowMap.type},set:function(t){console.warn("THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type."),this.shadowMap.type=t}},shadowMapCullFace:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.")}},context:{get:function(){return console.warn("THREE.WebGLRenderer: .context has been removed. Use .getContext() instead."),this.getContext()}},vr:{get:function(){return console.warn("THREE.WebGLRenderer: .vr has been renamed to .xr"),this.xr}},gammaInput:{get:function(){return console.warn("THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead."),!1},set:function(){console.warn("THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.")}},gammaOutput:{get:function(){return console.warn("THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead."),!1},set:function(t){console.warn("THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead."),this.outputEncoding=!0===t?Y:X}},toneMappingWhitePoint:{get:function(){return console.warn("THREE.WebGLRenderer: .toneMappingWhitePoint has been removed."),1},set:function(){console.warn("THREE.WebGLRenderer: .toneMappingWhitePoint has been removed.")}}}),Object.defineProperties(us.prototype,{cullFace:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.")}},renderReverseSided:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.")}},renderSingleSided:{get:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.")},set:function(){console.warn("THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.")}}}),Object.defineProperties(Tt.prototype,{wrapS:{get:function(){return console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS."),this.texture.wrapS},set:function(t){console.warn("THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS."),this.texture.wrapS=t}},wrapT:{get:function(){return console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT."),this.texture.wrapT},set:function(t){console.warn("THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT."),this.texture.wrapT=t}},magFilter:{get:function(){return console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter."),this.texture.magFilter},set:function(t){console.warn("THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter."),this.texture.magFilter=t}},minFilter:{get:function(){return console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter."),this.texture.minFilter},set:function(t){console.warn("THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter."),this.texture.minFilter=t}},anisotropy:{get:function(){return console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy."),this.texture.anisotropy},set:function(t){console.warn("THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy."),this.texture.anisotropy=t}},offset:{get:function(){return console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset."),this.texture.offset},set:function(t){console.warn("THREE.WebGLRenderTarget: .offset is now .texture.offset."),this.texture.offset=t}},repeat:{get:function(){return console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat."),this.texture.repeat},set:function(t){console.warn("THREE.WebGLRenderTarget: .repeat is now .texture.repeat."),this.texture.repeat=t}},format:{get:function(){return console.warn("THREE.WebGLRenderTarget: .format is now .texture.format."),this.texture.format},set:function(t){console.warn("THREE.WebGLRenderTarget: .format is now .texture.format."),this.texture.format=t}},type:{get:function(){return console.warn("THREE.WebGLRenderTarget: .type is now .texture.type."),this.texture.type},set:function(t){console.warn("THREE.WebGLRenderTarget: .type is now .texture.type."),this.texture.type=t}},generateMipmaps:{get:function(){return console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps."),this.texture.generateMipmaps},set:function(t){console.warn("THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps."),this.texture.generateMipmaps=t}}}),Lc.prototype.load=function(t){console.warn("THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.");const e=this;return(new vc).load(t,(function(t){e.setBuffer(t)})),this},Ic.prototype.getData=function(){return console.warn("THREE.AudioAnalyser: .getData() is now .getFrequencyData()."),this.getFrequencyData()},ti.prototype.updateCubeMap=function(t,e){return console.warn("THREE.CubeCamera: .updateCubeMap() is now .update()."),this.update(t,e)},ti.prototype.clear=function(t,e,n,i){return console.warn("THREE.CubeCamera: .clear() is now .renderTarget.clear()."),this.renderTarget.clear(t,e,n,i)},_t.crossOrigin=void 0,_t.loadTexture=function(t,e,n,i){console.warn("THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.");const r=new pl;r.setCrossOrigin(this.crossOrigin);const s=r.load(t,n,void 0,i);return e&&(s.mapping=e),s},_t.loadTextureCube=function(t,e,n,i){console.warn("THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.");const r=new ul;r.setCrossOrigin(this.crossOrigin);const s=r.load(t,n,void 0,i);return e&&(s.mapping=e),s},_t.loadCompressedTexture=function(){console.error("THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.")},_t.loadCompressedTextureCube=function(){console.error("THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.")};const eu={createMultiMaterialObject:function(){console.error("THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js")},detach:function(){console.error("THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js")},attach:function(){console.error("THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js")}};"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:e}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=e),t.ACESFilmicToneMapping=4,t.AddEquation=n,t.AddOperation=2,t.AdditiveAnimationBlendMode=q,t.AdditiveBlending=2,t.AlphaFormat=1021,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=$l,t.AmbientLightProbe=xc,t.AnimationClip=nl,t.AnimationLoader=class extends ol{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new cl(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=[];for(let n=0;n.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Sh.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Sh,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=Lc,t.AudioAnalyser=Ic,t.AudioContext=gc,t.AudioListener=class extends Ce{constructor(){super(),this.type="AudioListener",this.context=gc.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new bc}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(Sc,Tc,Ec),Ac.set(0,0,-1).applyQuaternion(Tc),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(Sc.x,t),e.positionY.linearRampToValueAtTime(Sc.y,t),e.positionZ.linearRampToValueAtTime(Sc.z,t),e.forwardX.linearRampToValueAtTime(Ac.x,t),e.forwardY.linearRampToValueAtTime(Ac.y,t),e.forwardZ.linearRampToValueAtTime(Ac.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(Sc.x,Sc.y,Sc.z),e.setOrientation(Ac.x,Ac.y,Ac.z,n.x,n.y,n.z)}},t.AudioLoader=vc,t.AxesHelper=Ah,t.AxisHelper=function(t){return console.warn("THREE.AxisHelper has been renamed to THREE.AxesHelper."),new Ah(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 dl(t)},t.Bone=ta,t.BooleanKeyframeTrack=Zo,t.BoundingBoxHelper=function(t,e){return console.warn("THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead."),new Mh(t,e)},t.Box2=eh,t.Box3=Pt,t.Box3Helper=class extends ya{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 En;i.setIndex(new sn(n,1)),i.setAttribute("position",new mn([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 ca({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=qn,t.BoxGeometry=qn,t.BoxHelper=Mh,t.BufferAttribute=sn,t.BufferGeometry=En,t.BufferGeometryLoader=oc,t.ByteType=1010,t.Cache=rl,t.Camera=Qn,t.CameraHelper=class extends ya{constructor(t){const e=new En,n=new ca({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={},a=new tn(16755200),o=new tn(16711680),l=new tn(43775),c=new tn(16777215),h=new tn(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 mn(i,3)),e.setAttribute("color",new mn(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;_h.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),wh("c",e,t,_h,0,0,-1),wh("t",e,t,_h,0,0,1),wh("n1",e,t,_h,-1,-1,-1),wh("n2",e,t,_h,1,-1,-1),wh("n3",e,t,_h,-1,1,-1),wh("n4",e,t,_h,1,1,-1),wh("f1",e,t,_h,-1,-1,1),wh("f2",e,t,_h,1,-1,1),wh("f3",e,t,_h,-1,1,1),wh("f4",e,t,_h,1,1,1),wh("u1",e,t,_h,.7,1.1,-1),wh("u2",e,t,_h,-.7,1.1,-1),wh("u3",e,t,_h,0,2,-1),wh("cf1",e,t,_h,-1,0,1),wh("cf2",e,t,_h,1,0,1),wh("cf3",e,t,_h,0,-1,1),wh("cf4",e,t,_h,0,1,1),wh("cn1",e,t,_h,-1,0,-1),wh("cn2",e,t,_h,1,0,-1),wh("cn3",e,t,_h,0,-1,-1),wh("cn4",e,t,_h,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=Ra,t.CatmullRomCurve3=bl,t.CineonToneMapping=3,t.CircleBufferGeometry=Pa,t.CircleGeometry=Pa,t.ClampToEdgeWrapping=u,t.Clock=bc,t.Color=tn,t.ColorKeyframeTrack=Jo,t.CompressedTexture=La,t.CompressedTextureLoader=class extends ol{constructor(t){super(t)}load(t,e,n,i){const r=this,s=[],a=new La,o=new cl(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;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=al,t.DepthFormat=A,t.DepthStencilFormat=L,t.DepthTexture=Ca,t.DirectionalLight=Kl,t.DirectionalLightHelper=class extends Ce{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 En;i.setAttribute("position",new mn([-e,e,0,e,e,0,e,-e,0,-e,-e,0,-e,e,0],3));const r=new ca({fog:!1,toneMapped:!1});this.lightPlane=new fa(i,r),this.add(this.lightPlane),i=new En,i.setAttribute("position",new mn([0,0,0,0,0,1],3)),this.targetLine=new fa(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(){gh.setFromMatrixPosition(this.light.matrixWorld),vh.setFromMatrixPosition(this.light.target.matrixWorld),yh.subVectors(vh,gh),this.lightPlane.lookAt(vh),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(vh),this.targetLine.scale.z=yh.length()}},t.DiscreteInterpolant=Xo,t.DodecahedronBufferGeometry=Ba,t.DodecahedronGeometry=Ba,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 sn(t,e).setUsage(nt)},t.DynamicCopyUsage=35050,t.DynamicDrawUsage=nt,t.DynamicReadUsage=35049,t.EdgesGeometry=Ga,t.EdgesHelper=function(t,e){return console.warn("THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead."),new ya(new Ga(t.geometry),new ca({color:void 0!==e?e:16777215}))},t.EllipseCurve=fl,t.EqualDepth=4,t.EqualStencilFunc=514,t.EquirectangularReflectionMapping=a,t.EquirectangularRefractionMapping=o,t.Euler=fe,t.EventDispatcher=rt,t.ExtrudeBufferGeometry=go,t.ExtrudeGeometry=go,t.FaceColors=1,t.FileLoader=cl,t.FlatShading=1,t.Float16BufferAttribute=pn,t.Float32Attribute=function(t,e){return console.warn("THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead."),new mn(t,e)},t.Float32BufferAttribute=mn,t.Float64Attribute=function(t,e){return console.warn("THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead."),new fn(t,e)},t.Float64BufferAttribute=fn,t.FloatType=b,t.Fog=Ss,t.FogExp2=Ms,t.Font=pc,t.FontLoader=class extends ol{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new cl(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(t){let n;try{n=JSON.parse(t)}catch(e){console.warn("THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead."),n=JSON.parse(t.substring(65,t.length-2))}const i=r.parse(n);e&&e(i)}),n,i)}parse(t){return new pc(t)}},t.FrontSide=0,t.Frustum=ai,t.GLBufferAttribute=Qc,t.GLSL1="100",t.GLSL3=it,t.GammaEncoding=Z,t.GreaterDepth=6,t.GreaterEqualDepth=5,t.GreaterEqualStencilFunc=518,t.GreaterStencilFunc=516,t.GridHelper=fh,t.Group=gs,t.HalfFloatType=M,t.HemisphereLight=Ol,t.HemisphereLightHelper=class extends Ce{constructor(t,e,n){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=n;const i=new _o(e);i.rotateY(.5*Math.PI),this.material=new en({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 sn(s,3)),this.add(new Wn(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");ph.copy(this.light.color),mh.copy(this.light.groundColor);for(let t=0,n=e.count;t0){const n=new sl(e);r=new hl(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e\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})}(Ih),this._equirectShader=null,this._cubemapShader=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){kh=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=Kh(),this._compileMaterial(this._cubemapShader))}compileEquirectangularShader(){null===this._equirectShader&&(this._equirectShader=Qh(),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?Ch:0,Ch,Ch),o.setRenderTarget(i),u&&o.render(zh,r),o.render(t,r)}o.toneMapping=h,o.outputEncoding=c,o.autoClear=l}_textureToCubeUV(t,e){const n=this._renderer;t.isCubeTexture?null==this._cubemapShader&&(this._cubemapShader=Kh()):null==this._equirectShader&&(this._equirectShader=Qh());const i=t.isCubeTexture?this._cubemapShader:this._equirectShader,r=new Wn(Oh[0],i),s=i.uniforms;s.envMap.value=t,t.isCubeTexture||s.texelSize.value.set(1/t.image.width,1/t.image.height),s.inputEncoding.value=Nh[t.encoding],s.outputEncoding.value=Nh[e.texture.encoding],Jh(e,0,0,3*Ch,2*Ch),n.setRenderTarget(e),n.render(r,Fh)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;eIh&&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,Fh)}},t.ParametricBufferGeometry=wo,t.ParametricGeometry=wo,t.Particle=function(t){return console.warn("THREE.Particle has been renamed to THREE.Sprite."),new Vs(t)},t.ParticleBasicMaterial=function(t){return console.warn("THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial."),new _a(t)},t.ParticleSystem=function(t,e){return console.warn("THREE.ParticleSystem has been renamed to THREE.Points."),new Ta(t,e)},t.ParticleSystemMaterial=function(t){return console.warn("THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial."),new _a(t)},t.Path=Bl,t.PerspectiveCamera=Kn,t.Plane=Ne,t.PlaneBufferGeometry=ci,t.PlaneGeometry=ci,t.PlaneHelper=class extends fa{constructor(t,e=1,n=16776960){const i=n,r=new En;r.setAttribute("position",new mn([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,0,1,0,0,0],3)),r.computeBoundingSphere(),super(r,new ca({color:i,toneMapped:!1})),this.type="PlaneHelper",this.plane=t,this.size=e;const s=new En;s.setAttribute("position",new mn([1,1,1,-1,1,1,-1,-1,1,1,1,1,-1,-1,1,1,-1,1],3)),s.computeBoundingSphere(),this.add(new Wn(s,new en({color:i,opacity:.2,transparent:!0,depthWrite:!1,toneMapped:!1})))}updateMatrixWorld(t){let e=-this.plane.constant;Math.abs(e)<1e-8&&(e=1e-8),this.scale.set(.5*this.size,.5*this.size,e),this.children[0].material.side=e<0?1:0,this.lookAt(this.plane.normal),super.updateMatrixWorld(t)}},t.PointCloud=function(t,e){return console.warn("THREE.PointCloud has been renamed to THREE.Points."),new Ta(t,e)},t.PointCloudMaterial=function(t){return console.warn("THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial."),new _a(t)},t.PointLight=Zl,t.PointLightHelper=class extends Wn{constructor(t,e,n){super(new So(e,4,2),new en({wireframe:!0,fog:!1,toneMapped:!1})),this.light=t,this.light.updateMatrixWorld(),this.color=n,this.type="PointLightHelper",this.matrix=this.light.matrixWorld,this.matrixAutoUpdate=!1,this.update()}dispose(){this.geometry.dispose(),this.material.dispose()}update(){void 0!==this.color?this.material.color.set(this.color):this.material.color.copy(this.light.color)}},t.Points=Ta,t.PointsMaterial=_a,t.PolarGridHelper=class extends ya{constructor(t=10,e=16,n=8,i=64,r=4473924,s=8947848){r=new tn(r),s=new tn(s);const a=[],o=[];for(let n=0;n<=e;n++){const i=n/e*(2*Math.PI),l=Math.sin(i)*t,c=Math.cos(i)*t;a.push(0,0,0),a.push(l,0,c);const h=1&n?r:s;o.push(h.r,h.g,h.b),o.push(h.r,h.g,h.b)}for(let e=0;e<=n;e++){const l=1&e?r:s,c=t-t/n*e;for(let t=0;t> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + + const d0 = Math.random() * 0xffffffff | 0; + const d1 = Math.random() * 0xffffffff | 0; + const d2 = Math.random() * 0xffffffff | 0; + const d3 = Math.random() * 0xffffffff | 0; + const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; - // .toUpperCase() here flattens concatenated strings to save heap memory space. - return uuid.toUpperCase(); - - }, - - clamp: function ( value, min, max ) { - - return Math.max( min, Math.min( max, value ) ); + // .toUpperCase() here flattens concatenated strings to save heap memory space. + return uuid.toUpperCase(); - }, +} - // compute euclidian modulo of m % n - // https://en.wikipedia.org/wiki/Modulo_operation +function clamp( value, min, max ) { - euclideanModulo: function ( n, m ) { + return Math.max( min, Math.min( max, value ) ); - return ( ( n % m ) + m ) % m; +} - }, +// compute euclidian modulo of m % n +// https://en.wikipedia.org/wiki/Modulo_operation +function euclideanModulo( n, m ) { - // Linear mapping from range to range + return ( ( n % m ) + m ) % m; - mapLinear: function ( x, a1, a2, b1, b2 ) { +} - return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); +// Linear mapping from range to range +function mapLinear( x, a1, a2, b1, b2 ) { - }, + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); - // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ +} - inverseLerp: function ( x, y, value ) { +// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ +function inverseLerp( x, y, value ) { - if ( x !== y ) { + if ( x !== y ) { - return ( value - x ) / ( y - x ); + return ( value - x ) / ( y - x ); } else { - return 0; + return 0; } - }, - - // https://en.wikipedia.org/wiki/Linear_interpolation - - lerp: function ( x, y, t ) { - - return ( 1 - t ) * x + t * y; - - }, - - // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ - - damp: function ( x, y, lambda, dt ) { - - return MathUtils.lerp( x, y, 1 - Math.exp( - lambda * dt ) ); - - }, - - // https://www.desmos.com/calculator/vcsjnyz7x4 +} - pingpong: function ( x, length = 1 ) { +// https://en.wikipedia.org/wiki/Linear_interpolation +function lerp( x, y, t ) { - return length - Math.abs( MathUtils.euclideanModulo( x, length * 2 ) - length ); + return ( 1 - t ) * x + t * y; - }, +} - // http://en.wikipedia.org/wiki/Smoothstep +// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ +function damp( x, y, lambda, dt ) { - smoothstep: function ( x, min, max ) { + return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); - if ( x <= min ) return 0; - if ( x >= max ) return 1; +} - x = ( x - min ) / ( max - min ); +// https://www.desmos.com/calculator/vcsjnyz7x4 +function pingpong( x, length = 1 ) { - return x * x * ( 3 - 2 * x ); + return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); - }, +} - smootherstep: function ( x, min, max ) { +// http://en.wikipedia.org/wiki/Smoothstep +function smoothstep( x, min, max ) { - if ( x <= min ) return 0; - if ( x >= max ) return 1; + if ( x <= min ) return 0; + if ( x >= max ) return 1; - x = ( x - min ) / ( max - min ); + x = ( x - min ) / ( max - min ); - return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); + return x * x * ( 3 - 2 * x ); - }, +} - // Random integer from interval +function smootherstep( x, min, max ) { - randInt: function ( low, high ) { + if ( x <= min ) return 0; + if ( x >= max ) return 1; - return low + Math.floor( Math.random() * ( high - low + 1 ) ); + x = ( x - min ) / ( max - min ); - }, + return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); - // Random float from interval +} - randFloat: function ( low, high ) { +// Random integer from interval +function randInt( low, high ) { - return low + Math.random() * ( high - low ); + return low + Math.floor( Math.random() * ( high - low + 1 ) ); - }, +} - // Random float from <-range/2, range/2> interval +// Random float from interval +function randFloat( low, high ) { - randFloatSpread: function ( range ) { + return low + Math.random() * ( high - low ); - return range * ( 0.5 - Math.random() ); +} - }, +// Random float from <-range/2, range/2> interval +function randFloatSpread( range ) { - // Deterministic pseudo-random float in the interval [ 0, 1 ] + return range * ( 0.5 - Math.random() ); - seededRandom: function ( s ) { +} - if ( s !== undefined ) _seed = s % 2147483647; +// Deterministic pseudo-random float in the interval [ 0, 1 ] +function seededRandom( s ) { - // Park-Miller algorithm + if ( s !== undefined ) _seed = s % 2147483647; - _seed = _seed * 16807 % 2147483647; + // Park-Miller algorithm - return ( _seed - 1 ) / 2147483646; + _seed = _seed * 16807 % 2147483647; - }, + return ( _seed - 1 ) / 2147483646; - degToRad: function ( degrees ) { +} - return degrees * MathUtils.DEG2RAD; +function degToRad( degrees ) { - }, + return degrees * DEG2RAD; - radToDeg: function ( radians ) { +} - return radians * MathUtils.RAD2DEG; +function radToDeg( radians ) { - }, + return radians * RAD2DEG; - isPowerOfTwo: function ( value ) { +} - return ( value & ( value - 1 ) ) === 0 && value !== 0; +function isPowerOfTwo( value ) { - }, + return ( value & ( value - 1 ) ) === 0 && value !== 0; - ceilPowerOfTwo: function ( value ) { +} - return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); +function ceilPowerOfTwo( value ) { - }, + return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); - floorPowerOfTwo: function ( value ) { +} - return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); +function floorPowerOfTwo( value ) { - }, + return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); - setQuaternionFromProperEuler: function ( q, a, b, c, order ) { +} - // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles +function setQuaternionFromProperEuler( q, a, b, c, order ) { - // rotations are applied to the axes in the order specified by 'order' - // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' - // angles are in radians + // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles - const cos = Math.cos; - const sin = Math.sin; + // rotations are applied to the axes in the order specified by 'order' + // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' + // angles are in radians - const c2 = cos( b / 2 ); - const s2 = sin( b / 2 ); + const cos = Math.cos; + const sin = Math.sin; - const c13 = cos( ( a + c ) / 2 ); - const s13 = sin( ( a + c ) / 2 ); + const c2 = cos( b / 2 ); + const s2 = sin( b / 2 ); - const c1_3 = cos( ( a - c ) / 2 ); - const s1_3 = sin( ( a - c ) / 2 ); + const c13 = cos( ( a + c ) / 2 ); + const s13 = sin( ( a + c ) / 2 ); - const c3_1 = cos( ( c - a ) / 2 ); - const s3_1 = sin( ( c - a ) / 2 ); + const c1_3 = cos( ( a - c ) / 2 ); + const s1_3 = sin( ( a - c ) / 2 ); - switch ( order ) { + const c3_1 = cos( ( c - a ) / 2 ); + const s3_1 = sin( ( c - a ) / 2 ); - case 'XYX': - q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); - break; + switch ( order ) { - case 'YZY': - q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); - break; + case 'XYX': + q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); + break; - case 'ZXZ': - q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); - break; + case 'YZY': + q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); + break; - case 'XZX': - q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); - break; + case 'ZXZ': + q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); + break; - case 'YXY': - q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); - break; + case 'XZX': + q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); + break; - case 'ZYZ': - q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); - break; + case 'YXY': + q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); + break; - default: - console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); + case 'ZYZ': + q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); + break; - } + default: + console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); } -}; +} + +var MathUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler +}); class Vector2 { @@ -1353,9 +1362,9 @@ Matrix3.prototype.isMatrix3 = true; let _canvas; -const ImageUtils = { +class ImageUtils { - getDataURL: function ( image ) { + static getDataURL( image ) { if ( /^data:/i.test( image.src ) ) { @@ -1412,7 +1421,7 @@ const ImageUtils = { } -}; +} let textureId = 0; @@ -1424,7 +1433,7 @@ class Texture extends EventDispatcher { Object.defineProperty( this, 'id', { value: textureId ++ } ); - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.name = ''; @@ -1573,7 +1582,7 @@ class Texture extends EventDispatcher { if ( image.uuid === undefined ) { - image.uuid = MathUtils.generateUUID(); // UGH + image.uuid = generateUUID(); // UGH } @@ -2953,7 +2962,7 @@ class Quaternion { angleTo( q ) { - return 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) ); + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); } @@ -3773,7 +3782,7 @@ class Vector3 { // clamp, to handle numerical problems - return Math.acos( MathUtils.clamp( theta, - 1, 1 ) ); + return Math.acos( clamp( theta, - 1, 1 ) ); } @@ -6196,8 +6205,6 @@ class Euler { setFromRotationMatrix( m, order, update ) { - const clamp = MathUtils.clamp; - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) const te = m.elements; @@ -6470,119 +6477,114 @@ class Layers { let _object3DId = 0; -const _v1$4 = new Vector3(); -const _q1 = new Quaternion(); -const _m1$1 = new Matrix4(); -const _target = new Vector3(); +const _v1$4 = new /*@__PURE__*/ Vector3(); +const _q1 = new /*@__PURE__*/ Quaternion(); +const _m1$1 = new /*@__PURE__*/ Matrix4(); +const _target = new /*@__PURE__*/ Vector3(); -const _position$3 = new Vector3(); -const _scale$2 = new Vector3(); -const _quaternion$2 = new Quaternion(); +const _position$3 = new /*@__PURE__*/ Vector3(); +const _scale$2 = new /*@__PURE__*/ Vector3(); +const _quaternion$2 = new /*@__PURE__*/ Quaternion(); -const _xAxis = new Vector3( 1, 0, 0 ); -const _yAxis = new Vector3( 0, 1, 0 ); -const _zAxis = new Vector3( 0, 0, 1 ); +const _xAxis = new /*@__PURE__*/ Vector3( 1, 0, 0 ); +const _yAxis = new /*@__PURE__*/ Vector3( 0, 1, 0 ); +const _zAxis = new /*@__PURE__*/ Vector3( 0, 0, 1 ); const _addedEvent = { type: 'added' }; const _removedEvent = { type: 'removed' }; -function Object3D() { +class Object3D extends EventDispatcher { - Object.defineProperty( this, 'id', { value: _object3DId ++ } ); + constructor() { - this.uuid = MathUtils.generateUUID(); + super(); - this.name = ''; - this.type = 'Object3D'; + Object.defineProperty( this, 'id', { value: _object3DId ++ } ); - this.parent = null; - this.children = []; + this.uuid = generateUUID(); - this.up = Object3D.DefaultUp.clone(); + this.name = ''; + this.type = 'Object3D'; - const position = new Vector3(); - const rotation = new Euler(); - const quaternion = new Quaternion(); - const scale = new Vector3( 1, 1, 1 ); + this.parent = null; + this.children = []; - function onRotationChange() { + this.up = Object3D.DefaultUp.clone(); - quaternion.setFromEuler( rotation, false ); + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3( 1, 1, 1 ); - } + function onRotationChange() { - function onQuaternionChange() { + quaternion.setFromEuler( rotation, false ); - rotation.setFromQuaternion( quaternion, undefined, false ); + } - } + function onQuaternionChange() { - rotation._onChange( onRotationChange ); - quaternion._onChange( onQuaternionChange ); + rotation.setFromQuaternion( quaternion, undefined, false ); - Object.defineProperties( this, { - position: { - configurable: true, - enumerable: true, - value: position - }, - rotation: { - configurable: true, - enumerable: true, - value: rotation - }, - 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; + rotation._onChange( onRotationChange ); + quaternion._onChange( onQuaternionChange ); - this.layers = new Layers(); - this.visible = true; - - this.castShadow = false; - this.receiveShadow = false; + Object.defineProperties( this, { + position: { + configurable: true, + enumerable: true, + value: position + }, + rotation: { + configurable: true, + enumerable: true, + value: rotation + }, + quaternion: { + configurable: true, + enumerable: true, + value: quaternion + }, + scale: { + configurable: true, + enumerable: true, + value: scale + }, + modelViewMatrix: { + value: new Matrix4() + }, + normalMatrix: { + value: new Matrix3() + } + } ); - this.frustumCulled = true; - this.renderOrder = 0; + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); - this.animations = []; + this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; + this.matrixWorldNeedsUpdate = false; - this.userData = {}; + this.layers = new Layers(); + this.visible = true; -} + this.castShadow = false; + this.receiveShadow = false; -Object3D.DefaultUp = new Vector3( 0, 1, 0 ); -Object3D.DefaultMatrixAutoUpdate = true; + this.frustumCulled = true; + this.renderOrder = 0; -Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + this.animations = []; - constructor: Object3D, + this.userData = {}; - isObject3D: true, + } - onBeforeRender: function () {}, - onAfterRender: function () {}, + onBeforeRender() {} + onAfterRender() {} - applyMatrix4: function ( matrix ) { + applyMatrix4( matrix ) { if ( this.matrixAutoUpdate ) this.updateMatrix(); @@ -6590,47 +6592,47 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), this.matrix.decompose( this.position, this.quaternion, this.scale ); - }, + } - applyQuaternion: function ( q ) { + applyQuaternion( q ) { this.quaternion.premultiply( q ); return this; - }, + } - setRotationFromAxisAngle: function ( axis, angle ) { + setRotationFromAxisAngle( axis, angle ) { // assumes axis is normalized this.quaternion.setFromAxisAngle( axis, angle ); - }, + } - setRotationFromEuler: function ( euler ) { + setRotationFromEuler( euler ) { this.quaternion.setFromEuler( euler, true ); - }, + } - setRotationFromMatrix: function ( m ) { + setRotationFromMatrix( m ) { // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) this.quaternion.setFromRotationMatrix( m ); - }, + } - setRotationFromQuaternion: function ( q ) { + setRotationFromQuaternion( q ) { // assumes q is normalized this.quaternion.copy( q ); - }, + } - rotateOnAxis: function ( axis, angle ) { + rotateOnAxis( axis, angle ) { // rotate object on axis in object space // axis is assumed to be normalized @@ -6641,9 +6643,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - rotateOnWorldAxis: function ( axis, angle ) { + rotateOnWorldAxis( axis, angle ) { // rotate object on axis in world space // axis is assumed to be normalized @@ -6655,27 +6657,27 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - rotateX: function ( angle ) { + rotateX( angle ) { return this.rotateOnAxis( _xAxis, angle ); - }, + } - rotateY: function ( angle ) { + rotateY( angle ) { return this.rotateOnAxis( _yAxis, angle ); - }, + } - rotateZ: function ( angle ) { + rotateZ( angle ) { return this.rotateOnAxis( _zAxis, angle ); - }, + } - translateOnAxis: function ( axis, distance ) { + translateOnAxis( axis, distance ) { // translate object by distance along axis in object space // axis is assumed to be normalized @@ -6686,39 +6688,39 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - translateX: function ( distance ) { + translateX( distance ) { return this.translateOnAxis( _xAxis, distance ); - }, + } - translateY: function ( distance ) { + translateY( distance ) { return this.translateOnAxis( _yAxis, distance ); - }, + } - translateZ: function ( distance ) { + translateZ( distance ) { return this.translateOnAxis( _zAxis, distance ); - }, + } - localToWorld: function ( vector ) { + localToWorld( vector ) { return vector.applyMatrix4( this.matrixWorld ); - }, + } - worldToLocal: function ( vector ) { + worldToLocal( vector ) { return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() ); - }, + } - lookAt: function ( x, y, z ) { + lookAt( x, y, z ) { // This method does not support objects having non-uniformly-scaled parent(s) @@ -6758,9 +6760,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - add: function ( object ) { + add( object ) { if ( arguments.length > 1 ) { @@ -6802,9 +6804,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - remove: function ( object ) { + remove( object ) { if ( arguments.length > 1 ) { @@ -6831,9 +6833,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - clear: function () { + clear() { for ( let i = 0; i < this.children.length; i ++ ) { @@ -6850,9 +6852,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - attach: function ( object ) { + attach( object ) { // adds object as a child of this, while maintaining the object's world transform @@ -6876,21 +6878,21 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return this; - }, + } - getObjectById: function ( id ) { + getObjectById( id ) { return this.getObjectByProperty( 'id', id ); - }, + } - getObjectByName: function ( name ) { + getObjectByName( name ) { return this.getObjectByProperty( 'name', name ); - }, + } - getObjectByProperty: function ( name, value ) { + getObjectByProperty( name, value ) { if ( this[ name ] === value ) return this; @@ -6909,9 +6911,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return undefined; - }, + } - getWorldPosition: function ( target ) { + getWorldPosition( target ) { if ( target === undefined ) { @@ -6924,9 +6926,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return target.setFromMatrixPosition( this.matrixWorld ); - }, + } - getWorldQuaternion: function ( target ) { + getWorldQuaternion( target ) { if ( target === undefined ) { @@ -6941,9 +6943,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return target; - }, + } - getWorldScale: function ( target ) { + getWorldScale( target ) { if ( target === undefined ) { @@ -6958,9 +6960,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return target; - }, + } - getWorldDirection: function ( target ) { + getWorldDirection( target ) { if ( target === undefined ) { @@ -6975,11 +6977,11 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); - }, + } - raycast: function () {}, + raycast() {} - traverse: function ( callback ) { + traverse( callback ) { callback( this ); @@ -6991,9 +6993,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - traverseVisible: function ( callback ) { + traverseVisible( callback ) { if ( this.visible === false ) return; @@ -7007,9 +7009,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - traverseAncestors: function ( callback ) { + traverseAncestors( callback ) { const parent = this.parent; @@ -7021,17 +7023,17 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - updateMatrix: function () { + updateMatrix() { this.matrix.compose( this.position, this.quaternion, this.scale ); this.matrixWorldNeedsUpdate = true; - }, + } - updateMatrixWorld: function ( force ) { + updateMatrixWorld( force ) { if ( this.matrixAutoUpdate ) this.updateMatrix(); @@ -7063,9 +7065,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - updateWorldMatrix: function ( updateParents, updateChildren ) { + updateWorldMatrix( updateParents, updateChildren ) { const parent = this.parent; @@ -7101,9 +7103,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - toJSON: function ( meta ) { + toJSON( meta ) { // meta is a string when called from JSON.stringify const isRootObject = ( meta === undefined || typeof meta === 'string' ); @@ -7318,15 +7320,15 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - }, + } - clone: function ( recursive ) { + clone( recursive ) { return new this.constructor().copy( this, recursive ); - }, + } - copy: function ( source, recursive = true ) { + copy( source, recursive = true ) { this.name = source.name; @@ -7369,7 +7371,12 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } -} ); +} + +Object3D.DefaultUp = new Vector3( 0, 1, 0 ); +Object3D.DefaultMatrixAutoUpdate = true; + +Object3D.prototype.isObject3D = true; const _vector1 = /*@__PURE__*/ new Vector3(); const _vector2$1 = /*@__PURE__*/ new Vector3(); @@ -7920,7 +7927,7 @@ function Material() { Object.defineProperty( this, 'id', { value: materialId ++ } ); - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.name = ''; this.type = 'Material'; @@ -7990,6 +7997,8 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), isMaterial: true, + onBuild: function ( /* shaderobject, renderer */ ) {}, + onBeforeCompile: function ( /* shaderobject, renderer */ ) {}, customProgramCacheKey: function () { @@ -8159,14 +8168,15 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), if ( this.envMap && this.envMap.isTexture ) { data.envMap = this.envMap.toJSON( meta ).uuid; - data.reflectivity = this.reflectivity; // Scale behind envMap - data.refractionRatio = this.refractionRatio; if ( this.combine !== undefined ) data.combine = this.combine; - if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; } + 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; @@ -8489,9 +8499,9 @@ class Color { setHSL( h, s, l ) { // h,s,l ranges are in 0.0 - 1.0 - h = MathUtils.euclideanModulo( h, 1 ); - s = MathUtils.clamp( s, 0, 1 ); - l = MathUtils.clamp( l, 0, 1 ); + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); if ( s === 0 ) { @@ -8632,7 +8642,7 @@ class Color { setColorName( style ) { // color keywords - const hex = _colorKeywords[ style ]; + const hex = _colorKeywords[ style.toLowerCase() ]; if ( hex !== undefined ) { @@ -8905,9 +8915,9 @@ class Color { this.getHSL( _hslA ); color.getHSL( _hslB ); - const h = MathUtils.lerp( _hslA.h, _hslB.h, alpha ); - const s = MathUtils.lerp( _hslA.s, _hslB.s, alpha ); - const l = MathUtils.lerp( _hslA.l, _hslB.l, alpha ); + 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 ); @@ -9086,56 +9096,50 @@ class MeshBasicMaterial extends Material { MeshBasicMaterial.prototype.isMeshBasicMaterial = true; -const _vector$9 = new Vector3(); -const _vector2 = new Vector2(); +const _vector$9 = new /*@__PURE__*/ Vector3(); +const _vector2 = new /*@__PURE__*/ Vector2(); -function BufferAttribute( array, itemSize, normalized ) { +class BufferAttribute { - if ( Array.isArray( array ) ) { + constructor( array, itemSize, normalized ) { - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + if ( Array.isArray( array ) ) { - } - - this.name = ''; + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - this.array = array; - this.itemSize = itemSize; - this.count = array !== undefined ? array.length / itemSize : 0; - this.normalized = normalized === true; - - this.usage = StaticDrawUsage; - this.updateRange = { offset: 0, count: - 1 }; + } - this.version = 0; + this.name = ''; -} + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized === true; -Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { + this.usage = StaticDrawUsage; + this.updateRange = { offset: 0, count: - 1 }; - set: function ( value ) { + this.version = 0; - if ( value === true ) this.version ++; + this.onUploadCallback = function () {}; } -} ); - -Object.assign( BufferAttribute.prototype, { + set needsUpdate( value ) { - isBufferAttribute: true, + if ( value === true ) this.version ++; - onUploadCallback: function () {}, + } - setUsage: function ( value ) { + setUsage( value ) { this.usage = value; return this; - }, + } - copy: function ( source ) { + copy( source ) { this.name = source.name; this.array = new source.array.constructor( source.array ); @@ -9147,9 +9151,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - copyAt: function ( index1, attribute, index2 ) { + copyAt( index1, attribute, index2 ) { index1 *= this.itemSize; index2 *= attribute.itemSize; @@ -9162,17 +9166,17 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - copyArray: function ( array ) { + copyArray( array ) { this.array.set( array ); return this; - }, + } - copyColorsArray: function ( colors ) { + copyColorsArray( colors ) { const array = this.array; let offset = 0; @@ -9196,9 +9200,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - copyVector2sArray: function ( vectors ) { + copyVector2sArray( vectors ) { const array = this.array; let offset = 0; @@ -9221,9 +9225,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - copyVector3sArray: function ( vectors ) { + copyVector3sArray( vectors ) { const array = this.array; let offset = 0; @@ -9247,9 +9251,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - copyVector4sArray: function ( vectors ) { + copyVector4sArray( vectors ) { const array = this.array; let offset = 0; @@ -9274,9 +9278,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - applyMatrix3: function ( m ) { + applyMatrix3( m ) { if ( this.itemSize === 2 ) { @@ -9304,9 +9308,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - applyMatrix4: function ( m ) { + applyMatrix4( m ) { for ( let i = 0, l = this.count; i < l; i ++ ) { @@ -9322,9 +9326,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - applyNormalMatrix: function ( m ) { + applyNormalMatrix( m ) { for ( let i = 0, l = this.count; i < l; i ++ ) { @@ -9340,9 +9344,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - transformDirection: function ( m ) { + transformDirection( m ) { for ( let i = 0, l = this.count; i < l; i ++ ) { @@ -9358,73 +9362,73 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - set: function ( value, offset = 0 ) { + set( value, offset = 0 ) { this.array.set( value, offset ); return this; - }, + } - getX: function ( index ) { + getX( index ) { return this.array[ index * this.itemSize ]; - }, + } - setX: function ( index, x ) { + setX( index, x ) { this.array[ index * this.itemSize ] = x; return this; - }, + } - getY: function ( index ) { + getY( index ) { return this.array[ index * this.itemSize + 1 ]; - }, + } - setY: function ( index, y ) { + setY( index, y ) { this.array[ index * this.itemSize + 1 ] = y; return this; - }, + } - getZ: function ( index ) { + getZ( index ) { return this.array[ index * this.itemSize + 2 ]; - }, + } - setZ: function ( index, z ) { + setZ( index, z ) { this.array[ index * this.itemSize + 2 ] = z; return this; - }, + } - getW: function ( index ) { + getW( index ) { return this.array[ index * this.itemSize + 3 ]; - }, + } - setW: function ( index, w ) { + setW( index, w ) { this.array[ index * this.itemSize + 3 ] = w; return this; - }, + } - setXY: function ( index, x, y ) { + setXY( index, x, y ) { index *= this.itemSize; @@ -9433,9 +9437,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - setXYZ: function ( index, x, y, z ) { + setXYZ( index, x, y, z ) { index *= this.itemSize; @@ -9445,9 +9449,9 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - setXYZW: function ( index, x, y, z, w ) { + setXYZW( index, x, y, z, w ) { index *= this.itemSize; @@ -9458,23 +9462,23 @@ Object.assign( BufferAttribute.prototype, { return this; - }, + } - onUpload: function ( callback ) { + onUpload( callback ) { this.onUploadCallback = callback; return this; - }, + } - clone: function () { + clone() { return new this.constructor( this.array, this.itemSize ).copy( this ); - }, + } - toJSON: function () { + toJSON() { const data = { itemSize: this.itemSize, @@ -9491,108 +9495,114 @@ Object.assign( BufferAttribute.prototype, { } -} ); +} + +BufferAttribute.prototype.isBufferAttribute = true; // -function Int8BufferAttribute( array, itemSize, normalized ) { +class Int8BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { - BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized ); + super( new Int8Array( array ), itemSize, normalized ); + + } } -Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; +class Uint8BufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Uint8BufferAttribute( array, itemSize, normalized ) { + super( new Uint8Array( array ), itemSize, normalized ); - BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized ); + } } -Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; +class Uint8ClampedBufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Uint8ClampedBufferAttribute( array, itemSize, normalized ) { + super( new Uint8ClampedArray( array ), itemSize, normalized ); - BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized ); + } } -Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; +class Int16BufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Int16BufferAttribute( array, itemSize, normalized ) { + super( new Int16Array( array ), itemSize, normalized ); - BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized ); + } } -Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; +class Uint16BufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Uint16BufferAttribute( array, itemSize, normalized ) { + super( new Uint16Array( array ), itemSize, normalized ); - BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); + } } -Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; +class Int32BufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Int32BufferAttribute( array, itemSize, normalized ) { + super( new Int32Array( array ), itemSize, normalized ); - BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized ); + } } -Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; +class Uint32BufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Uint32BufferAttribute( array, itemSize, normalized ) { + super( new Uint32Array( array ), itemSize, normalized ); - BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized ); + } } -Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; +class Float16BufferAttribute extends BufferAttribute { -function Float16BufferAttribute( array, itemSize, normalized ) { + constructor( array, itemSize, normalized ) { - BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); + super( new Uint16Array( array ), itemSize, normalized ); + + } } -Float16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float16BufferAttribute.prototype.constructor = Float16BufferAttribute; Float16BufferAttribute.prototype.isFloat16BufferAttribute = true; -function Float32BufferAttribute( array, itemSize, normalized ) { +class Float32BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { - BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized ); + super( new Float32Array( array ), itemSize, normalized ); + + } } -Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; +class Float64BufferAttribute extends BufferAttribute { + constructor( array, itemSize, normalized ) { -function Float64BufferAttribute( array, itemSize, normalized ) { + super( new Float64Array( array ), itemSize, normalized ); - BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized ); + } } -Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); -Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; - function arrayMax( array ) { if ( array.length === 0 ) return - Infinity; @@ -9629,52 +9639,50 @@ function getTypedArray( type, buffer ) { let _id = 0; -const _m1 = new Matrix4(); -const _obj = new Object3D(); -const _offset = new Vector3(); -const _box$1 = new Box3(); -const _boxMorphTargets = new Box3(); -const _vector$8 = new Vector3(); +const _m1 = new /*@__PURE__*/ Matrix4(); +const _obj = new /*@__PURE__*/ Object3D(); +const _offset = new /*@__PURE__*/ Vector3(); +const _box$1 = new /*@__PURE__*/ Box3(); +const _boxMorphTargets = new /*@__PURE__*/ Box3(); +const _vector$8 = new /*@__PURE__*/ Vector3(); -function BufferGeometry() { +class BufferGeometry extends EventDispatcher { - Object.defineProperty( this, 'id', { value: _id ++ } ); - - this.uuid = MathUtils.generateUUID(); + constructor() { - this.name = ''; - this.type = 'BufferGeometry'; + super(); - this.index = null; - this.attributes = {}; + Object.defineProperty( this, 'id', { value: _id ++ } ); - this.morphAttributes = {}; - this.morphTargetsRelative = false; + this.uuid = generateUUID(); - this.groups = []; + this.name = ''; + this.type = 'BufferGeometry'; - this.boundingBox = null; - this.boundingSphere = null; + this.index = null; + this.attributes = {}; - this.drawRange = { start: 0, count: Infinity }; + this.morphAttributes = {}; + this.morphTargetsRelative = false; - this.userData = {}; + this.groups = []; -} + this.boundingBox = null; + this.boundingSphere = null; -BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { + this.drawRange = { start: 0, count: Infinity }; - constructor: BufferGeometry, + this.userData = {}; - isBufferGeometry: true, + } - getIndex: function () { + getIndex() { return this.index; - }, + } - setIndex: function ( index ) { + setIndex( index ) { if ( Array.isArray( index ) ) { @@ -9688,37 +9696,37 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - getAttribute: function ( name ) { + getAttribute( name ) { return this.attributes[ name ]; - }, + } - setAttribute: function ( name, attribute ) { + setAttribute( name, attribute ) { this.attributes[ name ] = attribute; return this; - }, + } - deleteAttribute: function ( name ) { + deleteAttribute( name ) { delete this.attributes[ name ]; return this; - }, + } - hasAttribute: function ( name ) { + hasAttribute( name ) { return this.attributes[ name ] !== undefined; - }, + } - addGroup: function ( start, count, materialIndex = 0 ) { + addGroup( start, count, materialIndex = 0 ) { this.groups.push( { @@ -9728,22 +9736,22 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy } ); - }, + } - clearGroups: function () { + clearGroups() { this.groups = []; - }, + } - setDrawRange: function ( start, count ) { + setDrawRange( start, count ) { this.drawRange.start = start; this.drawRange.count = count; - }, + } - applyMatrix4: function ( matrix ) { + applyMatrix4( matrix ) { const position = this.attributes.position; @@ -9791,9 +9799,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - rotateX: function ( angle ) { + rotateX( angle ) { // rotate geometry around world x-axis @@ -9803,9 +9811,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - rotateY: function ( angle ) { + rotateY( angle ) { // rotate geometry around world y-axis @@ -9815,9 +9823,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - rotateZ: function ( angle ) { + rotateZ( angle ) { // rotate geometry around world z-axis @@ -9827,9 +9835,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - translate: function ( x, y, z ) { + translate( x, y, z ) { // translate geometry @@ -9839,9 +9847,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - scale: function ( x, y, z ) { + scale( x, y, z ) { // scale geometry @@ -9851,9 +9859,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - lookAt: function ( vector ) { + lookAt( vector ) { _obj.lookAt( vector ); @@ -9863,9 +9871,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - center: function () { + center() { this.computeBoundingBox(); @@ -9875,9 +9883,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - setFromPoints: function ( points ) { + setFromPoints( points ) { const position = []; @@ -9892,9 +9900,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - computeBoundingBox: function () { + computeBoundingBox() { if ( this.boundingBox === null ) { @@ -9962,9 +9970,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy } - }, + } - computeBoundingSphere: function () { + computeBoundingSphere() { if ( this.boundingSphere === null ) { @@ -10074,15 +10082,15 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy } - }, + } - computeFaceNormals: function () { + computeFaceNormals() { // backwards compatibility - }, + } - computeTangents: function () { + computeTangents() { const index = this.index; const attributes = this.attributes; @@ -10245,9 +10253,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy } - }, + } - computeVertexNormals: function () { + computeVertexNormals() { const index = this.index; const positionAttribute = this.getAttribute( 'position' ); @@ -10337,9 +10345,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy } - }, + } - merge: function ( geometry, offset ) { + merge( geometry, offset ) { if ( ! ( geometry && geometry.isBufferGeometry ) ) { @@ -10384,9 +10392,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - normalizeNormals: function () { + normalizeNormals() { const normals = this.attributes.normal; @@ -10400,9 +10408,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy } - }, + } - toNonIndexed: function () { + toNonIndexed() { function convertBufferAttribute( attribute, indices ) { @@ -10494,9 +10502,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return geometry2; - }, + } - toJSON: function () { + toJSON() { const data = { metadata: { @@ -10607,9 +10615,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return data; - }, + } - clone: function () { + clone() { /* // Handle primitives @@ -10637,9 +10645,9 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return new BufferGeometry().copy( this ); - }, + } - copy: function ( source ) { + copy( source ) { // reset @@ -10742,61 +10750,59 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy return this; - }, + } - dispose: function () { + dispose() { this.dispatchEvent( { type: 'dispose' } ); } -} ); - -const _inverseMatrix$2 = new Matrix4(); -const _ray$2 = new Ray(); -const _sphere$3 = new Sphere(); +} -const _vA$1 = new Vector3(); -const _vB$1 = new Vector3(); -const _vC$1 = new Vector3(); +BufferGeometry.prototype.isBufferGeometry = true; -const _tempA = new Vector3(); -const _tempB = new Vector3(); -const _tempC = new Vector3(); +const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _ray$2 = /*@__PURE__*/ new Ray(); +const _sphere$3 = /*@__PURE__*/ new Sphere(); -const _morphA = new Vector3(); -const _morphB = new Vector3(); -const _morphC = new Vector3(); +const _vA$1 = /*@__PURE__*/ new Vector3(); +const _vB$1 = /*@__PURE__*/ new Vector3(); +const _vC$1 = /*@__PURE__*/ new Vector3(); -const _uvA$1 = new Vector2(); -const _uvB$1 = new Vector2(); -const _uvC$1 = new Vector2(); +const _tempA = /*@__PURE__*/ new Vector3(); +const _tempB = /*@__PURE__*/ new Vector3(); +const _tempC = /*@__PURE__*/ new Vector3(); -const _intersectionPoint = new Vector3(); -const _intersectionPointWorld = new Vector3(); +const _morphA = /*@__PURE__*/ new Vector3(); +const _morphB = /*@__PURE__*/ new Vector3(); +const _morphC = /*@__PURE__*/ new Vector3(); -function Mesh( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { +const _uvA$1 = /*@__PURE__*/ new Vector2(); +const _uvB$1 = /*@__PURE__*/ new Vector2(); +const _uvC$1 = /*@__PURE__*/ new Vector2(); - Object3D.call( this ); +const _intersectionPoint = /*@__PURE__*/ new Vector3(); +const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); - this.type = 'Mesh'; +class Mesh extends Object3D { - this.geometry = geometry; - this.material = material; + constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { - this.updateMorphTargets(); + super(); -} + this.type = 'Mesh'; -Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.geometry = geometry; + this.material = material; - constructor: Mesh, + this.updateMorphTargets(); - isMesh: true, + } - copy: function ( source ) { + copy( source ) { - Object3D.prototype.copy.call( this, source ); + super.copy( source ); if ( source.morphTargetInfluences !== undefined ) { @@ -10815,9 +10821,9 @@ Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { return this; - }, + } - updateMorphTargets: function () { + updateMorphTargets() { const geometry = this.geometry; @@ -10860,9 +10866,9 @@ Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { } - }, + } - raycast: function ( raycaster, intersects ) { + raycast( raycaster, intersects ) { const geometry = this.geometry; const material = this.material; @@ -11031,7 +11037,9 @@ Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { } -} ); +} + +Mesh.prototype.isMesh = true; function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { @@ -11408,214 +11416,211 @@ var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 * } */ -function ShaderMaterial( parameters ) { +class ShaderMaterial extends Material { - Material.call( this ); + constructor( parameters ) { - this.type = 'ShaderMaterial'; + super(); - this.defines = {}; - this.uniforms = {}; + this.type = 'ShaderMaterial'; - this.vertexShader = default_vertex; - this.fragmentShader = default_fragment; + this.defines = {}; + this.uniforms = {}; - this.linewidth = 1; + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; - this.wireframe = false; - this.wireframeLinewidth = 1; + this.linewidth = 1; - this.fog = false; // set to use scene fog - this.lights = false; // set to use scene lights - this.clipping = false; // set to use user-defined clipping planes + this.wireframe = false; + this.wireframeLinewidth = 1; - this.skinning = false; // set to use skinning attribute streams - this.morphTargets = false; // set to use morph targets - this.morphNormals = false; // set to use morph normals + this.fog = false; // set to use scene fog + this.lights = false; // set to use scene lights + this.clipping = false; // set to use user-defined clipping planes - this.extensions = { - derivatives: false, // set to use derivatives - fragDepth: false, // set to use fragment depth values - drawBuffers: false, // set to use draw buffers - shaderTextureLOD: false // set to use shader texture LOD - }; + this.skinning = false; // set to use skinning attribute streams + this.morphTargets = false; // set to use morph targets + this.morphNormals = false; // set to use morph normals - // When rendered geometry doesn't include these attributes but the material does, - // use these default values in WebGL. This avoids errors when buffer data is missing. - this.defaultAttributeValues = { - 'color': [ 1, 1, 1 ], - 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] - }; + this.extensions = { + derivatives: false, // set to use derivatives + fragDepth: false, // set to use fragment depth values + drawBuffers: false, // set to use draw buffers + shaderTextureLOD: false // set to use shader texture LOD + }; - this.index0AttributeName = undefined; - this.uniformsNeedUpdate = false; + // When rendered geometry doesn't include these attributes but the material does, + // use these default values in WebGL. This avoids errors when buffer data is missing. + this.defaultAttributeValues = { + 'color': [ 1, 1, 1 ], + 'uv': [ 0, 0 ], + 'uv2': [ 0, 0 ] + }; - this.glslVersion = null; + this.index0AttributeName = undefined; + this.uniformsNeedUpdate = false; - if ( parameters !== undefined ) { + this.glslVersion = null; - if ( parameters.attributes !== undefined ) { + if ( parameters !== undefined ) { - console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); + if ( parameters.attributes !== undefined ) { - } + console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); - this.setValues( parameters ); + } - } + this.setValues( parameters ); -} + } -ShaderMaterial.prototype = Object.create( Material.prototype ); -ShaderMaterial.prototype.constructor = ShaderMaterial; + } -ShaderMaterial.prototype.isShaderMaterial = true; + copy( source ) { -ShaderMaterial.prototype.copy = function ( source ) { + super.copy( source ); - Material.prototype.copy.call( this, source ); + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; - this.fragmentShader = source.fragmentShader; - this.vertexShader = source.vertexShader; + this.uniforms = cloneUniforms( source.uniforms ); - this.uniforms = cloneUniforms( source.uniforms ); + this.defines = Object.assign( {}, source.defines ); - this.defines = Object.assign( {}, source.defines ); + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; + this.lights = source.lights; + this.clipping = source.clipping; - this.lights = source.lights; - this.clipping = source.clipping; + this.skinning = source.skinning; - this.skinning = source.skinning; + this.morphTargets = source.morphTargets; + this.morphNormals = source.morphNormals; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + this.extensions = Object.assign( {}, source.extensions ); - this.extensions = Object.assign( {}, source.extensions ); + this.glslVersion = source.glslVersion; - this.glslVersion = source.glslVersion; + return this; - return this; + } -}; + toJSON( meta ) { -ShaderMaterial.prototype.toJSON = function ( meta ) { + const data = super.toJSON( meta ); - const data = Material.prototype.toJSON.call( this, meta ); + data.glslVersion = this.glslVersion; + data.uniforms = {}; - data.glslVersion = this.glslVersion; - data.uniforms = {}; + for ( const name in this.uniforms ) { - for ( const name in this.uniforms ) { + const uniform = this.uniforms[ name ]; + const value = uniform.value; - const uniform = this.uniforms[ name ]; - const value = uniform.value; + if ( value && value.isTexture ) { - if ( value && value.isTexture ) { + data.uniforms[ name ] = { + type: 't', + value: value.toJSON( meta ).uuid + }; - data.uniforms[ name ] = { - type: 't', - value: value.toJSON( meta ).uuid - }; + } else if ( value && value.isColor ) { - } else if ( value && value.isColor ) { + data.uniforms[ name ] = { + type: 'c', + value: value.getHex() + }; - data.uniforms[ name ] = { - type: 'c', - value: value.getHex() - }; + } else if ( value && value.isVector2 ) { - } else if ( value && value.isVector2 ) { + data.uniforms[ name ] = { + type: 'v2', + value: value.toArray() + }; - data.uniforms[ name ] = { - type: 'v2', - value: value.toArray() - }; + } else if ( value && value.isVector3 ) { - } else if ( value && value.isVector3 ) { + data.uniforms[ name ] = { + type: 'v3', + value: value.toArray() + }; - data.uniforms[ name ] = { - type: 'v3', - value: value.toArray() - }; + } else if ( value && value.isVector4 ) { - } else if ( value && value.isVector4 ) { + data.uniforms[ name ] = { + type: 'v4', + value: value.toArray() + }; - data.uniforms[ name ] = { - type: 'v4', - value: value.toArray() - }; + } else if ( value && value.isMatrix3 ) { - } else if ( value && value.isMatrix3 ) { + data.uniforms[ name ] = { + type: 'm3', + value: value.toArray() + }; - data.uniforms[ name ] = { - type: 'm3', - value: value.toArray() - }; + } else if ( value && value.isMatrix4 ) { - } else if ( value && value.isMatrix4 ) { + data.uniforms[ name ] = { + type: 'm4', + value: value.toArray() + }; - data.uniforms[ name ] = { - type: 'm4', - value: value.toArray() - }; + } else { - } else { + data.uniforms[ name ] = { + value: value + }; - data.uniforms[ name ] = { - value: value - }; + // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far - // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far + } } - } - - if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; + if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; - data.vertexShader = this.vertexShader; - data.fragmentShader = this.fragmentShader; + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; - const extensions = {}; + const extensions = {}; - for ( const key in this.extensions ) { + for ( const key in this.extensions ) { - if ( this.extensions[ key ] === true ) extensions[ key ] = true; + if ( this.extensions[ key ] === true ) extensions[ key ] = true; - } + } - if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; + if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; - return data; + return data; -}; + } -function Camera() { +} - Object3D.call( this ); +ShaderMaterial.prototype.isShaderMaterial = true; - this.type = 'Camera'; +class Camera extends Object3D { - this.matrixWorldInverse = new Matrix4(); + constructor() { - this.projectionMatrix = new Matrix4(); - this.projectionMatrixInverse = new Matrix4(); + super(); -} + this.type = 'Camera'; -Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.matrixWorldInverse = new Matrix4(); - constructor: Camera, + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); - isCamera: true, + } - copy: function ( source, recursive ) { + copy( source, recursive ) { - Object3D.prototype.copy.call( this, source, recursive ); + super.copy( source, recursive ); this.matrixWorldInverse.copy( source.matrixWorldInverse ); @@ -11624,9 +11629,9 @@ Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { return this; - }, + } - getWorldDirection: function ( target ) { + getWorldDirection( target ) { if ( target === undefined ) { @@ -11641,64 +11646,62 @@ Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize(); - }, + } - updateMatrixWorld: function ( force ) { + updateMatrixWorld( force ) { - Object3D.prototype.updateMatrixWorld.call( this, force ); + super.updateMatrixWorld( force ); this.matrixWorldInverse.copy( this.matrixWorld ).invert(); - }, + } - updateWorldMatrix: function ( updateParents, updateChildren ) { + updateWorldMatrix( updateParents, updateChildren ) { - Object3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren ); + super.updateWorldMatrix( updateParents, updateChildren ); this.matrixWorldInverse.copy( this.matrixWorld ).invert(); - }, + } - clone: function () { + clone() { return new this.constructor().copy( this ); } -} ); - -function PerspectiveCamera( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { +} - Camera.call( this ); +Camera.prototype.isCamera = true; - this.type = 'PerspectiveCamera'; +class PerspectiveCamera extends Camera { - this.fov = fov; - this.zoom = 1; + constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { - this.near = near; - this.far = far; - this.focus = 10; + super(); - this.aspect = aspect; - this.view = null; + this.type = 'PerspectiveCamera'; - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) + this.fov = fov; + this.zoom = 1; - this.updateProjectionMatrix(); + this.near = near; + this.far = far; + this.focus = 10; -} + this.aspect = aspect; + this.view = null; -PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) - constructor: PerspectiveCamera, + this.updateProjectionMatrix(); - isPerspectiveCamera: true, + } - copy: function ( source, recursive ) { + copy( source, recursive ) { - Camera.prototype.copy.call( this, source, recursive ); + super.copy( source, recursive ); this.fov = source.fov; this.zoom = source.zoom; @@ -11715,7 +11718,7 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), return this; - }, + } /** * Sets the FOV by focal length in respect to the current .filmGauge. @@ -11725,47 +11728,47 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), * * Values for focal length and film gauge must have the same unit. */ - setFocalLength: function ( focalLength ) { + setFocalLength( focalLength ) { /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - this.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); this.updateProjectionMatrix(); - }, + } /** * Calculates the focal length from the current .fov and .filmGauge. */ - getFocalLength: function () { + getFocalLength() { - const vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ); + const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); return 0.5 * this.getFilmHeight() / vExtentSlope; - }, + } - getEffectiveFOV: function () { + getEffectiveFOV() { - return MathUtils.RAD2DEG * 2 * Math.atan( - Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom ); + return RAD2DEG * 2 * Math.atan( + Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); - }, + } - getFilmWidth: function () { + getFilmWidth() { // film not completely covered in portrait format (aspect < 1) return this.filmGauge * Math.min( this.aspect, 1 ); - }, + } - getFilmHeight: function () { + getFilmHeight() { // film not completely covered in landscape format (aspect > 1) return this.filmGauge / Math.max( this.aspect, 1 ); - }, + } /** * Sets an offset in a larger frustum. This is useful for multi-window or @@ -11802,7 +11805,7 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), * * Note there is no reason monitors have to be the same size or in a grid. */ - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { this.aspect = fullWidth / fullHeight; @@ -11830,9 +11833,9 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), this.updateProjectionMatrix(); - }, + } - clearViewOffset: function () { + clearViewOffset() { if ( this.view !== null ) { @@ -11842,12 +11845,12 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), this.updateProjectionMatrix(); - }, + } - updateProjectionMatrix: function () { + updateProjectionMatrix() { const near = this.near; - let top = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom; + let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom; let height = 2 * top; let width = this.aspect * height; let left = - 0.5 * width; @@ -11872,11 +11875,11 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); - }, + } - toJSON: function ( meta ) { + toJSON( meta ) { - const data = Object3D.prototype.toJSON.call( this, meta ); + const data = super.toJSON( meta ); data.object.fov = this.fov; data.object.zoom = this.zoom; @@ -11896,7 +11899,9 @@ PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), } -} ); +} + +PerspectiveCamera.prototype.isPerspectiveCamera = true; const fov = 90, aspect = 1; @@ -15466,6 +15471,7 @@ class DataTexture2DArray extends Texture { this.generateMipmaps = false; this.flipY = false; + this.unpackAlignment = 1; this.needsUpdate = true; @@ -15498,6 +15504,7 @@ class DataTexture3D extends Texture { this.generateMipmaps = false; this.flipY = false; + this.unpackAlignment = 1; this.needsUpdate = true; @@ -17542,7 +17549,7 @@ function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingSta vertexTangents: ( material.normalMap && material.vertexTangents ), vertexColors: material.vertexColors, - vertexAlphas: material.vertexColors === true && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4, + vertexAlphas: material.vertexColors === true && object.geometry && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4, vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmissionMap, uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap, @@ -19676,6 +19683,24 @@ function WebGLState( gl, extensions, capabilities ) { currentBoundFramebuffers[ target ] = framebuffer; + if ( isWebGL2 ) { + + // 36009 is equivalent to 36160 + + if ( target === 36009 ) { + + currentBoundFramebuffers[ 36160 ] = framebuffer; + + } + + if ( target === 36160 ) { + + currentBoundFramebuffers[ 36009 ] = framebuffer; + + } + + } + } } @@ -20330,7 +20355,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - const floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor; + const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor; const width = floor( scale * image.width ); const height = floor( scale * image.height ); @@ -20369,9 +20394,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function isPowerOfTwo( image ) { + function isPowerOfTwo$1( image ) { - return MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height ); + return isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ); } @@ -20774,10 +20799,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.pixelStorei( 3317, texture.unpackAlignment ); _gl.pixelStorei( 37443, 0 ); - const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false; + const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false; const image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); - const supportsMips = isPowerOfTwo( image ) || isWebGL2, + const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, glFormat = utils.convert( texture.format ); let glType = utils.convert( texture.type ), @@ -21004,7 +21029,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } const image = cubeImage[ 0 ], - supportsMips = isPowerOfTwo( image ) || isWebGL2, + supportsMips = isPowerOfTwo$1( image ) || isWebGL2, glFormat = utils.convert( texture.format ), glType = utils.convert( texture.type ), glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType ); @@ -21312,7 +21337,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); const isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true ); const isRenderTarget3D = texture.isDataTexture3D || texture.isDataTexture2DArray; - const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2; + const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2; // Handles WebGL2 RGBFormat fallback - #18858 @@ -21449,7 +21474,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const texture = renderTarget.texture; - const supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2; + const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2; if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { @@ -21470,11 +21495,6 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( isWebGL2 ) { - const renderTargetProperties = properties.get( renderTarget ); - - state.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer ); - state.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer ); - const width = renderTarget.width; const height = renderTarget.height; let mask = 16384; @@ -21482,9 +21502,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( renderTarget.depthBuffer ) mask |= 256; if ( renderTarget.stencilBuffer ) mask |= 1024; + const renderTargetProperties = properties.get( renderTarget ); + + state.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer ); + _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 ); - state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905 + state.bindFramebuffer( 36008, null ); + state.bindFramebuffer( 36009, renderTargetProperties.__webglMultisampledFramebuffer ); } else { @@ -21801,19 +21827,19 @@ class Group extends Object3D { Group.prototype.isGroup = true; -function WebXRController() { +const _moveEvent = { type: 'move' }; - this._targetRay = null; - this._grip = null; - this._hand = null; +class WebXRController { -} + constructor() { -Object.assign( WebXRController.prototype, { + this._targetRay = null; + this._grip = null; + this._hand = null; - constructor: WebXRController, + } - getHandSpace: function () { + getHandSpace() { if ( this._hand === null ) { @@ -21828,37 +21854,45 @@ Object.assign( WebXRController.prototype, { return this._hand; - }, + } - getTargetRaySpace: function () { + getTargetRaySpace() { if ( this._targetRay === null ) { this._targetRay = new Group(); this._targetRay.matrixAutoUpdate = false; this._targetRay.visible = false; + this._targetRay.hasLinearVelocity = false; + this._targetRay.linearVelocity = new Vector3(); + this._targetRay.hasAngularVelocity = false; + this._targetRay.angularVelocity = new Vector3(); } return this._targetRay; - }, + } - getGripSpace: function () { + getGripSpace() { if ( this._grip === null ) { this._grip = new Group(); this._grip.matrixAutoUpdate = false; this._grip.visible = false; + this._grip.hasLinearVelocity = false; + this._grip.linearVelocity = new Vector3(); + this._grip.hasAngularVelocity = false; + this._grip.angularVelocity = new Vector3(); } return this._grip; - }, + } - dispatchEvent: function ( event ) { + dispatchEvent( event ) { if ( this._targetRay !== null ) { @@ -21880,9 +21914,9 @@ Object.assign( WebXRController.prototype, { return this; - }, + } - disconnect: function ( inputSource ) { + disconnect( inputSource ) { this.dispatchEvent( { type: 'disconnected', data: inputSource } ); @@ -21906,9 +21940,9 @@ Object.assign( WebXRController.prototype, { return this; - }, + } - update: function ( inputSource, frame, referenceSpace ) { + update( inputSource, frame, referenceSpace ) { let inputPose = null; let gripPose = null; @@ -21929,6 +21963,30 @@ Object.assign( WebXRController.prototype, { targetRay.matrix.fromArray( inputPose.transform.matrix ); targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + if ( inputPose.linearVelocity ) { + + targetRay.hasLinearVelocity = true; + targetRay.linearVelocity.copy( inputPose.linearVelocity ); + + } else { + + targetRay.hasLinearVelocity = false; + + } + + if ( inputPose.angularVelocity ) { + + targetRay.hasAngularVelocity = true; + targetRay.angularVelocity.copy( inputPose.angularVelocity ); + + } else { + + targetRay.hasAngularVelocity = false; + + } + + this.dispatchEvent( _moveEvent ); + } } @@ -22009,6 +22067,28 @@ Object.assign( WebXRController.prototype, { grip.matrix.fromArray( gripPose.transform.matrix ); grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + if ( gripPose.linearVelocity ) { + + grip.hasLinearVelocity = true; + grip.linearVelocity.copy( gripPose.linearVelocity ); + + } else { + + grip.hasLinearVelocity = false; + + } + + if ( gripPose.angularVelocity ) { + + grip.hasAngularVelocity = true; + grip.angularVelocity.copy( gripPose.angularVelocity ); + + } else { + + grip.hasAngularVelocity = false; + + } + } } @@ -22039,489 +22119,493 @@ Object.assign( WebXRController.prototype, { } -} ); +} -function WebXRManager( renderer, gl ) { +class WebXRManager extends EventDispatcher { - const scope = this; - const state = renderer.state; + constructor( renderer, gl ) { - let session = null; + super(); - let framebufferScaleFactor = 1.0; + const scope = this; + const state = renderer.state; - let referenceSpace = null; - let referenceSpaceType = 'local-floor'; + let session = null; - let pose = null; + let framebufferScaleFactor = 1.0; - const controllers = []; - const inputSourcesMap = new Map(); + let referenceSpace = null; + let referenceSpaceType = 'local-floor'; - // + let pose = null; - const cameraL = new PerspectiveCamera(); - cameraL.layers.enable( 1 ); - cameraL.viewport = new Vector4(); + const controllers = []; + const inputSourcesMap = new Map(); - const cameraR = new PerspectiveCamera(); - cameraR.layers.enable( 2 ); - cameraR.viewport = new Vector4(); + // - const cameras = [ cameraL, cameraR ]; + const cameraL = new PerspectiveCamera(); + cameraL.layers.enable( 1 ); + cameraL.viewport = new Vector4(); - const cameraVR = new ArrayCamera(); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + const cameraR = new PerspectiveCamera(); + cameraR.layers.enable( 2 ); + cameraR.viewport = new Vector4(); - let _currentDepthNear = null; - let _currentDepthFar = null; + const cameras = [ cameraL, cameraR ]; - // + const cameraVR = new ArrayCamera(); + cameraVR.layers.enable( 1 ); + cameraVR.layers.enable( 2 ); - this.enabled = false; + let _currentDepthNear = null; + let _currentDepthFar = null; + + // - this.isPresenting = false; + this.enabled = false; - this.getController = function ( index ) { + this.isPresenting = false; - let controller = controllers[ index ]; + this.getController = function ( index ) { - if ( controller === undefined ) { + let controller = controllers[ index ]; - controller = new WebXRController(); - controllers[ index ] = controller; + if ( controller === undefined ) { - } + controller = new WebXRController(); + controllers[ index ] = controller; - return controller.getTargetRaySpace(); + } - }; + return controller.getTargetRaySpace(); - this.getControllerGrip = function ( index ) { + }; - let controller = controllers[ index ]; + this.getControllerGrip = function ( index ) { - if ( controller === undefined ) { + let controller = controllers[ index ]; - controller = new WebXRController(); - controllers[ index ] = controller; + if ( controller === undefined ) { - } + controller = new WebXRController(); + controllers[ index ] = controller; - return controller.getGripSpace(); + } - }; + return controller.getGripSpace(); - this.getHand = function ( index ) { + }; - let controller = controllers[ index ]; + this.getHand = function ( index ) { - if ( controller === undefined ) { + let controller = controllers[ index ]; - controller = new WebXRController(); - controllers[ index ] = controller; + if ( controller === undefined ) { - } + controller = new WebXRController(); + controllers[ index ] = controller; - return controller.getHandSpace(); + } - }; + return controller.getHandSpace(); - // + }; + + // - function onSessionEvent( event ) { + function onSessionEvent( event ) { - const controller = inputSourcesMap.get( event.inputSource ); + const controller = inputSourcesMap.get( event.inputSource ); - if ( controller ) { + if ( controller ) { + + controller.dispatchEvent( { type: event.type, data: event.inputSource } ); - controller.dispatchEvent( { type: event.type, data: event.inputSource } ); + } } - } + function onSessionEnd() { - function onSessionEnd() { + inputSourcesMap.forEach( function ( controller, inputSource ) { - inputSourcesMap.forEach( function ( controller, inputSource ) { + controller.disconnect( inputSource ); - controller.disconnect( inputSource ); + } ); - } ); + inputSourcesMap.clear(); - inputSourcesMap.clear(); + _currentDepthNear = null; + _currentDepthFar = null; - _currentDepthNear = null; - _currentDepthFar = null; + // restore framebuffer/rendering state - // restore framebuffer/rendering state + state.bindXRFramebuffer( null ); + renderer.setRenderTarget( renderer.getRenderTarget() ); - state.bindXRFramebuffer( null ); - renderer.setRenderTarget( renderer.getRenderTarget() ); + // - // + animation.stop(); - animation.stop(); + scope.isPresenting = false; - scope.isPresenting = false; + scope.dispatchEvent( { type: 'sessionend' } ); - scope.dispatchEvent( { type: 'sessionend' } ); + } - } + this.setFramebufferScaleFactor = function ( value ) { - this.setFramebufferScaleFactor = function ( value ) { + framebufferScaleFactor = value; - framebufferScaleFactor = value; + if ( scope.isPresenting === true ) { - if ( scope.isPresenting === true ) { + console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); - console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); + } - } + }; - }; + this.setReferenceSpaceType = function ( value ) { - this.setReferenceSpaceType = function ( value ) { + referenceSpaceType = value; - referenceSpaceType = value; + if ( scope.isPresenting === true ) { - if ( scope.isPresenting === true ) { + console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); - console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); + } - } + }; - }; + this.getReferenceSpace = function () { - this.getReferenceSpace = function () { + return referenceSpace; - return referenceSpace; + }; - }; + this.getSession = function () { - this.getSession = function () { + return session; - return session; + }; - }; + this.setSession = async function ( value ) { - this.setSession = async function ( value ) { + session = value; - session = value; + if ( session !== null ) { - if ( session !== null ) { + session.addEventListener( 'select', onSessionEvent ); + session.addEventListener( 'selectstart', onSessionEvent ); + session.addEventListener( 'selectend', onSessionEvent ); + session.addEventListener( 'squeeze', onSessionEvent ); + session.addEventListener( 'squeezestart', onSessionEvent ); + session.addEventListener( 'squeezeend', onSessionEvent ); + session.addEventListener( 'end', onSessionEnd ); + session.addEventListener( 'inputsourceschange', onInputSourcesChange ); - session.addEventListener( 'select', onSessionEvent ); - session.addEventListener( 'selectstart', onSessionEvent ); - session.addEventListener( 'selectend', onSessionEvent ); - session.addEventListener( 'squeeze', onSessionEvent ); - session.addEventListener( 'squeezestart', onSessionEvent ); - session.addEventListener( 'squeezeend', onSessionEvent ); - session.addEventListener( 'end', onSessionEnd ); - session.addEventListener( 'inputsourceschange', onInputSourcesChange ); + const attributes = gl.getContextAttributes(); - const attributes = gl.getContextAttributes(); + if ( attributes.xrCompatible !== true ) { - if ( attributes.xrCompatible !== true ) { + await gl.makeXRCompatible(); - await gl.makeXRCompatible(); + } - } + const layerInit = { + antialias: attributes.antialias, + alpha: attributes.alpha, + depth: attributes.depth, + stencil: attributes.stencil, + framebufferScaleFactor: framebufferScaleFactor + }; - const layerInit = { - antialias: attributes.antialias, - alpha: attributes.alpha, - depth: attributes.depth, - stencil: attributes.stencil, - framebufferScaleFactor: framebufferScaleFactor - }; + // eslint-disable-next-line no-undef + const baseLayer = new XRWebGLLayer( session, gl, layerInit ); - // eslint-disable-next-line no-undef - const baseLayer = new XRWebGLLayer( session, gl, layerInit ); + session.updateRenderState( { baseLayer: baseLayer } ); - session.updateRenderState( { baseLayer: baseLayer } ); + referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); - referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); + animation.setContext( session ); + animation.start(); - animation.setContext( session ); - animation.start(); + scope.isPresenting = true; - scope.isPresenting = true; + scope.dispatchEvent( { type: 'sessionstart' } ); - scope.dispatchEvent( { type: 'sessionstart' } ); + } - } + }; - }; + function onInputSourcesChange( event ) { - function onInputSourcesChange( event ) { + const inputSources = session.inputSources; - const inputSources = session.inputSources; + // Assign inputSources to available controllers - // Assign inputSources to available controllers + for ( let i = 0; i < controllers.length; i ++ ) { - for ( let i = 0; i < controllers.length; i ++ ) { + inputSourcesMap.set( inputSources[ i ], controllers[ i ] ); - inputSourcesMap.set( inputSources[ i ], controllers[ i ] ); + } - } + // Notify disconnected - // Notify disconnected + for ( let i = 0; i < event.removed.length; i ++ ) { - for ( let i = 0; i < event.removed.length; i ++ ) { + const inputSource = event.removed[ i ]; + const controller = inputSourcesMap.get( inputSource ); - const inputSource = event.removed[ i ]; - const controller = inputSourcesMap.get( inputSource ); + if ( controller ) { - if ( controller ) { + controller.dispatchEvent( { type: 'disconnected', data: inputSource } ); + inputSourcesMap.delete( inputSource ); - controller.dispatchEvent( { type: 'disconnected', data: inputSource } ); - inputSourcesMap.delete( inputSource ); + } } - } + // Notify connected - // Notify connected + for ( let i = 0; i < event.added.length; i ++ ) { - for ( let i = 0; i < event.added.length; i ++ ) { + const inputSource = event.added[ i ]; + const controller = inputSourcesMap.get( inputSource ); - const inputSource = event.added[ i ]; - const controller = inputSourcesMap.get( inputSource ); + if ( controller ) { - if ( controller ) { + controller.dispatchEvent( { type: 'connected', data: inputSource } ); - controller.dispatchEvent( { type: 'connected', data: inputSource } ); + } } } - } + // - // + const cameraLPos = new Vector3(); + const cameraRPos = new Vector3(); - const cameraLPos = new Vector3(); - const cameraRPos = new Vector3(); + /** + * Assumes 2 cameras that are parallel and share an X-axis, and that + * the cameras' projection and world matrices have already been set. + * And that near and far planes are identical for both cameras. + * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 + */ + function setProjectionFromUnion( camera, cameraL, cameraR ) { - /** - * Assumes 2 cameras that are parallel and share an X-axis, and that - * the cameras' projection and world matrices have already been set. - * And that near and far planes are identical for both cameras. - * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 - */ - function setProjectionFromUnion( camera, cameraL, cameraR ) { + cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); + cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); - cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); - cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); + const ipd = cameraLPos.distanceTo( cameraRPos ); - const ipd = cameraLPos.distanceTo( cameraRPos ); + const projL = cameraL.projectionMatrix.elements; + const projR = cameraR.projectionMatrix.elements; - const projL = cameraL.projectionMatrix.elements; - const projR = cameraR.projectionMatrix.elements; + // VR systems will have identical far and near planes, and + // most likely identical top and bottom frustum extents. + // Use the left camera for these values. + const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); + const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); + const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; + const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; - // VR systems will have identical far and near planes, and - // most likely identical top and bottom frustum extents. - // Use the left camera for these values. - const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); - const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); - const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; - const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; + const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; + const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; + const left = near * leftFov; + const right = near * rightFov; - const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; - const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; - const left = near * leftFov; - const right = near * rightFov; + // Calculate the new camera's position offset from the + // left camera. xOffset should be roughly half `ipd`. + const zOffset = ipd / ( - leftFov + rightFov ); + const xOffset = zOffset * - leftFov; - // Calculate the new camera's position offset from the - // left camera. xOffset should be roughly half `ipd`. - const zOffset = ipd / ( - leftFov + rightFov ); - const xOffset = zOffset * - leftFov; + // TODO: Better way to apply this offset? + cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); + camera.translateX( xOffset ); + camera.translateZ( zOffset ); + camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); - // TODO: Better way to apply this offset? - cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); - camera.translateX( xOffset ); - camera.translateZ( zOffset ); - camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); - camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); + // Find the union of the frustum values of the cameras and scale + // the values so that the near plane's position does not change in world space, + // although must now be relative to the new union camera. + const near2 = near + zOffset; + const far2 = far + zOffset; + const left2 = left - xOffset; + const right2 = right + ( ipd - xOffset ); + const top2 = topFov * far / far2 * near2; + const bottom2 = bottomFov * far / far2 * near2; - // Find the union of the frustum values of the cameras and scale - // the values so that the near plane's position does not change in world space, - // although must now be relative to the new union camera. - const near2 = near + zOffset; - const far2 = far + zOffset; - const left2 = left - xOffset; - const right2 = right + ( ipd - xOffset ); - const top2 = topFov * far / far2 * near2; - const bottom2 = bottomFov * far / far2 * near2; + camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); - camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + } - } + function updateCamera( camera, parent ) { - function updateCamera( camera, parent ) { + if ( parent === null ) { - if ( parent === null ) { + camera.matrixWorld.copy( camera.matrix ); - camera.matrixWorld.copy( camera.matrix ); + } else { - } else { + camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); - camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); + } + + camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); } - camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); + this.getCamera = function ( camera ) { - } + cameraVR.near = cameraR.near = cameraL.near = camera.near; + cameraVR.far = cameraR.far = cameraL.far = camera.far; - this.getCamera = function ( camera ) { + if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { - cameraVR.near = cameraR.near = cameraL.near = camera.near; - cameraVR.far = cameraR.far = cameraL.far = camera.far; + // Note that the new renderState won't apply until the next frame. See #18320 - if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { + session.updateRenderState( { + depthNear: cameraVR.near, + depthFar: cameraVR.far + } ); - // Note that the new renderState won't apply until the next frame. See #18320 + _currentDepthNear = cameraVR.near; + _currentDepthFar = cameraVR.far; - session.updateRenderState( { - depthNear: cameraVR.near, - depthFar: cameraVR.far - } ); + } - _currentDepthNear = cameraVR.near; - _currentDepthFar = cameraVR.far; + const parent = camera.parent; + const cameras = cameraVR.cameras; - } + updateCamera( cameraVR, parent ); - const parent = camera.parent; - const cameras = cameraVR.cameras; + for ( let i = 0; i < cameras.length; i ++ ) { - updateCamera( cameraVR, parent ); + updateCamera( cameras[ i ], parent ); - for ( let i = 0; i < cameras.length; i ++ ) { + } - updateCamera( cameras[ i ], parent ); + // update camera and its children - } + camera.matrixWorld.copy( cameraVR.matrixWorld ); + camera.matrix.copy( cameraVR.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); - // update camera and its children + const children = camera.children; - camera.matrixWorld.copy( cameraVR.matrixWorld ); - camera.matrix.copy( cameraVR.matrix ); - camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - const children = camera.children; + children[ i ].updateMatrixWorld( true ); - for ( let i = 0, l = children.length; i < l; i ++ ) { + } - children[ i ].updateMatrixWorld( true ); + // update projection matrix for proper view frustum culling - } + if ( cameras.length === 2 ) { - // update projection matrix for proper view frustum culling + setProjectionFromUnion( cameraVR, cameraL, cameraR ); - if ( cameras.length === 2 ) { + } else { - setProjectionFromUnion( cameraVR, cameraL, cameraR ); + // assume single camera setup (AR) - } else { + cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); - // assume single camera setup (AR) + } - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + return cameraVR; - } + }; - return cameraVR; + // Animation Loop - }; + let onAnimationFrameCallback = null; - // Animation Loop + function onAnimationFrame( time, frame ) { - let onAnimationFrameCallback = null; + pose = frame.getViewerPose( referenceSpace ); - function onAnimationFrame( time, frame ) { + if ( pose !== null ) { - pose = frame.getViewerPose( referenceSpace ); + const views = pose.views; + const baseLayer = session.renderState.baseLayer; - if ( pose !== null ) { + state.bindXRFramebuffer( baseLayer.framebuffer ); - const views = pose.views; - const baseLayer = session.renderState.baseLayer; + let cameraVRNeedsUpdate = false; - state.bindXRFramebuffer( baseLayer.framebuffer ); + // check if it's necessary to rebuild cameraVR's camera list - let cameraVRNeedsUpdate = false; + if ( views.length !== cameraVR.cameras.length ) { - // check if it's necessary to rebuild cameraVR's camera list + cameraVR.cameras.length = 0; + cameraVRNeedsUpdate = true; - if ( views.length !== cameraVR.cameras.length ) { + } - cameraVR.cameras.length = 0; - cameraVRNeedsUpdate = true; + for ( let i = 0; i < views.length; i ++ ) { - } + const view = views[ i ]; + const viewport = baseLayer.getViewport( view ); - for ( let i = 0; i < views.length; i ++ ) { + const camera = cameras[ i ]; + camera.matrix.fromArray( view.transform.matrix ); + camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); - const view = views[ i ]; - const viewport = baseLayer.getViewport( view ); + if ( i === 0 ) { - const camera = cameras[ i ]; - camera.matrix.fromArray( view.transform.matrix ); - camera.projectionMatrix.fromArray( view.projectionMatrix ); - camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); + cameraVR.matrix.copy( camera.matrix ); - if ( i === 0 ) { - - cameraVR.matrix.copy( camera.matrix ); + } - } + if ( cameraVRNeedsUpdate === true ) { - if ( cameraVRNeedsUpdate === true ) { + cameraVR.cameras.push( camera ); - cameraVR.cameras.push( camera ); + } } } - } + // - // + const inputSources = session.inputSources; - const inputSources = session.inputSources; + for ( let i = 0; i < controllers.length; i ++ ) { - for ( let i = 0; i < controllers.length; i ++ ) { + const controller = controllers[ i ]; + const inputSource = inputSources[ i ]; - const controller = controllers[ i ]; - const inputSource = inputSources[ i ]; + controller.update( inputSource, frame, referenceSpace ); - controller.update( inputSource, frame, referenceSpace ); + } - } + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); - if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); + } - } + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); - const animation = new WebGLAnimation(); - animation.setAnimationLoop( onAnimationFrame ); + this.setAnimationLoop = function ( callback ) { - this.setAnimationLoop = function ( callback ) { + onAnimationFrameCallback = callback; - onAnimationFrameCallback = callback; + }; - }; + this.dispose = function () {}; - this.dispose = function () {}; + } } -Object.assign( WebXRManager.prototype, EventDispatcher.prototype ); - function WebGLMaterials( properties ) { function refreshFogUniforms( uniforms, fog ) { @@ -24560,6 +24644,8 @@ function WebGLRenderer( parameters ) { parameters.uniforms = programCache.getUniforms( material ); + material.onBuild( parameters, _this ); + material.onBeforeCompile( parameters, _this ); program = programCache.acquireProgram( parameters, programCacheKey ); @@ -24643,7 +24729,7 @@ function WebGLRenderer( parameters ) { const environment = material.isMeshStandardMaterial ? scene.environment : null; const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding; const envMap = cubemaps.get( material.envMap || environment ); - const vertexAlphas = material.vertexColors === true && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4; + const vertexAlphas = material.vertexColors === true && object.geometry && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4; const materialProperties = properties.get( material ); const lights = currentRenderState.state.lights; @@ -24845,7 +24931,7 @@ function WebGLRenderer( parameters ) { let size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix - size = MathUtils.ceilPowerOfTwo( size ); + size = ceilPowerOfTwo( size ); size = Math.max( size, 4 ); const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel @@ -25411,46 +25497,40 @@ class Scene extends Object3D { Scene.prototype.isScene = true; -function InterleavedBuffer( array, stride ) { - - this.array = array; - this.stride = stride; - this.count = array !== undefined ? array.length / stride : 0; +class InterleavedBuffer { - this.usage = StaticDrawUsage; - this.updateRange = { offset: 0, count: - 1 }; + constructor( array, stride ) { - this.version = 0; - - this.uuid = MathUtils.generateUUID(); + this.array = array; + this.stride = stride; + this.count = array !== undefined ? array.length / stride : 0; -} + this.usage = StaticDrawUsage; + this.updateRange = { offset: 0, count: - 1 }; -Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', { + this.version = 0; - set: function ( value ) { + this.uuid = generateUUID(); - if ( value === true ) this.version ++; + this.onUploadCallback = function () {}; } -} ); - -Object.assign( InterleavedBuffer.prototype, { + set needsUpdate( value ) { - isInterleavedBuffer: true, + if ( value === true ) this.version ++; - onUploadCallback: function () {}, + } - setUsage: function ( value ) { + setUsage( value ) { this.usage = value; return this; - }, + } - copy: function ( source ) { + copy( source ) { this.array = new source.array.constructor( source.array ); this.count = source.count; @@ -25459,9 +25539,9 @@ Object.assign( InterleavedBuffer.prototype, { return this; - }, + } - copyAt: function ( index1, attribute, index2 ) { + copyAt( index1, attribute, index2 ) { index1 *= this.stride; index2 *= attribute.stride; @@ -25474,17 +25554,17 @@ Object.assign( InterleavedBuffer.prototype, { return this; - }, + } - set: function ( value, offset = 0 ) { + set( value, offset = 0 ) { this.array.set( value, offset ); return this; - }, + } - clone: function ( data ) { + clone( data ) { if ( data.arrayBuffers === undefined ) { @@ -25494,7 +25574,7 @@ Object.assign( InterleavedBuffer.prototype, { if ( this.array.buffer._uuid === undefined ) { - this.array.buffer._uuid = MathUtils.generateUUID(); + this.array.buffer._uuid = generateUUID(); } @@ -25511,17 +25591,17 @@ Object.assign( InterleavedBuffer.prototype, { return ib; - }, + } - onUpload: function ( callback ) { + onUpload( callback ) { this.onUploadCallback = callback; return this; - }, + } - toJSON: function ( data ) { + toJSON( data ) { if ( data.arrayBuffers === undefined ) { @@ -25533,7 +25613,7 @@ Object.assign( InterleavedBuffer.prototype, { if ( this.array.buffer._uuid === undefined ) { - this.array.buffer._uuid = MathUtils.generateUUID(); + this.array.buffer._uuid = generateUUID(); } @@ -25554,61 +25634,45 @@ Object.assign( InterleavedBuffer.prototype, { } -} ); - -const _vector$6 = new Vector3(); - -function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) { - - this.name = ''; - - this.data = interleavedBuffer; - this.itemSize = itemSize; - this.offset = offset; - - this.normalized = normalized === true; - } -Object.defineProperties( InterleavedBufferAttribute.prototype, { - - count: { - - get: function () { +InterleavedBuffer.prototype.isInterleavedBuffer = true; - return this.data.count; +const _vector$6 = new /*@__PURE__*/ Vector3(); - } +class InterleavedBufferAttribute { - }, + constructor( interleavedBuffer, itemSize, offset, normalized ) { - array: { + this.name = ''; - get: function () { + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; - return this.data.array; + this.normalized = normalized === true; - } + } - }, + get count() { - needsUpdate: { + return this.data.count; - set: function ( value ) { + } - this.data.needsUpdate = value; + get array() { - } + return this.data.array; } -} ); + set needsUpdate( value ) { -Object.assign( InterleavedBufferAttribute.prototype, { + this.data.needsUpdate = value; - isInterleavedBufferAttribute: true, + } - applyMatrix4: function ( m ) { + applyMatrix4( m ) { for ( let i = 0, l = this.data.count; i < l; i ++ ) { @@ -25624,9 +25688,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { return this; - }, + } - applyNormalMatrix: function ( m ) { + applyNormalMatrix( m ) { for ( let i = 0, l = this.count; i < l; i ++ ) { @@ -25642,9 +25706,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { return this; - }, + } - transformDirection: function ( m ) { + transformDirection( m ) { for ( let i = 0, l = this.count; i < l; i ++ ) { @@ -25660,65 +25724,65 @@ Object.assign( InterleavedBufferAttribute.prototype, { return this; - }, + } - setX: function ( index, x ) { + setX( index, x ) { this.data.array[ index * this.data.stride + this.offset ] = x; return this; - }, + } - setY: function ( index, y ) { + setY( index, y ) { this.data.array[ index * this.data.stride + this.offset + 1 ] = y; return this; - }, + } - setZ: function ( index, z ) { + setZ( index, z ) { this.data.array[ index * this.data.stride + this.offset + 2 ] = z; return this; - }, + } - setW: function ( index, w ) { + setW( index, w ) { this.data.array[ index * this.data.stride + this.offset + 3 ] = w; return this; - }, + } - getX: function ( index ) { + getX( index ) { return this.data.array[ index * this.data.stride + this.offset ]; - }, + } - getY: function ( index ) { + getY( index ) { return this.data.array[ index * this.data.stride + this.offset + 1 ]; - }, + } - getZ: function ( index ) { + getZ( index ) { return this.data.array[ index * this.data.stride + this.offset + 2 ]; - }, + } - getW: function ( index ) { + getW( index ) { return this.data.array[ index * this.data.stride + this.offset + 3 ]; - }, + } - setXY: function ( index, x, y ) { + setXY( index, x, y ) { index = index * this.data.stride + this.offset; @@ -25727,9 +25791,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { return this; - }, + } - setXYZ: function ( index, x, y, z ) { + setXYZ( index, x, y, z ) { index = index * this.data.stride + this.offset; @@ -25739,9 +25803,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { return this; - }, + } - setXYZW: function ( index, x, y, z, w ) { + setXYZW( index, x, y, z, w ) { index = index * this.data.stride + this.offset; @@ -25752,9 +25816,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { return this; - }, + } - clone: function ( data ) { + clone( data ) { if ( data === undefined ) { @@ -25794,9 +25858,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { } - }, + } - toJSON: function ( data ) { + toJSON( data ) { if ( data === undefined ) { @@ -25853,7 +25917,9 @@ Object.assign( InterleavedBufferAttribute.prototype, { } -} ); +} + +InterleavedBufferAttribute.prototype.isInterleavedBufferAttribute = true; /** * parameters = { @@ -26271,35 +26337,31 @@ class LOD extends Object3D { } -const _basePosition = new Vector3(); - -const _skinIndex = new Vector4(); -const _skinWeight = new Vector4(); - -const _vector$5 = new Vector3(); -const _matrix = new Matrix4(); +const _basePosition = /*@__PURE__*/ new Vector3(); -function SkinnedMesh( geometry, material ) { +const _skinIndex = /*@__PURE__*/ new Vector4(); +const _skinWeight = /*@__PURE__*/ new Vector4(); - Mesh.call( this, geometry, material ); +const _vector$5 = /*@__PURE__*/ new Vector3(); +const _matrix = /*@__PURE__*/ new Matrix4(); - this.type = 'SkinnedMesh'; +class SkinnedMesh extends Mesh { - this.bindMode = 'attached'; - this.bindMatrix = new Matrix4(); - this.bindMatrixInverse = new Matrix4(); + constructor( geometry, material ) { -} + super( geometry, material ); -SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { + this.type = 'SkinnedMesh'; - constructor: SkinnedMesh, + this.bindMode = 'attached'; + this.bindMatrix = new Matrix4(); + this.bindMatrixInverse = new Matrix4(); - isSkinnedMesh: true, + } - copy: function ( source ) { + copy( source ) { - Mesh.prototype.copy.call( this, source ); + super.copy( source ); this.bindMode = source.bindMode; this.bindMatrix.copy( source.bindMatrix ); @@ -26309,9 +26371,9 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { return this; - }, + } - bind: function ( skeleton, bindMatrix ) { + bind( skeleton, bindMatrix ) { this.skeleton = skeleton; @@ -26328,15 +26390,15 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { this.bindMatrix.copy( bindMatrix ); this.bindMatrixInverse.copy( bindMatrix ).invert(); - }, + } - pose: function () { + pose() { this.skeleton.pose(); - }, + } - normalizeSkinWeights: function () { + normalizeSkinWeights() { const vector = new Vector4(); @@ -26365,11 +26427,11 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - updateMatrixWorld: function ( force ) { + updateMatrixWorld( force ) { - Mesh.prototype.updateMatrixWorld.call( this, force ); + super.updateMatrixWorld( force ); if ( this.bindMode === 'attached' ) { @@ -26385,9 +26447,9 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - boneTransform: function ( index, target ) { + boneTransform( index, target ) { const skeleton = this.skeleton; const geometry = this.geometry; @@ -26419,23 +26481,23 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } -} ); +} -function Bone() { +SkinnedMesh.prototype.isSkinnedMesh = true; - Object3D.call( this ); +class Bone extends Object3D { - this.type = 'Bone'; + constructor() { -} + super(); -Bone.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.type = 'Bone'; - constructor: Bone, + } - isBone: true +} -} ); +Bone.prototype.isBone = true; const _offsetMatrix = /*@__PURE__*/ new Matrix4(); const _identityMatrix = /*@__PURE__*/ new Matrix4(); @@ -26444,7 +26506,7 @@ class Skeleton { constructor( bones = [], boneInverses = [] ) { - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.bones = bones.slice( 0 ); this.boneInverses = boneInverses; @@ -26681,35 +26743,31 @@ class Skeleton { } -const _instanceLocalMatrix = new Matrix4(); -const _instanceWorldMatrix = new Matrix4(); +const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); +const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); const _instanceIntersects = []; -const _mesh = new Mesh(); - -function InstancedMesh( geometry, material, count ) { +const _mesh = /*@__PURE__*/ new Mesh(); - Mesh.call( this, geometry, material ); +class InstancedMesh extends Mesh { - this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 ); - this.instanceColor = null; + constructor( geometry, material, count ) { - this.count = count; - - this.frustumCulled = false; + super( geometry, material ); -} + this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 ); + this.instanceColor = null; -InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { + this.count = count; - constructor: InstancedMesh, + this.frustumCulled = false; - isInstancedMesh: true, + } - copy: function ( source ) { + copy( source ) { - Mesh.prototype.copy.call( this, source ); + super.copy( source ); this.instanceMatrix.copy( source.instanceMatrix ); @@ -26719,21 +26777,21 @@ InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { return this; - }, + } - getColorAt: function ( index, color ) { + getColorAt( index, color ) { color.fromArray( this.instanceColor.array, index * 3 ); - }, + } - getMatrixAt: function ( index, matrix ) { + getMatrixAt( index, matrix ) { matrix.fromArray( this.instanceMatrix.array, index * 16 ); - }, + } - raycast: function ( raycaster, intersects ) { + raycast( raycaster, intersects ) { const matrixWorld = this.matrixWorld; const raycastTimes = this.count; @@ -26772,9 +26830,9 @@ InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - setColorAt: function ( index, color ) { + setColorAt( index, color ) { if ( this.instanceColor === null ) { @@ -26784,25 +26842,27 @@ InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { color.toArray( this.instanceColor.array, index * 3 ); - }, + } - setMatrixAt: function ( index, matrix ) { + setMatrixAt( index, matrix ) { matrix.toArray( this.instanceMatrix.array, index * 16 ); - }, + } - updateMorphTargets: function () { + updateMorphTargets() { - }, + } - dispose: function () { + dispose() { this.dispatchEvent( { type: 'dispose' } ); } -} ); +} + +InstancedMesh.prototype.isInstancedMesh = true; /** * parameters = { @@ -26856,43 +26916,39 @@ class LineBasicMaterial extends Material { LineBasicMaterial.prototype.isLineBasicMaterial = true; -const _start$1 = new Vector3(); -const _end$1 = new Vector3(); -const _inverseMatrix$1 = new Matrix4(); -const _ray$1 = new Ray(); -const _sphere$1 = new Sphere(); - -function Line( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { +const _start$1 = /*@__PURE__*/ new Vector3(); +const _end$1 = /*@__PURE__*/ new Vector3(); +const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _ray$1 = /*@__PURE__*/ new Ray(); +const _sphere$1 = /*@__PURE__*/ new Sphere(); - Object3D.call( this ); +class Line extends Object3D { - this.type = 'Line'; + constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { - this.geometry = geometry; - this.material = material; - - this.updateMorphTargets(); + super(); -} + this.type = 'Line'; -Line.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.geometry = geometry; + this.material = material; - constructor: Line, + this.updateMorphTargets(); - isLine: true, + } - copy: function ( source ) { + copy( source ) { - Object3D.prototype.copy.call( this, source ); + super.copy( source ); this.material = source.material; this.geometry = source.geometry; return this; - }, + } - computeLineDistances: function () { + computeLineDistances() { const geometry = this.geometry; @@ -26931,9 +26987,9 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), { return this; - }, + } - raycast: function ( raycaster, intersects ) { + raycast( raycaster, intersects ) { const geometry = this.geometry; const matrixWorld = this.matrixWorld; @@ -27051,9 +27107,9 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), { } - }, + } - updateMorphTargets: function () { + updateMorphTargets() { const geometry = this.geometry; @@ -27098,26 +27154,24 @@ Line.prototype = Object.assign( Object.create( Object3D.prototype ), { } -} ); - -const _start = new Vector3(); -const _end = new Vector3(); +} -function LineSegments( geometry, material ) { +Line.prototype.isLine = true; - Line.call( this, geometry, material ); +const _start = /*@__PURE__*/ new Vector3(); +const _end = /*@__PURE__*/ new Vector3(); - this.type = 'LineSegments'; +class LineSegments extends Line { -} + constructor( geometry, material ) { -LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { + super( geometry, material ); - constructor: LineSegments, + this.type = 'LineSegments'; - isLineSegments: true, + } - computeLineDistances: function () { + computeLineDistances() { const geometry = this.geometry; @@ -27158,7 +27212,9 @@ LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { } -} ); +} + +LineSegments.prototype.isLineSegments = true; class LineLoop extends Line { @@ -27234,42 +27290,38 @@ class PointsMaterial extends Material { PointsMaterial.prototype.isPointsMaterial = true; -const _inverseMatrix = new Matrix4(); -const _ray = new Ray(); -const _sphere = new Sphere(); -const _position$2 = new Vector3(); +const _inverseMatrix = /*@__PURE__*/ new Matrix4(); +const _ray = /*@__PURE__*/ new Ray(); +const _sphere = /*@__PURE__*/ new Sphere(); +const _position$2 = /*@__PURE__*/ new Vector3(); -function Points( geometry = new BufferGeometry(), material = new PointsMaterial() ) { +class Points extends Object3D { - Object3D.call( this ); + constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { - this.type = 'Points'; - - this.geometry = geometry; - this.material = material; - - this.updateMorphTargets(); + super(); -} + this.type = 'Points'; -Points.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.geometry = geometry; + this.material = material; - constructor: Points, + this.updateMorphTargets(); - isPoints: true, + } - copy: function ( source ) { + copy( source ) { - Object3D.prototype.copy.call( this, source ); + super.copy( source ); this.material = source.material; this.geometry = source.geometry; return this; - }, + } - raycast: function ( raycaster, intersects ) { + raycast( raycaster, intersects ) { const geometry = this.geometry; const matrixWorld = this.matrixWorld; @@ -27336,9 +27388,9 @@ Points.prototype = Object.assign( Object.create( Object3D.prototype ), { } - }, + } - updateMorphTargets: function () { + updateMorphTargets() { const geometry = this.geometry; @@ -27383,7 +27435,9 @@ Points.prototype = Object.assign( Object.create( Object3D.prototype ), { } -} ); +} + +Points.prototype.isPoints = true; function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { @@ -28282,7 +28336,7 @@ class EdgesGeometry extends BufferGeometry { const precisionPoints = 4; const precision = Math.pow( 10, precisionPoints ); - const thresholdDot = Math.cos( MathUtils.DEG2RAD * thresholdAngle ); + const thresholdDot = Math.cos( DEG2RAD * thresholdAngle ); const indexAttr = geometry.getIndex(); const positionAttr = geometry.getAttribute( 'position' ); @@ -29183,11 +29237,11 @@ function signedArea( data, start, end, dim ) { } -const ShapeUtils = { +class ShapeUtils { // calculate area of the contour polygon - area: function ( contour ) { + static area( contour ) { const n = contour.length; let a = 0.0; @@ -29200,15 +29254,15 @@ const ShapeUtils = { return a * 0.5; - }, + } - isClockWise: function ( pts ) { + static isClockWise( pts ) { return ShapeUtils.area( pts ) < 0; - }, + } - triangulateShape: function ( contour, holes ) { + static triangulateShape( contour, holes ) { const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] const holeIndices = []; // array of hole indices @@ -29247,7 +29301,7 @@ const ShapeUtils = { } -}; +} function removeDupEndPts( points ) { @@ -30100,7 +30154,7 @@ class LatheGeometry extends BufferGeometry { // clamp phiLength so it's in range of [ 0, 2PI ] - phiLength = MathUtils.clamp( phiLength, 0, Math.PI * 2 ); + phiLength = clamp( phiLength, 0, Math.PI * 2 ); // buffers @@ -30256,128 +30310,129 @@ class OctahedronGeometry extends PolyhedronGeometry { * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html */ -function ParametricGeometry( func, slices, stacks ) { +class ParametricGeometry extends BufferGeometry { + + constructor( func, slices, stacks ) { - BufferGeometry.call( this ); + super(); - this.type = 'ParametricGeometry'; + this.type = 'ParametricGeometry'; - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; + this.parameters = { + func: func, + slices: slices, + stacks: stacks + }; - // buffers + // buffers - const indices = []; - const vertices = []; - const normals = []; - const uvs = []; + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; - const EPS = 0.00001; + const EPS = 0.00001; - const normal = new Vector3(); + const normal = new Vector3(); - const p0 = new Vector3(), p1 = new Vector3(); - const pu = new Vector3(), pv = new Vector3(); + const p0 = new Vector3(), p1 = new Vector3(); + const pu = new Vector3(), pv = new Vector3(); - if ( func.length < 3 ) { + if ( func.length < 3 ) { - console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' ); + console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' ); - } + } - // generate vertices, normals and uvs + // generate vertices, normals and uvs - const sliceCount = slices + 1; + const sliceCount = slices + 1; - for ( let i = 0; i <= stacks; i ++ ) { + for ( let i = 0; i <= stacks; i ++ ) { - const v = i / stacks; + const v = i / stacks; - for ( let j = 0; j <= slices; j ++ ) { + for ( let j = 0; j <= slices; j ++ ) { - const u = j / slices; + const u = j / slices; - // vertex + // vertex - func( u, v, p0 ); - vertices.push( p0.x, p0.y, p0.z ); + func( u, v, p0 ); + vertices.push( p0.x, p0.y, p0.z ); - // normal + // normal - // approximate tangent vectors via finite differences + // approximate tangent vectors via finite differences - if ( u - EPS >= 0 ) { + if ( u - EPS >= 0 ) { - func( u - EPS, v, p1 ); - pu.subVectors( p0, p1 ); + func( u - EPS, v, p1 ); + pu.subVectors( p0, p1 ); - } else { + } else { - func( u + EPS, v, p1 ); - pu.subVectors( p1, p0 ); + func( u + EPS, v, p1 ); + pu.subVectors( p1, p0 ); - } + } - if ( v - EPS >= 0 ) { + if ( v - EPS >= 0 ) { - func( u, v - EPS, p1 ); - pv.subVectors( p0, p1 ); + func( u, v - EPS, p1 ); + pv.subVectors( p0, p1 ); - } else { + } else { - func( u, v + EPS, p1 ); - pv.subVectors( p1, p0 ); + func( u, v + EPS, p1 ); + pv.subVectors( p1, p0 ); - } + } - // cross product of tangent vectors returns surface normal + // cross product of tangent vectors returns surface normal + + normal.crossVectors( pu, pv ).normalize(); + normals.push( normal.x, normal.y, normal.z ); - normal.crossVectors( pu, pv ).normalize(); - normals.push( normal.x, normal.y, normal.z ); + // uv - // uv + uvs.push( u, v ); - uvs.push( u, v ); + } } - } + // generate indices - // generate indices + for ( let i = 0; i < stacks; i ++ ) { - for ( let i = 0; i < stacks; i ++ ) { + for ( let j = 0; j < slices; j ++ ) { - for ( let j = 0; j < slices; j ++ ) { + const a = i * sliceCount + j; + const b = i * sliceCount + j + 1; + const c = ( i + 1 ) * sliceCount + j + 1; + const d = ( i + 1 ) * sliceCount + j; - const a = i * sliceCount + j; - const b = i * sliceCount + j + 1; - const c = ( i + 1 ) * sliceCount + j + 1; - const d = ( i + 1 ) * sliceCount + j; + // faces one and two - // faces one and two + indices.push( a, b, d ); + indices.push( b, c, d ); - indices.push( a, b, d ); - indices.push( b, c, d ); + } } - } + // build geometry - // build geometry + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - this.setIndex( indices ); - this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + } } -ParametricGeometry.prototype = Object.create( BufferGeometry.prototype ); -ParametricGeometry.prototype.constructor = ParametricGeometry; - class RingGeometry extends BufferGeometry { constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) { @@ -31512,134 +31567,135 @@ RawShaderMaterial.prototype.isRawShaderMaterial = true; * } */ -function MeshStandardMaterial( parameters ) { +class MeshStandardMaterial extends Material { - Material.call( this ); + constructor( parameters ) { - this.defines = { 'STANDARD': '' }; + super(); - this.type = 'MeshStandardMaterial'; + this.defines = { 'STANDARD': '' }; - this.color = new Color( 0xffffff ); // diffuse - this.roughness = 1.0; - this.metalness = 0.0; + this.type = 'MeshStandardMaterial'; - this.map = null; + this.color = new Color( 0xffffff ); // diffuse + this.roughness = 1.0; + this.metalness = 0.0; - this.lightMap = null; - this.lightMapIntensity = 1.0; + this.map = null; - this.aoMap = null; - this.aoMapIntensity = 1.0; + this.lightMap = null; + this.lightMapIntensity = 1.0; - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; + this.aoMap = null; + this.aoMapIntensity = 1.0; - this.bumpMap = null; - this.bumpScale = 1; + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; - this.normalMap = null; - this.normalMapType = TangentSpaceNormalMap; - this.normalScale = new Vector2( 1, 1 ); + this.bumpMap = null; + this.bumpScale = 1; - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); - this.roughnessMap = null; + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; - this.metalnessMap = null; + this.roughnessMap = null; - this.alphaMap = null; + this.metalnessMap = null; - this.envMap = null; - this.envMapIntensity = 1.0; + this.alphaMap = null; - this.refractionRatio = 0.98; + this.envMap = null; + this.envMapIntensity = 1.0; - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; + this.refractionRatio = 0.98; - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + + this.skinning = false; + this.morphTargets = false; + this.morphNormals = false; - this.flatShading = false; + this.flatShading = false; - this.vertexTangents = false; + this.vertexTangents = false; - this.setValues( parameters ); + this.setValues( parameters ); -} + } -MeshStandardMaterial.prototype = Object.create( Material.prototype ); -MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; + copy( source ) { -MeshStandardMaterial.prototype.isMeshStandardMaterial = true; + super.copy( source ); -MeshStandardMaterial.prototype.copy = function ( source ) { + this.defines = { 'STANDARD': '' }; - Material.prototype.copy.call( this, source ); + this.color.copy( source.color ); + this.roughness = source.roughness; + this.metalness = source.metalness; - this.defines = { 'STANDARD': '' }; + this.map = source.map; - this.color.copy( source.color ); - this.roughness = source.roughness; - this.metalness = source.metalness; + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; - this.map = source.map; + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; - this.normalMap = source.normalMap; - this.normalMapType = source.normalMapType; - this.normalScale.copy( source.normalScale ); + this.roughnessMap = source.roughnessMap; - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; + this.metalnessMap = source.metalnessMap; - this.roughnessMap = source.roughnessMap; + this.alphaMap = source.alphaMap; - this.metalnessMap = source.metalnessMap; + this.envMap = source.envMap; + this.envMapIntensity = source.envMapIntensity; - this.alphaMap = source.alphaMap; + this.refractionRatio = source.refractionRatio; - this.envMap = source.envMap; - this.envMapIntensity = source.envMapIntensity; + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; - this.refractionRatio = source.refractionRatio; + this.skinning = source.skinning; + this.morphTargets = source.morphTargets; + this.morphNormals = source.morphNormals; - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; + this.flatShading = source.flatShading; - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; + this.vertexTangents = source.vertexTangents; - this.flatShading = source.flatShading; + return this; - this.vertexTangents = source.vertexTangents; + } - return this; +} -}; +MeshStandardMaterial.prototype.isMeshStandardMaterial = true; /** * parameters = { @@ -31660,91 +31716,92 @@ MeshStandardMaterial.prototype.copy = function ( source ) { * } */ -function MeshPhysicalMaterial( parameters ) { +class MeshPhysicalMaterial extends MeshStandardMaterial { - MeshStandardMaterial.call( this ); + constructor( parameters ) { - this.defines = { + super(); - 'STANDARD': '', - 'PHYSICAL': '' + this.defines = { - }; + 'STANDARD': '', + 'PHYSICAL': '' - this.type = 'MeshPhysicalMaterial'; + }; - this.clearcoat = 0.0; - this.clearcoatMap = null; - this.clearcoatRoughness = 0.0; - this.clearcoatRoughnessMap = null; - this.clearcoatNormalScale = new Vector2( 1, 1 ); - this.clearcoatNormalMap = null; + this.type = 'MeshPhysicalMaterial'; - this.reflectivity = 0.5; // maps to F0 = 0.04 + this.clearcoat = 0.0; + this.clearcoatMap = null; + this.clearcoatRoughness = 0.0; + this.clearcoatRoughnessMap = null; + this.clearcoatNormalScale = new Vector2( 1, 1 ); + this.clearcoatNormalMap = null; - Object.defineProperty( this, 'ior', { - get: function () { + this.reflectivity = 0.5; // maps to F0 = 0.04 - return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity ); + Object.defineProperty( this, 'ior', { + get: function () { - }, - set: function ( ior ) { + return ( 1 + 0.4 * this.reflectivity ) / ( 1 - 0.4 * this.reflectivity ); - this.reflectivity = MathUtils.clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 ); + }, + set: function ( ior ) { - } - } ); + this.reflectivity = clamp( 2.5 * ( ior - 1 ) / ( ior + 1 ), 0, 1 ); - this.sheen = null; // null will disable sheen bsdf + } + } ); - this.transmission = 0.0; - this.transmissionMap = null; + this.sheen = null; // null will disable sheen bsdf - this.setValues( parameters ); + this.transmission = 0.0; + this.transmissionMap = null; -} + this.setValues( parameters ); -MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); -MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; + } -MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; + copy( source ) { -MeshPhysicalMaterial.prototype.copy = function ( source ) { + super.copy( source ); - MeshStandardMaterial.prototype.copy.call( this, source ); + this.defines = { - this.defines = { + 'STANDARD': '', + 'PHYSICAL': '' - 'STANDARD': '', - 'PHYSICAL': '' + }; - }; + this.clearcoat = source.clearcoat; + this.clearcoatMap = source.clearcoatMap; + this.clearcoatRoughness = source.clearcoatRoughness; + this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; + this.clearcoatNormalMap = source.clearcoatNormalMap; + this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); - this.clearcoat = source.clearcoat; - this.clearcoatMap = source.clearcoatMap; - this.clearcoatRoughness = source.clearcoatRoughness; - this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; - this.clearcoatNormalMap = source.clearcoatNormalMap; - this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); + this.reflectivity = source.reflectivity; - this.reflectivity = source.reflectivity; + if ( source.sheen ) { - if ( source.sheen ) { + this.sheen = ( this.sheen || new Color() ).copy( source.sheen ); - this.sheen = ( this.sheen || new Color() ).copy( source.sheen ); + } else { - } else { + this.sheen = null; - this.sheen = null; + } - } + this.transmission = source.transmission; + this.transmissionMap = source.transmissionMap; - this.transmission = source.transmission; - this.transmissionMap = source.transmissionMap; + return this; - return this; + } -}; +} + +MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; /** * parameters = { @@ -32817,21 +32874,24 @@ const AnimationUtils = { * */ -function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +class Interpolant { - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - this.resultBuffer = resultBuffer !== undefined ? - resultBuffer : new sampleValues.constructor( sampleSize ); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; -} + this.resultBuffer = resultBuffer !== undefined ? + resultBuffer : new sampleValues.constructor( sampleSize ); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; -Object.assign( Interpolant.prototype, { + this.settings = null; + this.DefaultSettings_ = {}; - evaluate: function ( t ) { + } + + evaluate( t ) { const pp = this.parameterPositions; let i1 = this._cachedIndex, @@ -32989,22 +33049,15 @@ Object.assign( Interpolant.prototype, { return this.interpolate_( i1, t0, t, t1 ); - }, - - settings: null, // optional, subclass-specific settings structure - // Note: The indirection allows central control of many interpolants. - - // --- Protected interface - - DefaultSettings_: {}, + } - getSettings_: function () { + getSettings_() { return this.settings || this.DefaultSettings_; - }, + } - copySampleValue_: function ( index ) { + copySampleValue_( index ) { // copies a sample value to the result buffer @@ -33021,35 +33074,29 @@ Object.assign( Interpolant.prototype, { return result; - }, + } // Template methods for derived classes: - interpolate_: function ( /* i1, t0, t, t1 */ ) { + interpolate_( /* i1, t0, t, t1 */ ) { throw new Error( 'call to abstract method' ); // implementations shall return this.resultBuffer - }, + } - intervalChanged_: function ( /* i1, t0, t1 */ ) { + intervalChanged_( /* i1, t0, t1 */ ) { // empty } -} ); - -// DECLARE ALIAS AFTER assign prototype -Object.assign( Interpolant.prototype, { - - //( 0, t, t0 ), returns this.resultBuffer - beforeStart_: Interpolant.prototype.copySampleValue_, +} - //( N-1, tN-1, t ), returns this.resultBuffer - afterEnd_: Interpolant.prototype.copySampleValue_, +// ALIAS DEFINITIONS -} ); +Interpolant.prototype.beforeStart_ = Interpolant.prototype.copySampleValue_; +Interpolant.prototype.afterEnd_ = Interpolant.prototype.copySampleValue_; /** * Fast and simple cubic spline interpolant. @@ -33059,29 +33106,27 @@ Object.assign( Interpolant.prototype, { * over their parameter interval. */ -function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +class CubicInterpolant extends Interpolant { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - this._weightPrev = - 0; - this._offsetPrev = - 0; - this._weightNext = - 0; - this._offsetNext = - 0; - -} + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); -CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + this._weightPrev = - 0; + this._offsetPrev = - 0; + this._weightNext = - 0; + this._offsetNext = - 0; - constructor: CubicInterpolant, + this.DefaultSettings_ = { - DefaultSettings_: { + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding + }; - }, + } - intervalChanged_: function ( i1, t0, t1 ) { + intervalChanged_( i1, t0, t1 ) { const pp = this.parameterPositions; let iPrev = i1 - 2, @@ -33158,9 +33203,9 @@ CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype this._offsetPrev = iPrev * stride; this._offsetNext = iNext * stride; - }, + } - interpolate_: function ( i1, t0, t, t1 ) { + interpolate_( i1, t0, t, t1 ) { const result = this.resultBuffer, values = this.sampleValues, @@ -33197,19 +33242,17 @@ CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype } -} ); - -function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +} - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); +class LinearInterpolant extends Interpolant { -} + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { -LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - constructor: LinearInterpolant, + } - interpolate_: function ( i1, t0, t, t1 ) { + interpolate_( i1, t0, t, t1 ) { const result = this.resultBuffer, values = this.sampleValues, @@ -33233,7 +33276,7 @@ LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototyp } -} ); +} /** * @@ -33241,23 +33284,21 @@ LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototyp * the parameter. */ -function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +class DiscreteInterpolant extends Interpolant { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { -} + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); -DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { - - constructor: DiscreteInterpolant, + } - interpolate_: function ( i1 /*, t0, t, t1 */ ) { + interpolate_( i1 /*, t0, t, t1 */ ) { return this.copySampleValue_( i1 - 1 ); } -} ); +} class KeyframeTrack { @@ -33739,17 +33780,15 @@ NumberKeyframeTrack.prototype.ValueTypeName = 'number'; * Spherical linear unit quaternion interpolant. */ -function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +class QuaternionLinearInterpolant extends Interpolant { - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - -} + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { -QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - constructor: QuaternionLinearInterpolant, + } - interpolate_: function ( i1, t0, t, t1 ) { + interpolate_( i1, t0, t, t1 ) { const result = this.resultBuffer, values = this.sampleValues, @@ -33769,7 +33808,7 @@ QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolan } -} ); +} /** * A Track of quaternion keyframe values. @@ -33816,7 +33855,7 @@ class AnimationClip { this.duration = duration; this.blendMode = blendMode; - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); // this means it should figure out its duration by scanning the tracks if ( this.duration < 0 ) { @@ -34308,160 +34347,164 @@ const Cache = { }; -function LoadingManager( onLoad, onProgress, onError ) { +class LoadingManager { - const scope = this; + constructor( onLoad, onProgress, onError ) { - let isLoading = false; - let itemsLoaded = 0; - let itemsTotal = 0; - let urlModifier = undefined; - const handlers = []; + const scope = this; + + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; - // Refer to #5689 for the reason why we don't set .onStart - // in the constructor + // Refer to #5689 for the reason why we don't set .onStart + // in the constructor - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; - this.itemStart = function ( url ) { + this.itemStart = function ( url ) { - itemsTotal ++; + itemsTotal ++; - if ( isLoading === false ) { + if ( isLoading === false ) { - if ( scope.onStart !== undefined ) { + if ( scope.onStart !== undefined ) { - scope.onStart( url, itemsLoaded, itemsTotal ); + scope.onStart( url, itemsLoaded, itemsTotal ); + + } } - } + isLoading = true; - isLoading = true; + }; - }; + this.itemEnd = function ( url ) { - this.itemEnd = function ( url ) { + itemsLoaded ++; - itemsLoaded ++; + if ( scope.onProgress !== undefined ) { - if ( scope.onProgress !== undefined ) { + scope.onProgress( url, itemsLoaded, itemsTotal ); - scope.onProgress( url, itemsLoaded, itemsTotal ); + } - } + if ( itemsLoaded === itemsTotal ) { - if ( itemsLoaded === itemsTotal ) { + isLoading = false; - isLoading = false; + if ( scope.onLoad !== undefined ) { - if ( scope.onLoad !== undefined ) { + scope.onLoad(); - scope.onLoad(); + } } - } + }; - }; + this.itemError = function ( url ) { - this.itemError = function ( url ) { + if ( scope.onError !== undefined ) { - if ( scope.onError !== undefined ) { + scope.onError( url ); - scope.onError( url ); + } - } + }; - }; + this.resolveURL = function ( url ) { - this.resolveURL = function ( url ) { + if ( urlModifier ) { - if ( urlModifier ) { + return urlModifier( url ); - return urlModifier( url ); + } - } + return url; - return url; + }; - }; + this.setURLModifier = function ( transform ) { - this.setURLModifier = function ( transform ) { + urlModifier = transform; - urlModifier = transform; + return this; - return this; + }; - }; + this.addHandler = function ( regex, loader ) { - this.addHandler = function ( regex, loader ) { + handlers.push( regex, loader ); - handlers.push( regex, loader ); + return this; - return this; + }; - }; + this.removeHandler = function ( regex ) { - this.removeHandler = function ( regex ) { + const index = handlers.indexOf( regex ); - const index = handlers.indexOf( regex ); + if ( index !== - 1 ) { - if ( index !== - 1 ) { + handlers.splice( index, 2 ); - handlers.splice( index, 2 ); + } - } + return this; - return this; + }; - }; + this.getHandler = function ( file ) { - this.getHandler = function ( file ) { + for ( let i = 0, l = handlers.length; i < l; i += 2 ) { - for ( let i = 0, l = handlers.length; i < l; i += 2 ) { + const regex = handlers[ i ]; + const loader = handlers[ i + 1 ]; - const regex = handlers[ i ]; - const loader = handlers[ i + 1 ]; + if ( regex.global ) regex.lastIndex = 0; // see #17920 - if ( regex.global ) regex.lastIndex = 0; // see #17920 + if ( regex.test( file ) ) { - if ( regex.test( file ) ) { + return loader; - return loader; + } } - } + return null; - return null; + }; - }; + } } const DefaultLoadingManager = new LoadingManager(); -function Loader( manager ) { +class Loader { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + constructor( manager ) { - this.crossOrigin = 'anonymous'; - this.withCredentials = false; - this.path = ''; - this.resourcePath = ''; - this.requestHeader = {}; + this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; -} + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; -Object.assign( Loader.prototype, { + } - load: function ( /* url, onLoad, onProgress, onError */ ) {}, + load( /* url, onLoad, onProgress, onError */ ) {} - loadAsync: function ( url, onProgress ) { + loadAsync( url, onProgress ) { const scope = this; @@ -34471,60 +34514,58 @@ Object.assign( Loader.prototype, { } ); - }, + } - parse: function ( /* data */ ) {}, + parse( /* data */ ) {} - setCrossOrigin: function ( crossOrigin ) { + setCrossOrigin( crossOrigin ) { this.crossOrigin = crossOrigin; return this; - }, + } - setWithCredentials: function ( value ) { + setWithCredentials( value ) { this.withCredentials = value; return this; - }, + } - setPath: function ( path ) { + setPath( path ) { this.path = path; return this; - }, + } - setResourcePath: function ( resourcePath ) { + setResourcePath( resourcePath ) { this.resourcePath = resourcePath; return this; - }, + } - setRequestHeader: function ( requestHeader ) { + setRequestHeader( requestHeader ) { this.requestHeader = requestHeader; return this; } -} ); +} const loading = {}; -function FileLoader( manager ) { +class FileLoader extends Loader { - Loader.call( this, manager ); - -} + constructor( manager ) { -FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + super( manager ); - constructor: FileLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { if ( url === undefined ) url = ''; @@ -34788,23 +34829,23 @@ FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return request; - }, + } - setResponseType: function ( value ) { + setResponseType( value ) { this.responseType = value; return this; - }, + } - setMimeType: function ( value ) { + setMimeType( value ) { this.mimeType = value; return this; } -} ); +} class AnimationLoader extends Loader { @@ -34872,17 +34913,15 @@ class AnimationLoader extends Loader { * Sub classes have to implement the parse() method which will be used in load(). */ -function CompressedTextureLoader( manager ) { +class CompressedTextureLoader extends Loader { - Loader.call( this, manager ); - -} + constructor( manager ) { -CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + super( manager ); - constructor: CompressedTextureLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { const scope = this; @@ -34993,7 +35032,7 @@ CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototy } -} ); +} class ImageLoader extends Loader { @@ -35131,17 +35170,15 @@ class CubeTextureLoader extends Loader { * Sub classes have to implement the parse() method which will be used in load(). */ -function DataTextureLoader( manager ) { +class DataTextureLoader extends Loader { - Loader.call( this, manager ); - -} + constructor( manager ) { -DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + super( manager ); - constructor: DataTextureLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { const scope = this; @@ -35232,19 +35269,17 @@ DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), } -} ); - -function TextureLoader( manager ) { +} - Loader.call( this, manager ); +class TextureLoader extends Loader { -} + constructor( manager ) { -TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + super( manager ); - constructor: TextureLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { const texture = new Texture(); @@ -35274,7 +35309,7 @@ TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} /** * Extensible curve object. @@ -35306,39 +35341,39 @@ TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * **/ -function Curve() { +class Curve { - this.type = 'Curve'; + constructor() { - this.arcLengthDivisions = 200; + this.type = 'Curve'; -} + this.arcLengthDivisions = 200; -Object.assign( Curve.prototype, { + } // Virtual base class method to overwrite and implement in subclasses // - t [0 .. 1] - getPoint: function ( /* t, optionalTarget */ ) { + getPoint( /* t, optionalTarget */ ) { console.warn( 'THREE.Curve: .getPoint() not implemented.' ); return null; - }, + } // Get point at relative position in curve according to arc length // - u [0 .. 1] - getPointAt: function ( u, optionalTarget ) { + getPointAt( u, optionalTarget ) { const t = this.getUtoTmapping( u ); return this.getPoint( t, optionalTarget ); - }, + } // Get sequence of points using getPoint( t ) - getPoints: function ( divisions = 5 ) { + getPoints( divisions = 5 ) { const points = []; @@ -35350,11 +35385,11 @@ Object.assign( Curve.prototype, { return points; - }, + } // Get sequence of points using getPointAt( u ) - getSpacedPoints: function ( divisions = 5 ) { + getSpacedPoints( divisions = 5 ) { const points = []; @@ -35366,22 +35401,20 @@ Object.assign( Curve.prototype, { return points; - }, + } // Get total curve arc length - getLength: function () { + getLength() { const lengths = this.getLengths(); return lengths[ lengths.length - 1 ]; - }, + } // Get list of cumulative segment lengths - getLengths: function ( divisions ) { - - if ( divisions === undefined ) divisions = this.arcLengthDivisions; + getLengths( divisions = this.arcLengthDivisions ) { if ( this.cacheArcLengths && ( this.cacheArcLengths.length === divisions + 1 ) && @@ -35412,18 +35445,18 @@ Object.assign( Curve.prototype, { return cache; // { sums: cache, sum: sum }; Sum is in the last element. - }, + } - updateArcLengths: function () { + updateArcLengths() { this.needsUpdate = true; this.getLengths(); - }, + } // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant - getUtoTmapping: function ( u, distance ) { + getUtoTmapping( u, distance ) { const arcLengths = this.getLengths(); @@ -35496,14 +35529,14 @@ Object.assign( Curve.prototype, { return t; - }, + } // Returns a unit vector tangent at t // In case any sub curve does not implement its tangent derivation, // 2 points a small delta apart will be used to find its gradient // which seems to give a reasonable approximation - getTangent: function ( t, optionalTarget ) { + getTangent( t, optionalTarget ) { const delta = 0.0001; let t1 = t - delta; @@ -35523,16 +35556,16 @@ Object.assign( Curve.prototype, { return tangent; - }, + } - getTangentAt: function ( u, optionalTarget ) { + getTangentAt( u, optionalTarget ) { const t = this.getUtoTmapping( u ); return this.getTangent( t, optionalTarget ); - }, + } - computeFrenetFrames: function ( segments, closed ) { + computeFrenetFrames( segments, closed ) { // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf @@ -35606,7 +35639,7 @@ Object.assign( Curve.prototype, { vec.normalize(); - const theta = Math.acos( MathUtils.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors + const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); @@ -35620,7 +35653,7 @@ Object.assign( Curve.prototype, { if ( closed === true ) { - let theta = Math.acos( MathUtils.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); + let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); theta /= segments; if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { @@ -35645,23 +35678,23 @@ Object.assign( Curve.prototype, { binormals: binormals }; - }, + } - clone: function () { + clone() { return new this.constructor().copy( this ); - }, + } - copy: function ( source ) { + copy( source ) { this.arcLengthDivisions = source.arcLengthDivisions; return this; - }, + } - toJSON: function () { + toJSON() { const data = { metadata: { @@ -35676,9 +35709,9 @@ Object.assign( Curve.prototype, { return data; - }, + } - fromJSON: function ( json ) { + fromJSON( json ) { this.arcLengthDivisions = json.arcLengthDivisions; @@ -35686,7 +35719,7 @@ Object.assign( Curve.prototype, { } -} ); +} class EllipseCurve extends Curve { @@ -37167,7 +37200,7 @@ class Shape extends Path { super( points ); - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); this.type = 'Shape'; @@ -37271,6 +37304,12 @@ class Light extends Object3D { } + dispose() { + + // Empty here in base class; some subclasses override. + + } + copy( source ) { super.copy( source ); @@ -37422,6 +37461,22 @@ class LightShadow { } + dispose() { + + if ( this.map ) { + + this.map.dispose(); + + } + + if ( this.mapPass ) { + + this.mapPass.dispose(); + + } + + } + copy( source ) { this.camera = source.camera.clone(); @@ -37473,7 +37528,7 @@ class SpotLightShadow extends LightShadow { const camera = this.camera; - const fov = MathUtils.RAD2DEG * 2 * light.angle * this.focus; + const fov = RAD2DEG * 2 * light.angle * this.focus; const aspect = this.mapSize.width / this.mapSize.height; const far = light.distance || camera.far; @@ -37542,6 +37597,12 @@ class SpotLight extends Light { } + dispose() { + + this.shadow.dispose(); + + } + copy( source ) { super.copy( source ); @@ -37682,6 +37743,12 @@ class PointLight extends Light { } + dispose() { + + this.shadow.dispose(); + + } + copy( source ) { super.copy( source ); @@ -37812,7 +37879,7 @@ class OrthographicCamera extends Camera { toJSON( meta ) { - const data = Object3D.prototype.toJSON.call( this, meta ); + const data = super.toJSON( meta ); data.object.zoom = this.zoom; data.object.left = this.left; @@ -37861,6 +37928,12 @@ class DirectionalLight extends Light { } + dispose() { + + this.shadow.dispose(); + + } + copy( source ) { super.copy( source ); @@ -38499,9 +38572,9 @@ class MaterialLoader extends Loader { } -const LoaderUtils = { +class LoaderUtils { - decodeText: function ( array ) { + static decodeText( array ) { if ( typeof TextDecoder !== 'undefined' ) { @@ -38533,9 +38606,9 @@ const LoaderUtils = { } - }, + } - extractUrlBase: function ( url ) { + static extractUrlBase( url ) { const index = url.lastIndexOf( '/' ); @@ -38545,42 +38618,38 @@ const LoaderUtils = { } -}; - -function InstancedBufferGeometry() { - - BufferGeometry.call( this ); +} - this.type = 'InstancedBufferGeometry'; - this.instanceCount = Infinity; +class InstancedBufferGeometry extends BufferGeometry { -} + constructor() { -InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), { + super(); - constructor: InstancedBufferGeometry, + this.type = 'InstancedBufferGeometry'; + this.instanceCount = Infinity; - isInstancedBufferGeometry: true, + } - copy: function ( source ) { + copy( source ) { - BufferGeometry.prototype.copy.call( this, source ); + super.copy( source ); this.instanceCount = source.instanceCount; return this; - }, + } - clone: function () { + clone() { return new this.constructor().copy( this ); - }, + } - toJSON: function () { + toJSON() { - const data = BufferGeometry.prototype.toJSON.call( this ); + const data = super.toJSON( this ); data.instanceCount = this.instanceCount; @@ -38590,45 +38659,43 @@ InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry } -} ); - -function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) { +} - if ( typeof ( normalized ) === 'number' ) { +InstancedBufferGeometry.prototype.isInstancedBufferGeometry = true; - meshPerAttribute = normalized; +class InstancedBufferAttribute extends BufferAttribute { - normalized = false; + constructor( array, itemSize, normalized, meshPerAttribute ) { - console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' ); + if ( typeof ( normalized ) === 'number' ) { - } + meshPerAttribute = normalized; - BufferAttribute.call( this, array, itemSize, normalized ); + normalized = false; - this.meshPerAttribute = meshPerAttribute || 1; + console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' ); -} + } -InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), { + super( array, itemSize, normalized ); - constructor: InstancedBufferAttribute, + this.meshPerAttribute = meshPerAttribute || 1; - isInstancedBufferAttribute: true, + } - copy: function ( source ) { + copy( source ) { - BufferAttribute.prototype.copy.call( this, source ); + super.copy( source ); this.meshPerAttribute = source.meshPerAttribute; return this; - }, + } - toJSON: function () { + toJSON() { - const data = BufferAttribute.prototype.toJSON.call( this ); + const data = super.toJSON(); data.meshPerAttribute = this.meshPerAttribute; @@ -38638,7 +38705,9 @@ InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribu } -} ); +} + +InstancedBufferAttribute.prototype.isInstancedBufferAttribute = true; class BufferGeometryLoader extends Loader { @@ -39966,41 +40035,37 @@ const TEXTURE_FILTER = { LinearMipmapLinearFilter: LinearMipmapLinearFilter }; -function ImageBitmapLoader( manager ) { - - if ( typeof createImageBitmap === 'undefined' ) { +class ImageBitmapLoader extends Loader { - console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); - - } + constructor( manager ) { - if ( typeof fetch === 'undefined' ) { + super( manager ); - console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); + if ( typeof createImageBitmap === 'undefined' ) { - } + console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); - Loader.call( this, manager ); + } - this.options = { premultiplyAlpha: 'none' }; + if ( typeof fetch === 'undefined' ) { -} + console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); -ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + } - constructor: ImageBitmapLoader, + this.options = { premultiplyAlpha: 'none' }; - isImageBitmapLoader: true, + } - setOptions: function setOptions( options ) { + setOptions( options ) { this.options = options; return this; - }, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { if ( url === undefined ) url = ''; @@ -40061,7 +40126,9 @@ ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), } -} ); +} + +ImageBitmapLoader.prototype.isImageBitmapLoader = true; class ShapePath { @@ -40658,8 +40725,8 @@ class AmbientLightProbe extends LightProbe { AmbientLightProbe.prototype.isAmbientLightProbe = true; -const _eyeRight = new Matrix4(); -const _eyeLeft = new Matrix4(); +const _eyeRight = /*@__PURE__*/ new Matrix4(); +const _eyeLeft = /*@__PURE__*/ new Matrix4(); class StereoCamera { @@ -40715,7 +40782,7 @@ class StereoCamera { const projectionMatrix = camera.projectionMatrix.clone(); const eyeSepHalf = cache.eyeSep / 2; const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; - const ymax = ( cache.near * Math.tan( MathUtils.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; + const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; let xmin, xmax; // translate xOffset @@ -40754,9 +40821,9 @@ class StereoCamera { class Clock { - constructor( autoStart ) { + constructor( autoStart = true ) { - this.autoStart = ( autoStart !== undefined ) ? autoStart : true; + this.autoStart = autoStart; this.startTime = 0; this.oldTime = 0; @@ -41857,18 +41924,18 @@ const _trackRe = new RegExp( '' const _supportedObjectNames = [ 'material', 'materials', 'bones' ]; -function Composite( targetGroup, path, optionalParsedPath ) { +class Composite { - const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); + constructor( targetGroup, path, optionalParsedPath ) { - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_( path, parsedPath ); + const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); -} + this._targetGroup = targetGroup; + this._bindings = targetGroup.subscribe_( path, parsedPath ); -Object.assign( Composite.prototype, { + } - getValue: function ( array, offset ) { + getValue( array, offset ) { this.bind(); // bind all binding @@ -41878,9 +41945,9 @@ Object.assign( Composite.prototype, { // and only call .getValue on the first if ( binding !== undefined ) binding.getValue( array, offset ); - }, + } - setValue: function ( array, offset ) { + setValue( array, offset ) { const bindings = this._bindings; @@ -41890,9 +41957,9 @@ Object.assign( Composite.prototype, { } - }, + } - bind: function () { + bind() { const bindings = this._bindings; @@ -41902,9 +41969,9 @@ Object.assign( Composite.prototype, { } - }, + } - unbind: function () { + unbind() { const bindings = this._bindings; @@ -41916,25 +41983,32 @@ Object.assign( Composite.prototype, { } -} ); +} +// Note: This class uses a State pattern on a per-method basis: +// 'bind' sets 'this.getValue' / 'setValue' and shadows the +// prototype version of these methods with one that represents +// the bound state. When the property is not found, the methods +// become no-ops. +class PropertyBinding { -function PropertyBinding( rootNode, path, parsedPath ) { + constructor( rootNode, path, parsedPath ) { - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); + this.path = path; + this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); - this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; + this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; - this.rootNode = rootNode; + this.rootNode = rootNode; -} + // initial state of these methods that calls 'bind' + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; -Object.assign( PropertyBinding, { + } - Composite: Composite, - create: function ( root, path, parsedPath ) { + static create( root, path, parsedPath ) { if ( ! ( root && root.isAnimationObjectGroup ) ) { @@ -41946,7 +42020,7 @@ Object.assign( PropertyBinding, { } - }, + } /** * Replaces spaces with underscores and removes unsupported characters from @@ -41955,13 +42029,13 @@ Object.assign( PropertyBinding, { * @param {string} name Node name to be sanitized. * @return {string} */ - sanitizeNodeName: function ( name ) { + static sanitizeNodeName( name ) { return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); - }, + } - parseTrackName: function ( trackName ) { + static parseTrackName( trackName ) { const matches = _trackRe.exec( trackName ); @@ -42007,9 +42081,9 @@ Object.assign( PropertyBinding, { return results; - }, + } - findNode: function ( root, nodeName ) { + static findNode( root, nodeName ) { if ( ! nodeName || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { @@ -42069,204 +42143,166 @@ Object.assign( PropertyBinding, { } -} ); - -Object.assign( PropertyBinding.prototype, { // prototype, continued - // these are used to "bind" a nonexistent property - _getValue_unavailable: function () {}, - _setValue_unavailable: function () {}, - - BindingType: { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 - }, - - Versioning: { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 - }, - - GetterByBindingType: [ - - function getValue_direct( buffer, offset ) { + _getValue_unavailable() {} + _setValue_unavailable() {} - buffer[ offset ] = this.node[ this.propertyName ]; - - }, + // Getters - function getValue_array( buffer, offset ) { + _getValue_direct( buffer, offset ) { - const source = this.resolvedProperty; + buffer[ offset ] = this.node[ this.propertyName ]; - for ( let i = 0, n = source.length; i !== n; ++ i ) { - - buffer[ offset ++ ] = source[ i ]; - - } - - }, - - function getValue_arrayElement( buffer, offset ) { + } - buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; + _getValue_array( buffer, offset ) { - }, + const source = this.resolvedProperty; - function getValue_toArray( buffer, offset ) { + for ( let i = 0, n = source.length; i !== n; ++ i ) { - this.resolvedProperty.toArray( buffer, offset ); + buffer[ offset ++ ] = source[ i ]; } - ], + } - SetterByBindingTypeAndVersioning: [ + _getValue_arrayElement( buffer, offset ) { - [ - // Direct + buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; - function setValue_direct( buffer, offset ) { + } - this.targetObject[ this.propertyName ] = buffer[ offset ]; + _getValue_toArray( buffer, offset ) { - }, + this.resolvedProperty.toArray( buffer, offset ); - function setValue_direct_setNeedsUpdate( buffer, offset ) { + } - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + // Direct - }, + _setValue_direct( buffer, offset ) { - function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { + this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + } - } + _setValue_direct_setNeedsUpdate( buffer, offset ) { - ], [ + this.targetObject[ this.propertyName ] = buffer[ offset ]; + this.targetObject.needsUpdate = true; - // EntireArray + } - function setValue_array( buffer, offset ) { + _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { - const dest = this.resolvedProperty; + this.targetObject[ this.propertyName ] = buffer[ offset ]; + this.targetObject.matrixWorldNeedsUpdate = true; - for ( let i = 0, n = dest.length; i !== n; ++ i ) { + } - dest[ i ] = buffer[ offset ++ ]; + // EntireArray - } + _setValue_array( buffer, offset ) { - }, + const dest = this.resolvedProperty; - function setValue_array_setNeedsUpdate( buffer, offset ) { + for ( let i = 0, n = dest.length; i !== n; ++ i ) { - const dest = this.resolvedProperty; + dest[ i ] = buffer[ offset ++ ]; - for ( let i = 0, n = dest.length; i !== n; ++ i ) { + } - dest[ i ] = buffer[ offset ++ ]; + } - } + _setValue_array_setNeedsUpdate( buffer, offset ) { - this.targetObject.needsUpdate = true; + const dest = this.resolvedProperty; - }, + for ( let i = 0, n = dest.length; i !== n; ++ i ) { - function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { + dest[ i ] = buffer[ offset ++ ]; - const dest = this.resolvedProperty; + } - for ( let i = 0, n = dest.length; i !== n; ++ i ) { + this.targetObject.needsUpdate = true; - dest[ i ] = buffer[ offset ++ ]; + } - } + _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { - this.targetObject.matrixWorldNeedsUpdate = true; + const dest = this.resolvedProperty; - } + for ( let i = 0, n = dest.length; i !== n; ++ i ) { - ], [ + dest[ i ] = buffer[ offset ++ ]; - // ArrayElement + } - function setValue_arrayElement( buffer, offset ) { + this.targetObject.matrixWorldNeedsUpdate = true; - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + } - }, + // ArrayElement - function setValue_arrayElement_setNeedsUpdate( buffer, offset ) { + _setValue_arrayElement( buffer, offset ) { - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - }, + } - function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { + _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + this.targetObject.needsUpdate = true; - } + } - ], [ + _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { - // HasToFromArray + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + this.targetObject.matrixWorldNeedsUpdate = true; - function setValue_fromArray( buffer, offset ) { + } - this.resolvedProperty.fromArray( buffer, offset ); + // HasToFromArray - }, + _setValue_fromArray( buffer, offset ) { - function setValue_fromArray_setNeedsUpdate( buffer, offset ) { + this.resolvedProperty.fromArray( buffer, offset ); - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.needsUpdate = true; + } - }, + _setValue_fromArray_setNeedsUpdate( buffer, offset ) { - function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { + this.resolvedProperty.fromArray( buffer, offset ); + this.targetObject.needsUpdate = true; - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.matrixWorldNeedsUpdate = true; + } - } + _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { - ] + this.resolvedProperty.fromArray( buffer, offset ); + this.targetObject.matrixWorldNeedsUpdate = true; - ], + } - getValue: function getValue_unbound( targetArray, offset ) { + _getValue_unbound( targetArray, offset ) { this.bind(); this.getValue( targetArray, offset ); - // Note: This class uses a State pattern on a per-method basis: - // 'bind' sets 'this.getValue' / 'setValue' and shadows the - // prototype version of these methods with one that represents - // the bound state. When the property is not found, the methods - // become no-ops. - - }, + } - setValue: function getValue_unbound( sourceArray, offset ) { + _setValue_unbound( sourceArray, offset ) { this.bind(); this.setValue( sourceArray, offset ); - }, + } // create getter / setter pair for a property in the scene graph - bind: function () { + bind() { let targetObject = this.node; const parsedPath = this.parsedPath; @@ -42480,9 +42516,9 @@ Object.assign( PropertyBinding.prototype, { // prototype, continued this.getValue = this.GetterByBindingType[ bindingType ]; this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; - }, + } - unbind: function () { + unbind() { this.node = null; @@ -42493,16 +42529,65 @@ Object.assign( PropertyBinding.prototype, { // prototype, continued } -} ); +} -// DECLARE ALIAS AFTER assign prototype -Object.assign( PropertyBinding.prototype, { +PropertyBinding.Composite = Composite; - // initial state of these methods that calls 'bind' - _getValue_unbound: PropertyBinding.prototype.getValue, - _setValue_unbound: PropertyBinding.prototype.setValue, +PropertyBinding.prototype.BindingType = { + Direct: 0, + EntireArray: 1, + ArrayElement: 2, + HasFromToArray: 3 +}; -} ); +PropertyBinding.prototype.Versioning = { + None: 0, + NeedsUpdate: 1, + MatrixWorldNeedsUpdate: 2 +}; + +PropertyBinding.prototype.GetterByBindingType = [ + + PropertyBinding.prototype._getValue_direct, + PropertyBinding.prototype._getValue_array, + PropertyBinding.prototype._getValue_arrayElement, + PropertyBinding.prototype._getValue_toArray, + +]; + +PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ + + [ + // Direct + PropertyBinding.prototype._setValue_direct, + PropertyBinding.prototype._setValue_direct_setNeedsUpdate, + PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, + + ], [ + + // EntireArray + + PropertyBinding.prototype._setValue_array, + PropertyBinding.prototype._setValue_array_setNeedsUpdate, + PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, + + ], [ + + // ArrayElement + PropertyBinding.prototype._setValue_arrayElement, + PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, + PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, + + ], [ + + // HasToFromArray + PropertyBinding.prototype._setValue_fromArray, + PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, + PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, + + ] + +]; /** * @@ -42537,7 +42622,7 @@ class AnimationObjectGroup { constructor() { - this.uuid = MathUtils.generateUUID(); + this.uuid = generateUUID(); // cached objects followed by the active ones this._objects = Array.prototype.slice.call( arguments ); @@ -44362,43 +44447,39 @@ class Uniform { } -function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) { +class InstancedInterleavedBuffer extends InterleavedBuffer { - InterleavedBuffer.call( this, array, stride ); + constructor( array, stride, meshPerAttribute = 1 ) { - this.meshPerAttribute = meshPerAttribute || 1; + super( array, stride ); -} - -InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), { - - constructor: InstancedInterleavedBuffer, + this.meshPerAttribute = meshPerAttribute || 1; - isInstancedInterleavedBuffer: true, + } - copy: function ( source ) { + copy( source ) { - InterleavedBuffer.prototype.copy.call( this, source ); + super.copy( source ); this.meshPerAttribute = source.meshPerAttribute; return this; - }, + } - clone: function ( data ) { + clone( data ) { - const ib = InterleavedBuffer.prototype.clone.call( this, data ); + const ib = super.clone( data ); ib.meshPerAttribute = this.meshPerAttribute; return ib; - }, + } - toJSON: function ( data ) { + toJSON( data ) { - const json = InterleavedBuffer.prototype.toJSON.call( this, data ); + const json = super.toJSON( data ); json.isInstancedInterleavedBuffer = true; json.meshPerAttribute = this.meshPerAttribute; @@ -44407,139 +44488,98 @@ InstancedInterleavedBuffer.prototype = Object.assign( Object.create( Interleaved } -} ); - -function GLBufferAttribute( buffer, type, itemSize, elementSize, count ) { - - this.buffer = buffer; - this.type = type; - this.itemSize = itemSize; - this.elementSize = elementSize; - this.count = count; +} - this.version = 0; +InstancedInterleavedBuffer.prototype.isInstancedInterleavedBuffer = true; -} +class GLBufferAttribute { -Object.defineProperty( GLBufferAttribute.prototype, 'needsUpdate', { + constructor( buffer, type, itemSize, elementSize, count ) { - set: function ( value ) { + this.buffer = buffer; + this.type = type; + this.itemSize = itemSize; + this.elementSize = elementSize; + this.count = count; - if ( value === true ) this.version ++; + this.version = 0; } -} ); + set needsUpdate( value ) { -Object.assign( GLBufferAttribute.prototype, { + if ( value === true ) this.version ++; - isGLBufferAttribute: true, + } - setBuffer: function ( buffer ) { + setBuffer( buffer ) { this.buffer = buffer; return this; - }, + } - setType: function ( type, elementSize ) { + setType( type, elementSize ) { this.type = type; this.elementSize = elementSize; return this; - }, + } - setItemSize: function ( itemSize ) { + setItemSize( itemSize ) { this.itemSize = itemSize; return this; - }, + } - setCount: function ( count ) { + setCount( count ) { this.count = count; return this; - }, - -} ); - -function Raycaster( origin, direction, near = 0, far = Infinity ) { - - this.ray = new Ray( origin, direction ); - // direction is assumed to be normalized (for accurate distance calculations) - - this.near = near; - this.far = far; - this.camera = null; - this.layers = new Layers(); - - this.params = { - Mesh: {}, - Line: { threshold: 1 }, - LOD: {}, - Points: { threshold: 1 }, - Sprite: {} - }; - - Object.defineProperties( this.params, { - PointCloud: { - get: function () { - - console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); - return this.Points; - - } - } - } ); - -} - -function ascSort( a, b ) { - - return a.distance - b.distance; + } } -function intersectObject( object, raycaster, intersects, recursive ) { - - if ( object.layers.test( raycaster.layers ) ) { +GLBufferAttribute.prototype.isGLBufferAttribute = true; - object.raycast( raycaster, intersects ); +class Raycaster { - } - - if ( recursive === true ) { - - const children = object.children; - - for ( let i = 0, l = children.length; i < l; i ++ ) { + constructor( origin, direction, near = 0, far = Infinity ) { - intersectObject( children[ i ], raycaster, intersects, true ); + this.ray = new Ray( origin, direction ); + // direction is assumed to be normalized (for accurate distance calculations) - } + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); + + this.params = { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + }; } -} - -Object.assign( Raycaster.prototype, { - - set: function ( origin, direction ) { + set( origin, direction ) { // direction is assumed to be normalized (for accurate distance calculations) this.ray.set( origin, direction ); - }, + } - setFromCamera: function ( coords, camera ) { + setFromCamera( coords, camera ) { if ( camera && camera.isPerspectiveCamera ) { @@ -44559,9 +44599,9 @@ Object.assign( Raycaster.prototype, { } - }, + } - intersectObject: function ( object, recursive = false, intersects = [] ) { + intersectObject( object, recursive = false, intersects = [] ) { intersectObject( object, this, intersects, recursive ); @@ -44569,9 +44609,9 @@ Object.assign( Raycaster.prototype, { return intersects; - }, + } - intersectObjects: function ( objects, recursive = false, intersects = [] ) { + intersectObjects( objects, recursive = false, intersects = [] ) { for ( let i = 0, l = objects.length; i < l; i ++ ) { @@ -44585,7 +44625,35 @@ Object.assign( Raycaster.prototype, { } -} ); +} + +function ascSort( a, b ) { + + return a.distance - b.distance; + +} + +function intersectObject( object, raycaster, intersects, recursive ) { + + if ( object.layers.test( raycaster.layers ) ) { + + object.raycast( raycaster, intersects ); + + } + + if ( recursive === true ) { + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + intersectObject( children[ i ], raycaster, intersects, true ); + + } + + } + +} /** * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system @@ -44654,7 +44722,7 @@ class Spherical { } else { this.theta = Math.atan2( x, z ); - this.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) ); + this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) ); } @@ -45051,7 +45119,7 @@ class Line3 { if ( clampToLine ) { - t = MathUtils.clamp( t, 0, 1 ); + t = clamp( t, 0, 1 ); } @@ -45097,29 +45165,30 @@ class Line3 { } -function ImmediateRenderObject( material ) { +class ImmediateRenderObject extends Object3D { - Object3D.call( this ); + constructor( material ) { - this.material = material; - this.render = function ( /* renderCallback */ ) {}; + super(); - this.hasPositions = false; - this.hasNormals = false; - this.hasColors = false; - this.hasUvs = false; + this.material = material; + this.render = function ( /* renderCallback */ ) {}; - this.positionArray = null; - this.normalArray = null; - this.colorArray = null; - this.uvArray = null; + this.hasPositions = false; + this.hasNormals = false; + this.hasColors = false; + this.hasUvs = false; - this.count = 0; + this.positionArray = null; + this.normalArray = null; + this.colorArray = null; + this.uvArray = null; -} + this.count = 0; -ImmediateRenderObject.prototype = Object.create( Object3D.prototype ); -ImmediateRenderObject.prototype.constructor = ImmediateRenderObject; + } + +} ImmediateRenderObject.prototype.isImmediateRenderObject = true; @@ -45842,6 +45911,13 @@ class CameraHelper extends LineSegments { } + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + } @@ -46175,16 +46251,23 @@ class AxesHelper extends LineSegments { } + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + } const _floatView = new Float32Array( 1 ); const _int32View = new Int32Array( _floatView.buffer ); -const DataUtils = { +class DataUtils { // Converts float32 to float16 (stored as uint16 value). - toHalfFloat: function ( val ) { + static toHalfFloat( val ) { // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410 @@ -46233,7 +46316,7 @@ const DataUtils = { } -}; +} const LOD_MIN = 4; const LOD_MAX = 8; @@ -47556,29 +47639,6 @@ Line3.prototype.center = function ( optionalTarget ) { // -MathUtils.random16 = function () { - - console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' ); - return Math.random(); - -}; - -MathUtils.nearestPowerOfTwo = function ( value ) { - - console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' ); - return MathUtils.floorPowerOfTwo( value ); - -}; - -MathUtils.nextPowerOfTwo = function ( value ) { - - console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' ); - return MathUtils.ceilPowerOfTwo( value ); - -}; - -// - Matrix3.prototype.flattenToArrayOffset = function ( array, offset ) { console.warn( 'THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.' ); @@ -48066,23 +48126,6 @@ SkinnedMesh.prototype.initBones = function () { }; -Object.defineProperty( Curve.prototype, '__arcLengthDivisions', { - - get: function () { - - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - return this.arcLengthDivisions; - - }, - set: function ( value ) { - - console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); - this.arcLengthDivisions = value; - - } - -} ); - // PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) { @@ -48346,63 +48389,6 @@ Object.defineProperties( BufferGeometry.prototype, { } ); -Object.defineProperties( InstancedBufferGeometry.prototype, { - - maxInstancedCount: { - get: function () { - - console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' ); - return this.instanceCount; - - }, - set: function ( value ) { - - console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' ); - this.instanceCount = value; - - } - } - -} ); - -Object.defineProperties( Raycaster.prototype, { - - linePrecision: { - get: function () { - - console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' ); - return this.params.Line.threshold; - - }, - set: function ( value ) { - - console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' ); - this.params.Line.threshold = value; - - } - } - -} ); - -Object.defineProperties( InterleavedBuffer.prototype, { - - dynamic: { - get: function () { - - console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' ); - return this.usage === DynamicDrawUsage; - - }, - set: function ( value ) { - - console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' ); - this.setUsage( value ); - - } - } - -} ); - InterleavedBuffer.prototype.setDynamic = function ( value ) { console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' ); @@ -48524,25 +48510,6 @@ Object.defineProperties( Material.prototype, { } ); -Object.defineProperties( MeshPhysicalMaterial.prototype, { - - transparency: { - get: function () { - - console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' ); - return this.transmission; - - }, - set: function ( value ) { - - console.warn( 'THREE.MeshPhysicalMaterial: .transparency has been renamed to .transmission.' ); - this.transmission = value; - - } - } - -} ); - Object.defineProperties( ShaderMaterial.prototype, { derivatives: { diff --git a/docs/api/en/helpers/AxesHelper.html b/docs/api/en/helpers/AxesHelper.html index 0afc44c8a4ef2f..efe5fe9c0bd840 100644 --- a/docs/api/en/helpers/AxesHelper.html +++ b/docs/api/en/helpers/AxesHelper.html @@ -44,6 +44,11 @@

Properties

Methods

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

+

[method:AxesHelper dispose]()

+

+ Disposes of the internally-created [page:Line.material material] and [page:Line.geometry geometry] used by this helper. +

+

Source

diff --git a/docs/api/en/helpers/CameraHelper.html b/docs/api/en/helpers/CameraHelper.html index b4b5ce94438886..7b0c03dfb3f1a1 100644 --- a/docs/api/en/helpers/CameraHelper.html +++ b/docs/api/en/helpers/CameraHelper.html @@ -68,6 +68,10 @@

[property:Object matrixAutoUpdate]

Methods

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

+

[method:CameraHelper dispose]()

+

+ Disposes of the internally-created [page:Line.material material] and [page:Line.geometry geometry] used by this helper. +

[method:null update]()

Updates the helper based on the projectionMatrix of the camera.

diff --git a/docs/api/en/lights/DirectionalLight.html b/docs/api/en/lights/DirectionalLight.html index 60de56bc8c8a8c..3e65f6c2096c4b 100644 --- a/docs/api/en/lights/DirectionalLight.html +++ b/docs/api/en/lights/DirectionalLight.html @@ -117,6 +117,12 @@

Methods

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

+

[method:DirectionalLight dispose]()

+

+ Override of base class's [page:Light.dispose dispose]. + Disposes of this light's [page:DirectionalLightShadow shadow]. +

+

[method:DirectionalLight copy]( [param:DirectionalLight source] )

Copies value of all the properties from the [page:DirectionalLight source] to this diff --git a/docs/api/en/lights/Light.html b/docs/api/en/lights/Light.html index d94c58e6aec5af..5c02d037bddfa5 100644 --- a/docs/api/en/lights/Light.html +++ b/docs/api/en/lights/Light.html @@ -52,6 +52,10 @@

Methods

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

+

[method:Light dispose]()

+

+ Abstract dispose method for lights; implemented by subclasses that have disposable resources. +

[method:Light copy]( [param:Light source] )

diff --git a/docs/api/en/lights/PointLight.html b/docs/api/en/lights/PointLight.html index 10acb59049504c..46b5929fbe7a3a 100644 --- a/docs/api/en/lights/PointLight.html +++ b/docs/api/en/lights/PointLight.html @@ -105,6 +105,12 @@

Methods

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

+

[method:PointLight dispose]()

+

+ Override of base class's [page:Light.dispose dispose]. + Disposes of this light's [page:PointLightShadow shadow]. +

+

[method:PointLight copy]( [param:PointLight source] )

Copies value of all the properties from the [page:PointLight source] to this diff --git a/docs/api/en/lights/SpotLight.html b/docs/api/en/lights/SpotLight.html index 0f6581e9f5069e..481c244bd1329c 100644 --- a/docs/api/en/lights/SpotLight.html +++ b/docs/api/en/lights/SpotLight.html @@ -163,6 +163,12 @@

Methods

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

+

[method:SpotLight dispose]()

+

+ Override of base class's [page:Light.dispose dispose]. + Disposes of this light's [page:SpotLightShadow shadow]. +

+

[method:SpotLight copy]( [param:SpotLight source] )

Copies value of all the properties from the [page:SpotLight source] to this diff --git a/docs/api/en/lights/shadows/LightShadow.html b/docs/api/en/lights/shadows/LightShadow.html index 99ece9ced5ff96..b49f5595a64185 100644 --- a/docs/api/en/lights/shadows/LightShadow.html +++ b/docs/api/en/lights/shadows/LightShadow.html @@ -122,6 +122,11 @@

[method:number getViewportCount]()

Used internally by the renderer to get the number of viewports that need to be rendered for this shadow.

+

[method:LightShadow dispose]()

+

+ Disposes of this shadow's textures ([page:LightShadow.map map] and [page:LightShadow.mapPass mapPass]). +

+

[method:LightShadow copy]( [param:LightShadow source] )

Copies value of all the properties from the [page:LightShadow source] to this diff --git a/docs/api/en/math/Color.html b/docs/api/en/math/Color.html index 68c41951839c9e..adfdf427f88a46 100644 --- a/docs/api/en/math/Color.html +++ b/docs/api/en/math/Color.html @@ -310,7 +310,7 @@

[method:Color setStyle]( [param:String style] )

Translucent colors such as "rgba(255, 0, 0, 0.5)" and "hsla(0, 100%, 50%, 0.5)" are also accepted, but the alpha-channel coordinate will be discarded.

- Note that for X11 color names, multiple words such as Dark Orange become the string 'darkorange' (all lowercase). + Note that for X11 color names, multiple words such as Dark Orange become the string 'darkorange'.

[method:Color setColorName]( [param:String style] )

diff --git a/docs/api/en/objects/SkinnedMesh.html b/docs/api/en/objects/SkinnedMesh.html index ee22f2166750aa..94c0ae762e47f0 100644 --- a/docs/api/en/objects/SkinnedMesh.html +++ b/docs/api/en/objects/SkinnedMesh.html @@ -153,6 +153,11 @@

[method:null 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. +

+

Source

diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index 239621ad67803c..3135cb17b570c9 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -298,8 +298,8 @@

[method:null copyFramebufferToTexture]( [param:Vector2 position], [param:Tex

[method:null copyTextureToTexture]( [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )

Copies all pixels of a texture to an existing texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D WebGLRenderingContext.texSubImage2D].

-

[method:null copyTextureToTexture3D]( [param:Box3 sourceBox], [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )

-

Copies the pixels of a texture in the bounds '[page:Box3 sourceBox]' in the desination texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D].

+

[method:null copyTextureToTexture3D]( [param:Box3 sourceBox], [param:Vector3 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )

+

Copies the pixels of a texture in the bounds '[page:Box3 sourceBox]' in the destination texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D].

[method:null dispose]( )

Dispose of the current rendering context.

diff --git a/docs/api/zh/math/Color.html b/docs/api/zh/math/Color.html index 0ac3aef8414251..5ac4632fd177e9 100644 --- a/docs/api/zh/math/Color.html +++ b/docs/api/zh/math/Color.html @@ -303,7 +303,7 @@

[method:Color setStyle]( [param:String style] )

半透明颜色例如 "rgba(255, 0, 0, 0.5)" and "hsla(0, 100%, 50%, 0.5)" 也能支持, 但是alpha通道的值将会被丢弃。

- 注意,对于X11颜色名称,多个单词(如暗橙色)变成字符串“darkorange”(全部是小写字母)。 + 注意,对于X11颜色名称,多个单词(如暗橙色)变成字符串“darkorange”。

[method:Color setColorName]( [param:String style] )

diff --git a/docs/examples/en/controls/TrackballControls.html b/docs/examples/en/controls/TrackballControls.html index 0abfd056957e0a..19d2445832a1ed 100644 --- a/docs/examples/en/controls/TrackballControls.html +++ b/docs/examples/en/controls/TrackballControls.html @@ -126,7 +126,7 @@

[property:Camera object]

[property:Number panSpeed]

- The zoom speed. Default is *0.3*. + The pan speed. Default is *0.3*.

[property:Number rotateSpeed]

diff --git a/docs/manual/en/introduction/How-to-run-things-locally.html b/docs/manual/en/introduction/How-to-run-things-locally.html index c31731a449d18b..38b16eaab7cdbb 100644 --- a/docs/manual/en/introduction/How-to-run-things-locally.html +++ b/docs/manual/en/introduction/How-to-run-things-locally.html @@ -52,6 +52,7 @@

Plugins for popular code editors

Some code editors have plugins which will spawn a simple server on demand.

    +
  • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] for Visual Studio Code.
  • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] for Visual Studio Code.
  • [link:https://atom.io/packages/atom-live-server Live Server] for Atom.
@@ -64,6 +65,24 @@

Servez

+

Node.js five-server

+
+

Development server with live reload capability. To install:

+ +# Remove live-server (if you have it) +npm -g rm live-server + +# Install five-server +npm -g i five-server + +# Update five-server (from time to time) +npm -g i five-server@latest + + +

To run (from your local directory):

+ five-server . -p 8000 +
+

Node.js http-server

Node.js has a simple HTTP server package. To install:

diff --git a/editor/js/Editor.js b/editor/js/Editor.js index 6e41ba7f6f9b32..55b44f67ec27ed 100644 --- a/editor/js/Editor.js +++ b/editor/js/Editor.js @@ -41,7 +41,7 @@ function Editor() { transformModeChanged: new Signal(), snapChanged: new Signal(), spaceChanged: new Signal(), - rendererChanged: new Signal(), + rendererCreated: new Signal(), rendererUpdated: new Signal(), sceneBackgroundChanged: new Signal(), @@ -414,7 +414,7 @@ Editor.prototype = { } else if ( object.isSpotLight ) { - helper = new THREE.SpotLightHelper( object, 1 ); + helper = new THREE.SpotLightHelper( object ); } else if ( object.isHemisphereLight ) { diff --git a/editor/js/Loader.js b/editor/js/Loader.js index 5c2f5c774078f3..ae1d2989e1a5de 100644 --- a/editor/js/Loader.js +++ b/editor/js/Loader.js @@ -7,7 +7,7 @@ import { SetSceneCommand } from './commands/SetSceneCommand.js'; import { LoaderUtils } from './LoaderUtils.js'; -import { unzipSync, strFromU8 } from '../../examples/jsm/libs/fflate.module.min.js'; +import { unzipSync, strFromU8 } from '../../examples/jsm/libs/fflate.module.js'; function Loader( editor ) { diff --git a/editor/js/Menubar.File.js b/editor/js/Menubar.File.js index a0af8de75b7050..1e389aade0e791 100644 --- a/editor/js/Menubar.File.js +++ b/editor/js/Menubar.File.js @@ -1,6 +1,6 @@ import * as THREE from '../../build/three.module.js'; -import { zipSync, strToU8 } from '../../examples/jsm/libs/fflate.module.min.js'; +import { zipSync, strToU8 } from '../../examples/jsm/libs/fflate.module.js'; import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js'; diff --git a/editor/js/Script.js b/editor/js/Script.js index 677f420535488a..7c1584798ae002 100644 --- a/editor/js/Script.js +++ b/editor/js/Script.js @@ -48,7 +48,7 @@ function Script( editor ) { var renderer; - signals.rendererChanged.add( function ( newRenderer ) { + signals.rendererCreated.add( function ( newRenderer ) { renderer = newRenderer; diff --git a/editor/js/Sidebar.Project.Renderer.js b/editor/js/Sidebar.Project.Renderer.js index af0ac60c464b06..7a61258ff35ada 100644 --- a/editor/js/Sidebar.Project.Renderer.js +++ b/editor/js/Sidebar.Project.Renderer.js @@ -116,7 +116,8 @@ function SidebarProjectRenderer( editor ) { currentRenderer.toneMapping = parseFloat( toneMappingSelect.getValue() ); currentRenderer.toneMappingExposure = toneMappingExposure.getValue(); - signals.rendererChanged.dispatch( currentRenderer ); + signals.rendererCreated.dispatch( currentRenderer ); + signals.rendererUpdated.dispatch(); } diff --git a/editor/js/Sidebar.Project.js b/editor/js/Sidebar.Project.js index c6932a8569d0e9..f920f0864d9a67 100644 --- a/editor/js/Sidebar.Project.js +++ b/editor/js/Sidebar.Project.js @@ -7,6 +7,7 @@ import { SidebarProjectVideo } from './Sidebar.Project.Video.js'; function SidebarProject( editor ) { var config = editor.config; + var signals = editor.signals; var strings = editor.strings; var container = new UISpan(); @@ -69,6 +70,15 @@ function SidebarProject( editor ) { } + // Signals + + signals.editorCleared.add( function () { + + title.setValue( '' ); + config.setKey( 'project/title', '' ); + + } ); + return container; } diff --git a/editor/js/Viewport.VR.js b/editor/js/Viewport.VR.js index 650b40b4c958a0..5c54c710af3fb4 100644 --- a/editor/js/Viewport.VR.js +++ b/editor/js/Viewport.VR.js @@ -1,6 +1,7 @@ import * as THREE from '../../build/three.module.js'; -import { HTMLMesh } from './libs/three.html.js'; +import { HTMLMesh } from '../../examples/jsm/interactive/HTMLMesh.js'; +import { InteractiveGroup } from '../../examples/jsm/interactive/InteractiveGroup.js'; import { XRControllerModelFactory } from '../../examples/jsm/webxr/XRControllerModelFactory.js'; @@ -29,31 +30,29 @@ class VR { if ( group === null ) { - group = new THREE.Group(); + group = new InteractiveGroup( renderer ); editor.sceneHelpers.add( group ); const mesh = new HTMLMesh( sidebar ); mesh.position.set( 1, 1.5, - 0.5 ); mesh.rotation.y = - 0.5; + mesh.scale.setScalar( 2 ); group.add( mesh ); intersectables.push( mesh ); // controllers - const controller1 = renderer.xr.getController( 0 ); - controller1.addEventListener( 'select', onSelect ); - group.add( controller1 ); - - const controller2 = renderer.xr.getController( 1 ); - controller2.addEventListener( 'selectstart', onSelect ); - group.add( controller2 ); - const geometry = new THREE.BufferGeometry(); geometry.setFromPoints( [ new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, - 5 ) ] ); + const controller1 = renderer.xr.getController( 0 ); controller1.add( new THREE.Line( geometry ) ); + group.add( controller1 ); + + const controller2 = renderer.xr.getController( 1 ); controller2.add( new THREE.Line( geometry ) ); + group.add( controller2 ); // @@ -101,41 +100,6 @@ class VR { }; - // - - function onSelect( event ) { - - const controller = event.target; - - const intersections = getIntersections( controller ); - - if ( intersections.length > 0 ) { - - const intersection = intersections[ 0 ]; - - const object = intersection.object; - const uv = intersection.uv; - - object.material.map.click( uv.x, 1 - uv.y ); - - } - - } - - const raycaster = new THREE.Raycaster(); - const tempMatrix = new THREE.Matrix4(); - - function getIntersections( controller ) { - - tempMatrix.identity().extractRotation( controller.matrixWorld ); - - raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld ); - raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix ); - - return raycaster.intersectObjects( intersectables ); - - } - // signals signals.toggleVR.add( () => { @@ -153,7 +117,7 @@ class VR { } ); - signals.rendererChanged.add( ( value ) => { + signals.rendererCreated.add( ( value ) => { renderer = value; renderer.xr.enabled = true; diff --git a/editor/js/Viewport.ViewHelper.js b/editor/js/Viewport.ViewHelper.js index 120bda19bb035d..d503ab4b3ae4da 100644 --- a/editor/js/Viewport.ViewHelper.js +++ b/editor/js/Viewport.ViewHelper.js @@ -2,317 +2,315 @@ import { UIPanel } from './libs/ui.js'; import * as THREE from '../../build/three.module.js'; -function ViewHelper( editorCamera, container ) { +class ViewHelper extends THREE.Object3D { - THREE.Object3D.call( this ); + constructor( editorCamera, container ) { - this.animating = false; - this.controls = null; + super(); - var panel = new UIPanel(); - panel.setId( 'viewHelper' ); - panel.setPosition( 'absolute' ); - panel.setRight( '0px' ); - panel.setBottom( '0px' ); - panel.setHeight( '128px' ); - panel.setWidth( '128px' ); + this.animating = false; + this.controls = null; - var scope = this; + const panel = new UIPanel(); + panel.setId( 'viewHelper' ); + panel.setPosition( 'absolute' ); + panel.setRight( '0px' ); + panel.setBottom( '0px' ); + panel.setHeight( '128px' ); + panel.setWidth( '128px' ); - panel.dom.addEventListener( 'mouseup', function ( event ) { + const scope = this; - event.stopPropagation(); + panel.dom.addEventListener( 'mouseup', function ( event ) { - scope.handleClick( event ); + event.stopPropagation(); - } ); + scope.handleClick( event ); - panel.dom.addEventListener( 'mousedown', function ( event ) { + } ); - event.stopPropagation(); + panel.dom.addEventListener( 'mousedown', function ( event ) { - } ); + event.stopPropagation(); - container.add( panel ); + } ); - var color1 = new THREE.Color( '#ff3653' ); - var color2 = new THREE.Color( '#8adb00' ); - var color3 = new THREE.Color( '#2c8fff' ); + container.add( panel ); - var interactiveObjects = []; - var raycaster = new THREE.Raycaster(); - var mouse = new THREE.Vector2(); - var dummy = new THREE.Object3D(); + const color1 = new THREE.Color( '#ff3653' ); + const color2 = new THREE.Color( '#8adb00' ); + const color3 = new THREE.Color( '#2c8fff' ); - var camera = new THREE.OrthographicCamera( - 2, 2, 2, - 2, 0, 4 ); - camera.position.set( 0, 0, 2 ); + const interactiveObjects = []; + const raycaster = new THREE.Raycaster(); + const mouse = new THREE.Vector2(); + const dummy = new THREE.Object3D(); - var geometry = new THREE.BoxGeometry( 0.8, 0.05, 0.05 ).translate( 0.4, 0, 0 ); + const camera = new THREE.OrthographicCamera( - 2, 2, 2, - 2, 0, 4 ); + camera.position.set( 0, 0, 2 ); - var xAxis = new THREE.Mesh( geometry, getAxisMaterial( color1 ) ); - var yAxis = new THREE.Mesh( geometry, getAxisMaterial( color2 ) ); - var zAxis = new THREE.Mesh( geometry, getAxisMaterial( color3 ) ); + const geometry = new THREE.BoxGeometry( 0.8, 0.05, 0.05 ).translate( 0.4, 0, 0 ); - yAxis.rotation.z = Math.PI / 2; - zAxis.rotation.y = - Math.PI / 2; + const xAxis = new THREE.Mesh( geometry, getAxisMaterial( color1 ) ); + const yAxis = new THREE.Mesh( geometry, getAxisMaterial( color2 ) ); + const zAxis = new THREE.Mesh( geometry, getAxisMaterial( color3 ) ); - this.add( xAxis ); - this.add( zAxis ); - this.add( yAxis ); + yAxis.rotation.z = Math.PI / 2; + zAxis.rotation.y = - Math.PI / 2; - var posXAxisHelper = new THREE.Sprite( getSpriteMaterial( color1, 'X' ) ); - posXAxisHelper.userData.type = 'posX'; - var posYAxisHelper = new THREE.Sprite( getSpriteMaterial( color2, 'Y' ) ); - posYAxisHelper.userData.type = 'posY'; - var posZAxisHelper = new THREE.Sprite( getSpriteMaterial( color3, 'Z' ) ); - posZAxisHelper.userData.type = 'posZ'; - var negXAxisHelper = new THREE.Sprite( getSpriteMaterial( color1 ) ); - negXAxisHelper.userData.type = 'negX'; - var negYAxisHelper = new THREE.Sprite( getSpriteMaterial( color2 ) ); - negYAxisHelper.userData.type = 'negY'; - var negZAxisHelper = new THREE.Sprite( getSpriteMaterial( color3 ) ); - negZAxisHelper.userData.type = 'negZ'; + this.add( xAxis ); + this.add( zAxis ); + this.add( yAxis ); - posXAxisHelper.position.x = 1; - posYAxisHelper.position.y = 1; - posZAxisHelper.position.z = 1; - negXAxisHelper.position.x = - 1; - negXAxisHelper.scale.setScalar( 0.8 ); - negYAxisHelper.position.y = - 1; - negYAxisHelper.scale.setScalar( 0.8 ); - negZAxisHelper.position.z = - 1; - negZAxisHelper.scale.setScalar( 0.8 ); + const posXAxisHelper = new THREE.Sprite( getSpriteMaterial( color1, 'X' ) ); + posXAxisHelper.userData.type = 'posX'; + const posYAxisHelper = new THREE.Sprite( getSpriteMaterial( color2, 'Y' ) ); + posYAxisHelper.userData.type = 'posY'; + const posZAxisHelper = new THREE.Sprite( getSpriteMaterial( color3, 'Z' ) ); + posZAxisHelper.userData.type = 'posZ'; + const negXAxisHelper = new THREE.Sprite( getSpriteMaterial( color1 ) ); + negXAxisHelper.userData.type = 'negX'; + const negYAxisHelper = new THREE.Sprite( getSpriteMaterial( color2 ) ); + negYAxisHelper.userData.type = 'negY'; + const negZAxisHelper = new THREE.Sprite( getSpriteMaterial( color3 ) ); + negZAxisHelper.userData.type = 'negZ'; - this.add( posXAxisHelper ); - this.add( posYAxisHelper ); - this.add( posZAxisHelper ); - this.add( negXAxisHelper ); - this.add( negYAxisHelper ); - this.add( negZAxisHelper ); + posXAxisHelper.position.x = 1; + posYAxisHelper.position.y = 1; + posZAxisHelper.position.z = 1; + negXAxisHelper.position.x = - 1; + negXAxisHelper.scale.setScalar( 0.8 ); + negYAxisHelper.position.y = - 1; + negYAxisHelper.scale.setScalar( 0.8 ); + negZAxisHelper.position.z = - 1; + negZAxisHelper.scale.setScalar( 0.8 ); - interactiveObjects.push( posXAxisHelper ); - interactiveObjects.push( posYAxisHelper ); - interactiveObjects.push( posZAxisHelper ); - interactiveObjects.push( negXAxisHelper ); - interactiveObjects.push( negYAxisHelper ); - interactiveObjects.push( negZAxisHelper ); + this.add( posXAxisHelper ); + this.add( posYAxisHelper ); + this.add( posZAxisHelper ); + this.add( negXAxisHelper ); + this.add( negYAxisHelper ); + this.add( negZAxisHelper ); - var point = new THREE.Vector3(); - var dim = 128; - var turnRate = 2 * Math.PI; // turn rate in angles per second + interactiveObjects.push( posXAxisHelper ); + interactiveObjects.push( posYAxisHelper ); + interactiveObjects.push( posZAxisHelper ); + interactiveObjects.push( negXAxisHelper ); + interactiveObjects.push( negYAxisHelper ); + interactiveObjects.push( negZAxisHelper ); - this.render = function ( renderer ) { + const point = new THREE.Vector3(); + const dim = 128; + const turnRate = 2 * Math.PI; // turn rate in angles per second - this.quaternion.copy( editorCamera.quaternion ).invert(); - this.updateMatrixWorld(); + this.render = function ( renderer ) { - point.set( 0, 0, 1 ); - point.applyQuaternion( editorCamera.quaternion ); + this.quaternion.copy( editorCamera.quaternion ).invert(); + this.updateMatrixWorld(); - if ( point.x >= 0 ) { + point.set( 0, 0, 1 ); + point.applyQuaternion( editorCamera.quaternion ); - posXAxisHelper.material.opacity = 1; - negXAxisHelper.material.opacity = 0.5; + if ( point.x >= 0 ) { - } else { + posXAxisHelper.material.opacity = 1; + negXAxisHelper.material.opacity = 0.5; - posXAxisHelper.material.opacity = 0.5; - negXAxisHelper.material.opacity = 1; + } else { - } + posXAxisHelper.material.opacity = 0.5; + negXAxisHelper.material.opacity = 1; - if ( point.y >= 0 ) { + } - posYAxisHelper.material.opacity = 1; - negYAxisHelper.material.opacity = 0.5; + if ( point.y >= 0 ) { - } else { + posYAxisHelper.material.opacity = 1; + negYAxisHelper.material.opacity = 0.5; - posYAxisHelper.material.opacity = 0.5; - negYAxisHelper.material.opacity = 1; + } else { - } + posYAxisHelper.material.opacity = 0.5; + negYAxisHelper.material.opacity = 1; - if ( point.z >= 0 ) { + } - posZAxisHelper.material.opacity = 1; - negZAxisHelper.material.opacity = 0.5; + if ( point.z >= 0 ) { - } else { + posZAxisHelper.material.opacity = 1; + negZAxisHelper.material.opacity = 0.5; - posZAxisHelper.material.opacity = 0.5; - negZAxisHelper.material.opacity = 1; + } else { - } + posZAxisHelper.material.opacity = 0.5; + negZAxisHelper.material.opacity = 1; - // + } - var x = container.dom.offsetWidth - dim; + // - renderer.clearDepth(); - renderer.setViewport( x, 0, dim, dim ); - renderer.render( this, camera ); + const x = container.dom.offsetWidth - dim; - }; + renderer.clearDepth(); + renderer.setViewport( x, 0, dim, dim ); + renderer.render( this, camera ); - var targetPosition = new THREE.Vector3(); - var targetQuaternion = new THREE.Quaternion(); + }; - var q1 = new THREE.Quaternion(); - var q2 = new THREE.Quaternion(); - var radius = 0; + const targetPosition = new THREE.Vector3(); + const targetQuaternion = new THREE.Quaternion(); - this.handleClick = function ( event ) { + const q1 = new THREE.Quaternion(); + const q2 = new THREE.Quaternion(); + let radius = 0; - if ( this.animating === true ) return false; + this.handleClick = function ( event ) { - var rect = container.dom.getBoundingClientRect(); - var offsetX = rect.left + ( container.dom.offsetWidth - dim ); - var offsetY = rect.top + ( container.dom.offsetHeight - dim ); - mouse.x = ( ( event.clientX - offsetX ) / ( rect.width - offsetX ) ) * 2 - 1; - mouse.y = - ( ( event.clientY - offsetY ) / ( rect.bottom - offsetY ) ) * 2 + 1; + if ( this.animating === true ) return false; - raycaster.setFromCamera( mouse, camera ); + const rect = container.dom.getBoundingClientRect(); + const offsetX = rect.left + ( container.dom.offsetWidth - dim ); + const offsetY = rect.top + ( container.dom.offsetHeight - dim ); + mouse.x = ( ( event.clientX - offsetX ) / ( rect.width - offsetX ) ) * 2 - 1; + mouse.y = - ( ( event.clientY - offsetY ) / ( rect.bottom - offsetY ) ) * 2 + 1; - var intersects = raycaster.intersectObjects( interactiveObjects ); + raycaster.setFromCamera( mouse, camera ); - if ( intersects.length > 0 ) { + const intersects = raycaster.intersectObjects( interactiveObjects ); - var intersection = intersects[ 0 ]; - var object = intersection.object; + if ( intersects.length > 0 ) { - prepareAnimationData( object, this.controls.center ); + const intersection = intersects[ 0 ]; + const object = intersection.object; - this.animating = true; + prepareAnimationData( object, this.controls.center ); - return true; + this.animating = true; - } else { + return true; - return false; + } else { - } + return false; - }; + } - this.update = function ( delta ) { + }; - var step = delta * turnRate; - var focusPoint = this.controls.center; + this.update = function ( delta ) { - // animate position by doing a slerp and then scaling the position on the unit sphere + const step = delta * turnRate; + const focusPoint = this.controls.center; - q1.rotateTowards( q2, step ); - editorCamera.position.set( 0, 0, 1 ).applyQuaternion( q1 ).multiplyScalar( radius ).add( focusPoint ); + // animate position by doing a slerp and then scaling the position on the unit sphere - // animate orientation + q1.rotateTowards( q2, step ); + editorCamera.position.set( 0, 0, 1 ).applyQuaternion( q1 ).multiplyScalar( radius ).add( focusPoint ); - editorCamera.quaternion.rotateTowards( targetQuaternion, step ); + // animate orientation - if ( q1.angleTo( q2 ) === 0 ) { + editorCamera.quaternion.rotateTowards( targetQuaternion, step ); - this.animating = false; + if ( q1.angleTo( q2 ) === 0 ) { - } + this.animating = false; - }; + } - function prepareAnimationData( object, focusPoint ) { + }; - switch ( object.userData.type ) { + function prepareAnimationData( object, focusPoint ) { - case 'posX': - targetPosition.set( 1, 0, 0 ); - targetQuaternion.setFromEuler( new THREE.Euler( 0, Math.PI * 0.5, 0 ) ); - break; + switch ( object.userData.type ) { - case 'posY': - targetPosition.set( 0, 1, 0 ); - targetQuaternion.setFromEuler( new THREE.Euler( - Math.PI * 0.5, 0, 0 ) ); - break; + case 'posX': + targetPosition.set( 1, 0, 0 ); + targetQuaternion.setFromEuler( new THREE.Euler( 0, Math.PI * 0.5, 0 ) ); + break; - case 'posZ': - targetPosition.set( 0, 0, 1 ); - targetQuaternion.setFromEuler( new THREE.Euler() ); - break; + case 'posY': + targetPosition.set( 0, 1, 0 ); + targetQuaternion.setFromEuler( new THREE.Euler( - Math.PI * 0.5, 0, 0 ) ); + break; - case 'negX': - targetPosition.set( - 1, 0, 0 ); - targetQuaternion.setFromEuler( new THREE.Euler( 0, - Math.PI * 0.5, 0 ) ); - break; + case 'posZ': + targetPosition.set( 0, 0, 1 ); + targetQuaternion.setFromEuler( new THREE.Euler() ); + break; - case 'negY': - targetPosition.set( 0, - 1, 0 ); - targetQuaternion.setFromEuler( new THREE.Euler( Math.PI * 0.5, 0, 0 ) ); - break; + case 'negX': + targetPosition.set( - 1, 0, 0 ); + targetQuaternion.setFromEuler( new THREE.Euler( 0, - Math.PI * 0.5, 0 ) ); + break; - case 'negZ': - targetPosition.set( 0, 0, - 1 ); - targetQuaternion.setFromEuler( new THREE.Euler( 0, Math.PI, 0 ) ); - break; + case 'negY': + targetPosition.set( 0, - 1, 0 ); + targetQuaternion.setFromEuler( new THREE.Euler( Math.PI * 0.5, 0, 0 ) ); + break; - default: - console.error( 'ViewHelper: Invalid axis.' ); + case 'negZ': + targetPosition.set( 0, 0, - 1 ); + targetQuaternion.setFromEuler( new THREE.Euler( 0, Math.PI, 0 ) ); + break; - } + default: + console.error( 'ViewHelper: Invalid axis.' ); - // + } - radius = editorCamera.position.distanceTo( focusPoint ); - targetPosition.multiplyScalar( radius ).add( focusPoint ); + // - dummy.position.copy( focusPoint ); + radius = editorCamera.position.distanceTo( focusPoint ); + targetPosition.multiplyScalar( radius ).add( focusPoint ); - dummy.lookAt( editorCamera.position ); - q1.copy( dummy.quaternion ); + dummy.position.copy( focusPoint ); - dummy.lookAt( targetPosition ); - q2.copy( dummy.quaternion ); + dummy.lookAt( editorCamera.position ); + q1.copy( dummy.quaternion ); - } + dummy.lookAt( targetPosition ); + q2.copy( dummy.quaternion ); - function getAxisMaterial( color ) { + } - return new THREE.MeshBasicMaterial( { color: color, toneMapped: false } ); + function getAxisMaterial( color ) { - } + return new THREE.MeshBasicMaterial( { color: color, toneMapped: false } ); - function getSpriteMaterial( color, text = null ) { - - var canvas = document.createElement( 'canvas' ); - canvas.width = 64; - canvas.height = 64; + } - var context = canvas.getContext( '2d' ); - context.beginPath(); - context.arc( 32, 32, 16, 0, 2 * Math.PI ); - context.closePath(); - context.fillStyle = color.getStyle(); - context.fill(); + function getSpriteMaterial( color, text = null ) { - if ( text !== null ) { + const canvas = document.createElement( 'canvas' ); + canvas.width = 64; + canvas.height = 64; - context.font = '24px Arial'; - context.textAlign = 'center'; - context.fillStyle = '#000000'; - context.fillText( text, 32, 41 ); + const context = canvas.getContext( '2d' ); + context.beginPath(); + context.arc( 32, 32, 16, 0, 2 * Math.PI ); + context.closePath(); + context.fillStyle = color.getStyle(); + context.fill(); - } + if ( text !== null ) { - var texture = new THREE.CanvasTexture( canvas ); + context.font = '24px Arial'; + context.textAlign = 'center'; + context.fillStyle = '#000000'; + context.fillText( text, 32, 41 ); - return new THREE.SpriteMaterial( { map: texture, toneMapped: false } ); + } - } + const texture = new THREE.CanvasTexture( canvas ); -} + return new THREE.SpriteMaterial( { map: texture, toneMapped: false } ); -ViewHelper.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { + } - constructor: ViewHelper, + } - isViewHelper: true +} -} ); +ViewHelper.prototype.isViewHelper = true; export { ViewHelper }; diff --git a/editor/js/Viewport.js b/editor/js/Viewport.js index 8f79a804dc5307..626e435442a9ee 100644 --- a/editor/js/Viewport.js +++ b/editor/js/Viewport.js @@ -347,7 +347,7 @@ function Viewport( editor ) { } ); - signals.rendererChanged.add( function ( newRenderer ) { + signals.rendererCreated.add( function ( newRenderer ) { if ( renderer !== null ) { diff --git a/editor/sw.js b/editor/sw.js index 5969a13c0fbf5f..b320027c23d94e 100644 --- a/editor/sw.js +++ b/editor/sw.js @@ -1,3 +1,5 @@ +// r128 + const cacheName = 'threejs-editor'; const assets = [ @@ -13,7 +15,7 @@ const assets = [ '../examples/jsm/controls/TransformControls.js', '../examples/jsm/libs/chevrotain.module.min.js', - '../examples/jsm/libs/fflate.module.min.js', + '../examples/jsm/libs/fflate.module.js', '../examples/js/libs/draco/draco_decoder.js', '../examples/js/libs/draco/draco_decoder.wasm', @@ -57,6 +59,9 @@ const assets = [ '../examples/jsm/curves/NURBSCurve.js', '../examples/jsm/curves/NURBSUtils.js', + '../examples/jsm/interactive/HTMLMesh.js', + '../examples/jsm/interactive/InteractiveGroup.js', + '../examples/jsm/environments/RoomEnvironment.js', '../examples/jsm/exporters/ColladaExporter.js', @@ -108,7 +113,6 @@ const assets = [ './js/libs/tern-threejs/threejs.js', './js/libs/signals.min.js', - './js/libs/three.html.js', './js/libs/ui.js', './js/libs/ui.three.js', diff --git a/examples/files.json b/examples/files.json index 4fca40924db47e..58a028dcd526f2 100644 --- a/examples/files.json +++ b/examples/files.json @@ -123,7 +123,6 @@ "webgl_loader_vrm", "webgl_loader_vrml", "webgl_loader_vtk", - "webgl_loader_x", "webgl_loader_xyz", "webgl_lod", "webgl_marchingcubes", @@ -233,6 +232,7 @@ "webgl_materials_envmaps_hdr_nodes", "webgl_materials_envmaps_pmrem_nodes", "webgl_materials_nodes", + "webgl_materials_standard_nodes", "webgl_mirror_nodes", "webgl_performance_nodes", "webgl_postprocessing_nodes", @@ -318,6 +318,7 @@ "webgpu": [ "webgpu_compute", "webgpu_instance_uniform", + "webgpu_lights_selective", "webgpu_materials", "webgpu_rtt", "webgpu_sandbox" diff --git a/examples/index.html b/examples/index.html index 9527cb16c0a11a..7bd44aee947774 100644 --- a/examples/index.html +++ b/examples/index.html @@ -51,7 +51,7 @@

three.js

- + diff --git a/examples/js/WebGL.js b/examples/js/WebGL.js index 6838b2c47a2f8f..bd1e877041cbf0 100644 --- a/examples/js/WebGL.js +++ b/examples/js/WebGL.js @@ -1,89 +1,90 @@ -THREE.WEBGL = { +( function () { - isWebGLAvailable: function () { + class WEBGL { - try { + static isWebGLAvailable() { - var canvas = document.createElement( 'canvas' ); - return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); + try { - } catch ( e ) { + const canvas = document.createElement( 'canvas' ); + return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); - return false; + } catch ( e ) { - } + return false; - }, + } - isWebGL2Available: function () { + } - try { + static isWebGL2Available() { - var canvas = document.createElement( 'canvas' ); - return !! ( window.WebGL2RenderingContext && canvas.getContext( 'webgl2' ) ); + try { - } catch ( e ) { + const canvas = document.createElement( 'canvas' ); + return !! ( window.WebGL2RenderingContext && canvas.getContext( 'webgl2' ) ); - return false; + } catch ( e ) { - } + return false; - }, + } - getWebGLErrorMessage: function () { + } - return this.getErrorMessage( 1 ); + static getWebGLErrorMessage() { - }, + return this.getErrorMessage( 1 ); - getWebGL2ErrorMessage: function () { + } - return this.getErrorMessage( 2 ); + static getWebGL2ErrorMessage() { - }, + return this.getErrorMessage( 2 ); - getErrorMessage: function ( version ) { + } - var names = { - 1: 'WebGL', - 2: 'WebGL 2' - }; + static getErrorMessage( version ) { - var contexts = { - 1: window.WebGLRenderingContext, - 2: window.WebGL2RenderingContext - }; + 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'; - var message = 'Your $0 does not seem to support $1'; + if ( contexts[ version ] ) { - var 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'; + message = message.replace( '$0', 'graphics card' ); - if ( contexts[ version ] ) { + } else { - message = message.replace( '$0', 'graphics card' ); + message = message.replace( '$0', 'browser' ); - } else { + } - message = message.replace( '$0', 'browser' ); + message = message.replace( '$1', names[ version ] ); + element.innerHTML = message; + return element; } - message = message.replace( '$1', names[ version ] ); - - element.innerHTML = message; - - return element; - } -}; + THREE.WEBGL = WEBGL; + +} )(); diff --git a/examples/js/animation/AnimationClipCreator.js b/examples/js/animation/AnimationClipCreator.js index e2fce29fcb9994..dc399c51c75afc 100644 --- a/examples/js/animation/AnimationClipCreator.js +++ b/examples/js/animation/AnimationClipCreator.js @@ -1,106 +1,97 @@ -THREE.AnimationClipCreator = function () {}; +( function () { -THREE.AnimationClipCreator.CreateRotationAnimation = function ( period, axis ) { + class AnimationClipCreator { - var times = [ 0, period ], values = [ 0, 360 ]; + static CreateRotationAnimation( period, axis = 'x' ) { - axis = axis || 'x'; - var trackName = '.rotation[' + axis + ']'; + const times = [ 0, period ], + values = [ 0, 360 ]; + const trackName = '.rotation[' + axis + ']'; + const track = new THREE.NumberKeyframeTrack( trackName, times, values ); + return new THREE.AnimationClip( null, period, [ track ] ); - var track = new THREE.NumberKeyframeTrack( trackName, times, values ); + } - return new THREE.AnimationClip( null, period, [ track ] ); + static CreateScaleAxisAnimation( period, axis = 'x' ) { -}; + const times = [ 0, period ], + values = [ 0, 1 ]; + const trackName = '.scale[' + axis + ']'; + const track = new THREE.NumberKeyframeTrack( trackName, times, values ); + return new THREE.AnimationClip( null, period, [ track ] ); -THREE.AnimationClipCreator.CreateScaleAxisAnimation = function ( period, axis ) { + } - var times = [ 0, period ], values = [ 0, 1 ]; + static CreateShakeAnimation( duration, shakeScale ) { - axis = axis || 'x'; - var trackName = '.scale[' + axis + ']'; + const times = [], + values = [], + tmp = new THREE.Vector3(); - var track = new THREE.NumberKeyframeTrack( trackName, times, values ); + for ( let i = 0; i < duration * 10; i ++ ) { - return new THREE.AnimationClip( null, period, [ track ] ); + times.push( i / 10 ); + tmp.set( Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0 ).multiply( shakeScale ).toArray( values, values.length ); -}; + } -THREE.AnimationClipCreator.CreateShakeAnimation = function ( duration, shakeScale ) { + const trackName = '.position'; + const track = new THREE.VectorKeyframeTrack( trackName, times, values ); + return new THREE.AnimationClip( null, duration, [ track ] ); - var times = [], values = [], tmp = new THREE.Vector3(); + } - for ( var i = 0; i < duration * 10; i ++ ) { + static CreatePulsationAnimation( duration, pulseScale ) { - times.push( i / 10 ); + const times = [], + values = [], + tmp = new THREE.Vector3(); - tmp.set( Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0 ). - multiply( shakeScale ). - toArray( values, values.length ); + for ( let i = 0; i < duration * 10; i ++ ) { - } - - var trackName = '.position'; - - var track = new THREE.VectorKeyframeTrack( trackName, times, values ); - - return new THREE.AnimationClip( null, duration, [ track ] ); - -}; - - -THREE.AnimationClipCreator.CreatePulsationAnimation = function ( duration, pulseScale ) { - - var times = [], values = [], tmp = new THREE.Vector3(); - - for ( var i = 0; i < duration * 10; i ++ ) { + times.push( i / 10 ); + const scaleFactor = Math.random() * pulseScale; + tmp.set( scaleFactor, scaleFactor, scaleFactor ).toArray( values, values.length ); - times.push( i / 10 ); + } - var scaleFactor = Math.random() * pulseScale; - tmp.set( scaleFactor, scaleFactor, scaleFactor ). - toArray( values, values.length ); + const trackName = '.scale'; + const track = new THREE.VectorKeyframeTrack( trackName, times, values ); + return new THREE.AnimationClip( null, duration, [ track ] ); - } - - var trackName = '.scale'; - - var track = new THREE.VectorKeyframeTrack( trackName, times, values ); - - return new THREE.AnimationClip( null, duration, [ track ] ); - -}; + } + static CreateVisibilityAnimation( duration ) { -THREE.AnimationClipCreator.CreateVisibilityAnimation = function ( duration ) { + const times = [ 0, duration / 2, duration ], + values = [ true, false, true ]; + const trackName = '.visible'; + const track = new THREE.BooleanKeyframeTrack( trackName, times, values ); + return new THREE.AnimationClip( null, duration, [ track ] ); - var times = [ 0, duration / 2, duration ], values = [ true, false, true ]; + } - var trackName = '.visible'; + static CreateMaterialColorAnimation( duration, colors ) { - var track = new THREE.BooleanKeyframeTrack( trackName, times, values ); + const times = [], + values = [], + timeStep = duration / colors.length; - return new THREE.AnimationClip( null, duration, [ track ] ); + for ( let i = 0; i <= colors.length; i ++ ) { -}; + times.push( i * timeStep ); + values.push( colors[ i % colors.length ] ); + } -THREE.AnimationClipCreator.CreateMaterialColorAnimation = function ( duration, colors ) { + const trackName = '.material[0].color'; + const track = new THREE.ColorKeyframeTrack( trackName, times, values ); + return new THREE.AnimationClip( null, duration, [ track ] ); - var times = [], values = [], - timeStep = duration / colors.length; - - for ( var i = 0; i <= colors.length; i ++ ) { - - times.push( i * timeStep ); - values.push( colors[ i % colors.length ] ); + } } - var trackName = '.material[0].color'; - - var track = new THREE.ColorKeyframeTrack( trackName, times, values ); - - return new THREE.AnimationClip( null, duration, [ track ] ); + THREE.AnimationClipCreator = AnimationClipCreator; -}; +} )(); diff --git a/examples/js/animation/CCDIKSolver.js b/examples/js/animation/CCDIKSolver.js index 8da242601bc61c..904991a9f0a9c5 100644 --- a/examples/js/animation/CCDIKSolver.js +++ b/examples/js/animation/CCDIKSolver.js @@ -1,4 +1,27 @@ -/** +( function () { + + const _q = new THREE.Quaternion(); + + const _targetPos = new THREE.Vector3(); + + const _targetVec = new THREE.Vector3(); + + const _effectorPos = new THREE.Vector3(); + + const _effectorVec = new THREE.Vector3(); + + const _linkPos = new THREE.Vector3(); + + const _invLinkQ = new THREE.Quaternion(); + + const _linkScale = new THREE.Vector3(); + + const _axis = new THREE.Vector3(); + + const _vector = new THREE.Vector3(); + + const _matrix = new THREE.Matrix4(); + /** * CCD Algorithm * - https://sites.google.com/site/auraliusproject/ccd-algorithm * @@ -18,35 +41,33 @@ * } ]; */ -THREE.CCDIKSolver = ( function () { - /** - * @param {THREE.SkinnedMesh} mesh - * @param {Array} iks - */ - function CCDIKSolver( mesh, iks ) { + class CCDIKSolver { - this.mesh = mesh; - this.iks = iks || []; + /** + * @param {THREE.SkinnedMesh} mesh + * @param {Array} iks + */ + constructor( mesh, iks = [] ) { - this._valid(); + this.mesh = mesh; + this.iks = iks; - } + this._valid(); - CCDIKSolver.prototype = { + } + /** + * Update all IK bones. + * + * @return {CCDIKSolver} + */ - constructor: CCDIKSolver, - /** - * Update all IK bones. - * - * @return {CCDIKSolver} - */ - update: function () { + update() { - var iks = this.iks; + const iks = this.iks; - for ( var i = 0, il = iks.length; i < il; i ++ ) { + for ( let i = 0, il = iks.length; i < il; i ++ ) { this.updateOne( iks[ i ] ); @@ -54,188 +75,161 @@ THREE.CCDIKSolver = ( function () { return this; - }, - + } /** - * Update one IK bone - * - * @param {Object} ik parameter - * @return {THREE.CCDIKSolver} - */ - updateOne: function () { + * Update one IK bone + * + * @param {Object} ik parameter + * @return {CCDIKSolver} + */ - var q = new THREE.Quaternion(); - var targetPos = new THREE.Vector3(); - var targetVec = new THREE.Vector3(); - var effectorPos = new THREE.Vector3(); - var effectorVec = new THREE.Vector3(); - var linkPos = new THREE.Vector3(); - var invLinkQ = new THREE.Quaternion(); - var linkScale = new THREE.Vector3(); - var axis = new THREE.Vector3(); - var vector = new THREE.Vector3(); - return function update( ik ) { + updateOne( ik ) { - var bones = this.mesh.skeleton.bones; + const bones = this.mesh.skeleton.bones; // for reference overhead reduction in loop - // for reference overhead reduction in loop - var math = Math; + const math = Math; + const effector = bones[ ik.effector ]; + const target = bones[ ik.target ]; // don't use getWorldPosition() here for the performance + // because it calls updateMatrixWorld( true ) inside. - var effector = bones[ ik.effector ]; - var target = bones[ ik.target ]; + _targetPos.setFromMatrixPosition( target.matrixWorld ); - // don't use getWorldPosition() here for the performance - // because it calls updateMatrixWorld( true ) inside. - targetPos.setFromMatrixPosition( target.matrixWorld ); + const links = ik.links; + const iteration = ik.iteration !== undefined ? ik.iteration : 1; - var links = ik.links; - var iteration = ik.iteration !== undefined ? ik.iteration : 1; + for ( let i = 0; i < iteration; i ++ ) { - for ( var i = 0; i < iteration; i ++ ) { + let rotated = false; - var rotated = false; + for ( let j = 0, jl = links.length; j < jl; j ++ ) { - for ( var j = 0, jl = links.length; j < jl; j ++ ) { + const link = bones[ links[ j ].index ]; // skip this link and following links. + // this skip is used for MMD performance optimization. - var link = bones[ links[ j ].index ]; + if ( links[ j ].enabled === false ) break; + const limitation = links[ j ].limitation; + const rotationMin = links[ j ].rotationMin; + const rotationMax = links[ j ].rotationMax; // don't use getWorldPosition/Quaternion() here for the performance + // because they call updateMatrixWorld( true ) inside. - // skip this link and following links. - // this skip is used for MMD performance optimization. - if ( links[ j ].enabled === false ) break; + link.matrixWorld.decompose( _linkPos, _invLinkQ, _linkScale ); - var limitation = links[ j ].limitation; - var rotationMin = links[ j ].rotationMin; - var rotationMax = links[ j ].rotationMax; + _invLinkQ.invert(); - // don't use getWorldPosition/Quaternion() here for the performance - // because they call updateMatrixWorld( true ) inside. - link.matrixWorld.decompose( linkPos, invLinkQ, linkScale ); - invLinkQ.invert(); - effectorPos.setFromMatrixPosition( effector.matrixWorld ); + _effectorPos.setFromMatrixPosition( effector.matrixWorld ); // work in link world - // work in link world - effectorVec.subVectors( effectorPos, linkPos ); - effectorVec.applyQuaternion( invLinkQ ); - effectorVec.normalize(); - targetVec.subVectors( targetPos, linkPos ); - targetVec.applyQuaternion( invLinkQ ); - targetVec.normalize(); + _effectorVec.subVectors( _effectorPos, _linkPos ); - var angle = targetVec.dot( effectorVec ); + _effectorVec.applyQuaternion( _invLinkQ ); - if ( angle > 1.0 ) { + _effectorVec.normalize(); - angle = 1.0; + _targetVec.subVectors( _targetPos, _linkPos ); - } else if ( angle < - 1.0 ) { + _targetVec.applyQuaternion( _invLinkQ ); - angle = - 1.0; + _targetVec.normalize(); - } + let angle = _targetVec.dot( _effectorVec ); - angle = math.acos( angle ); + if ( angle > 1.0 ) { - // 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; + angle = 1.0; - if ( ik.minAngle !== undefined && angle < ik.minAngle ) { + } else if ( angle < - 1.0 ) { - angle = ik.minAngle; + angle = - 1.0; - } + } + + 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 ( ik.maxAngle !== undefined && angle > ik.maxAngle ) { + if ( angle < 1e-5 ) continue; - angle = ik.maxAngle; + if ( ik.minAngle !== undefined && angle < ik.minAngle ) { - } + angle = ik.minAngle; + + } - axis.crossVectors( effectorVec, targetVec ); - axis.normalize(); + if ( ik.maxAngle !== undefined && angle > ik.maxAngle ) { - q.setFromAxisAngle( axis, angle ); - link.quaternion.multiply( q ); + angle = ik.maxAngle; - // TODO: re-consider the limitation specification - if ( limitation !== undefined ) { + } - var c = link.quaternion.w; + _axis.crossVectors( _effectorVec, _targetVec ); - if ( c > 1.0 ) c = 1.0; + _axis.normalize(); - var c2 = math.sqrt( 1 - c * c ); - link.quaternion.set( limitation.x * c2, - limitation.y * c2, - limitation.z * c2, - c ); + _q.setFromAxisAngle( _axis, angle ); - } + link.quaternion.multiply( _q ); // TODO: re-consider the limitation specification - if ( rotationMin !== undefined ) { + if ( limitation !== undefined ) { - link.rotation.setFromVector3( - link.rotation - .toVector3( vector ) - .max( rotationMin ) ); + let c = link.quaternion.w; + if ( c > 1.0 ) c = 1.0; + const c2 = math.sqrt( 1 - c * c ); + link.quaternion.set( limitation.x * c2, limitation.y * c2, limitation.z * c2, c ); - } + } - if ( rotationMax !== undefined ) { + if ( rotationMin !== undefined ) { - link.rotation.setFromVector3( - link.rotation - .toVector3( vector ) - .min( rotationMax ) ); + link.rotation.setFromVector3( link.rotation.toVector3( _vector ).max( rotationMin ) ); - } + } - link.updateMatrixWorld( true ); + if ( rotationMax !== undefined ) { - rotated = true; + link.rotation.setFromVector3( link.rotation.toVector3( _vector ).min( rotationMax ) ); } - if ( ! rotated ) break; + link.updateMatrixWorld( true ); + rotated = true; } - return this; + if ( ! rotated ) break; - }; + } - }(), + return this; + } /** - * Creates Helper - * - * @return {CCDIKHelper} - */ - createHelper: function () { + * Creates Helper + * + * @return {CCDIKHelper} + */ - return new CCDIKHelper( this.mesh, this.mesh.geometry.userData.MMD.iks ); - }, + createHelper() { - // private methods + return new CCDIKHelper( this.mesh, this.mesh.geometry.userData.MMD.iks ); - _valid: function () { + } // private methods - var iks = this.iks; - var bones = this.mesh.skeleton.bones; - for ( var i = 0, il = iks.length; i < il; i ++ ) { + _valid() { - var ik = iks[ i ]; - var effector = bones[ ik.effector ]; - var links = ik.links; - var link0, link1; + const iks = this.iks; + const bones = this.mesh.skeleton.bones; + for ( let i = 0, il = iks.length; i < il; i ++ ) { + + const ik = iks[ i ]; + const effector = bones[ ik.effector ]; + const links = ik.links; + let link0, link1; link0 = effector; - for ( var j = 0, jl = links.length; j < jl; j ++ ) { + for ( let j = 0, jl = links.length; j < jl; j ++ ) { link1 = bones[ links[ j ].index ]; @@ -253,166 +247,139 @@ THREE.CCDIKSolver = ( function () { } - }; - - /** - * Visualize IK bones - * - * @param {SkinnedMesh} mesh - * @param {Array} iks - */ - function CCDIKHelper( mesh, iks ) { - - THREE.Object3D.call( this ); - - this.root = mesh; - this.iks = iks || []; - - this.matrix.copy( mesh.matrixWorld ); - this.matrixAutoUpdate = false; - - this.sphereGeometry = new THREE.SphereGeometry( 0.25, 16, 8 ); - - this.targetSphereMaterial = new THREE.MeshBasicMaterial( { - color: new THREE.Color( 0xff8888 ), - depthTest: false, - depthWrite: false, - transparent: true - } ); - - this.effectorSphereMaterial = new THREE.MeshBasicMaterial( { - color: new THREE.Color( 0x88ff88 ), - depthTest: false, - depthWrite: false, - transparent: true - } ); - - this.linkSphereMaterial = new THREE.MeshBasicMaterial( { - color: new THREE.Color( 0x8888ff ), - depthTest: false, - depthWrite: false, - transparent: true - } ); - - this.lineMaterial = new THREE.LineBasicMaterial( { - color: new THREE.Color( 0xff0000 ), - depthTest: false, - depthWrite: false, - transparent: true - } ); - - this._init(); - } - CCDIKHelper.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { - - constructor: CCDIKHelper, - - /** - * Updates IK bones visualization. - */ - updateMatrixWorld: function () { - - var matrix = new THREE.Matrix4(); - var vector = new THREE.Vector3(); + function getPosition( bone, matrixWorldInv ) { - function getPosition( bone, matrixWorldInv ) { - - return vector - .setFromMatrixPosition( bone.matrixWorld ) - .applyMatrix4( matrixWorldInv ); - - } - - function setPositionOfBoneToAttributeArray( array, index, bone, matrixWorldInv ) { - - var v = getPosition( bone, matrixWorldInv ); - - array[ index * 3 + 0 ] = v.x; - array[ index * 3 + 1 ] = v.y; - array[ index * 3 + 2 ] = v.z; - - } + return _vector.setFromMatrixPosition( bone.matrixWorld ).applyMatrix4( matrixWorldInv ); - return function updateMatrixWorld( force ) { - - var mesh = this.root; + } - if ( this.visible ) { + function setPositionOfBoneToAttributeArray( array, index, bone, matrixWorldInv ) { - var offset = 0; + const v = getPosition( bone, matrixWorldInv ); + array[ index * 3 + 0 ] = v.x; + array[ index * 3 + 1 ] = v.y; + array[ index * 3 + 2 ] = v.z; - var iks = this.iks; - var bones = mesh.skeleton.bones; + } + /** + * Visualize IK bones + * + * @param {SkinnedMesh} mesh + * @param {Array} iks + */ - matrix.copy( mesh.matrixWorld ).invert(); - for ( var i = 0, il = iks.length; i < il; i ++ ) { + class CCDIKHelper extends THREE.Object3D { + + constructor( mesh, iks = [] ) { + + super(); + this.root = mesh; + this.iks = iks; + this.matrix.copy( mesh.matrixWorld ); + this.matrixAutoUpdate = false; + this.sphereGeometry = new THREE.SphereGeometry( 0.25, 16, 8 ); + this.targetSphereMaterial = new THREE.MeshBasicMaterial( { + color: new THREE.Color( 0xff8888 ), + depthTest: false, + depthWrite: false, + transparent: true + } ); + this.effectorSphereMaterial = new THREE.MeshBasicMaterial( { + color: new THREE.Color( 0x88ff88 ), + depthTest: false, + depthWrite: false, + transparent: true + } ); + this.linkSphereMaterial = new THREE.MeshBasicMaterial( { + color: new THREE.Color( 0x8888ff ), + depthTest: false, + depthWrite: false, + transparent: true + } ); + this.lineMaterial = new THREE.LineBasicMaterial( { + color: new THREE.Color( 0xff0000 ), + depthTest: false, + depthWrite: false, + transparent: true + } ); + + this._init(); - var ik = iks[ i ]; + } + /** + * Updates IK bones visualization. + */ - var targetBone = bones[ ik.target ]; - var effectorBone = bones[ ik.effector ]; - var targetMesh = this.children[ offset ++ ]; - var effectorMesh = this.children[ offset ++ ]; + updateMatrixWorld( force ) { - targetMesh.position.copy( getPosition( targetBone, matrix ) ); - effectorMesh.position.copy( getPosition( effectorBone, matrix ) ); + const mesh = this.root; - for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) { + if ( this.visible ) { - var link = ik.links[ j ]; - var linkBone = bones[ link.index ]; + let offset = 0; + const iks = this.iks; + const bones = mesh.skeleton.bones; - var linkMesh = this.children[ offset ++ ]; + _matrix.copy( mesh.matrixWorld ).invert(); - linkMesh.position.copy( getPosition( linkBone, matrix ) ); + for ( let i = 0, il = iks.length; i < il; i ++ ) { - } + const ik = iks[ i ]; + const targetBone = bones[ ik.target ]; + const effectorBone = bones[ ik.effector ]; + const targetMesh = this.children[ offset ++ ]; + const effectorMesh = this.children[ offset ++ ]; + targetMesh.position.copy( getPosition( targetBone, _matrix ) ); + effectorMesh.position.copy( getPosition( effectorBone, _matrix ) ); - var line = this.children[ offset ++ ]; - var array = line.geometry.attributes.position.array; + for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { - setPositionOfBoneToAttributeArray( array, 0, targetBone, matrix ); - setPositionOfBoneToAttributeArray( array, 1, effectorBone, matrix ); + const link = ik.links[ j ]; + const linkBone = bones[ link.index ]; + const linkMesh = this.children[ offset ++ ]; + linkMesh.position.copy( getPosition( linkBone, _matrix ) ); - for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) { + } - var link = ik.links[ j ]; - var linkBone = bones[ link.index ]; - setPositionOfBoneToAttributeArray( array, j + 2, linkBone, matrix ); + const line = this.children[ offset ++ ]; + const array = line.geometry.attributes.position.array; + setPositionOfBoneToAttributeArray( array, 0, targetBone, _matrix ); + setPositionOfBoneToAttributeArray( array, 1, effectorBone, _matrix ); - } + for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { - line.geometry.attributes.position.needsUpdate = true; + const link = ik.links[ j ]; + const linkBone = bones[ link.index ]; + setPositionOfBoneToAttributeArray( array, j + 2, linkBone, _matrix ); } - } + line.geometry.attributes.position.needsUpdate = true; - this.matrix.copy( mesh.matrixWorld ); + } - THREE.Object3D.prototype.updateMatrixWorld.call( this, force ); + } - }; + this.matrix.copy( mesh.matrixWorld ); + super.updateMatrixWorld( force ); - }(), + } // private method - // private method - _init: function () { + _init() { - var scope = this; - var iks = this.iks; + const scope = this; + const iks = this.iks; function createLineGeometry( ik ) { - var geometry = new THREE.BufferGeometry(); - var vertices = new Float32Array( ( 2 + ik.links.length ) * 3 ); + const geometry = new THREE.BufferGeometry(); + const vertices = new Float32Array( ( 2 + ik.links.length ) * 3 ); geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); - return geometry; } @@ -441,14 +408,13 @@ THREE.CCDIKSolver = ( function () { } - for ( var i = 0, il = iks.length; i < il; i ++ ) { - - var ik = iks[ i ]; + for ( let i = 0, il = iks.length; i < il; i ++ ) { + const ik = iks[ i ]; this.add( createTargetMesh() ); this.add( createEffectorMesh() ); - for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) { + for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { this.add( createLinkMesh() ); @@ -460,8 +426,8 @@ THREE.CCDIKSolver = ( function () { } - } ); + } - return CCDIKSolver; + THREE.CCDIKSolver = CCDIKSolver; } )(); diff --git a/examples/js/animation/MMDAnimationHelper.js b/examples/js/animation/MMDAnimationHelper.js index c288f9183e7f28..17606cd425c754 100644 --- a/examples/js/animation/MMDAnimationHelper.js +++ b/examples/js/animation/MMDAnimationHelper.js @@ -1,4 +1,6 @@ -/** +( function () { + + /** * MMDAnimationHelper handles animation of MMD assets loaded by MMDLoader * with MMD special features as IK, Grant, and Physics. * @@ -11,79 +13,63 @@ * - more precise grant skinning support. */ -THREE.MMDAnimationHelper = ( function () { + class MMDAnimationHelper { - /** - * @param {Object} params - (optional) - * @param {boolean} params.sync - Whether animation durations of added objects are synched. Default is true. - * @param {Number} params.afterglow - Default is 0.0. - * @param {boolean} params.resetPhysicsOnLoop - Default is true. - */ - function MMDAnimationHelper( params ) { - - params = params || {}; - - this.meshes = []; - - this.camera = null; - this.cameraTarget = new THREE.Object3D(); - this.cameraTarget.name = 'target'; - - this.audio = null; - this.audioManager = null; - - this.objects = new WeakMap(); - - this.configuration = { - sync: params.sync !== undefined - ? params.sync : true, - afterglow: params.afterglow !== undefined - ? params.afterglow : 0.0, - resetPhysicsOnLoop: params.resetPhysicsOnLoop !== undefined - ? params.resetPhysicsOnLoop : true, - pmxAnimation: params.pmxAnimation !== undefined - ? params.pmxAnimation : false - }; - - this.enabled = { - animation: true, - ik: true, - grant: true, - physics: true, - cameraAnimation: true - }; - - this.onBeforePhysics = function ( /* mesh */ ) {}; - - // experimental - this.sharedPhysics = false; - this.masterPhysics = null; + /** + * @param {Object} params - (optional) + * @param {boolean} params.sync - Whether animation durations of added objects are synched. Default is true. + * @param {Number} params.afterglow - Default is 0.0. + * @param {boolean} params.resetPhysicsOnLoop - Default is true. + */ + constructor( params = {} ) { + + this.meshes = []; + this.camera = null; + this.cameraTarget = new THREE.Object3D(); + this.cameraTarget.name = 'target'; + this.audio = null; + this.audioManager = null; + this.objects = new WeakMap(); + this.configuration = { + sync: params.sync !== undefined ? params.sync : true, + afterglow: params.afterglow !== undefined ? params.afterglow : 0.0, + resetPhysicsOnLoop: params.resetPhysicsOnLoop !== undefined ? params.resetPhysicsOnLoop : true, + pmxAnimation: params.pmxAnimation !== undefined ? params.pmxAnimation : false + }; + this.enabled = { + animation: true, + ik: true, + grant: true, + physics: true, + cameraAnimation: true + }; - } + this.onBeforePhysics = function ( ) {}; // experimental - MMDAnimationHelper.prototype = { - constructor: MMDAnimationHelper, + this.sharedPhysics = false; + this.masterPhysics = null; + } /** - * Adds an Three.js Object to helper and setups animation. - * The anmation durations of added objects are synched - * if this.configuration.sync is true. - * - * @param {THREE.SkinnedMesh|THREE.Camera|THREE.Audio} object - * @param {Object} params - (optional) - * @param {THREE.AnimationClip|Array} params.animation - Only for THREE.SkinnedMesh and THREE.Camera. Default is undefined. - * @param {boolean} params.physics - Only for THREE.SkinnedMesh. Default is true. - * @param {Integer} params.warmup - Only for THREE.SkinnedMesh and physics is true. Default is 60. - * @param {Number} params.unitStep - Only for THREE.SkinnedMesh and physics is true. Default is 1 / 65. - * @param {Integer} params.maxStepNum - Only for THREE.SkinnedMesh and physics is true. Default is 3. - * @param {THREE.Vector3} params.gravity - Only for THREE.SkinnedMesh and physics is true. Default ( 0, - 9.8 * 10, 0 ). - * @param {Number} params.delayTime - Only for THREE.Audio. Default is 0.0. - * @return {THREE.MMDAnimationHelper} - */ - add: function ( object, params ) { - - params = params || {}; + * Adds an Three.js Object to helper and setups animation. + * The anmation durations of added objects are synched + * if this.configuration.sync is true. + * + * @param {THREE.SkinnedMesh|THREE.Camera|THREE.Audio} object + * @param {Object} params - (optional) + * @param {THREE.AnimationClip|Array} params.animation - Only for THREE.SkinnedMesh and THREE.Camera. Default is undefined. + * @param {boolean} params.physics - Only for THREE.SkinnedMesh. Default is true. + * @param {Integer} params.warmup - Only for THREE.SkinnedMesh and physics is true. Default is 60. + * @param {Number} params.unitStep - Only for THREE.SkinnedMesh and physics is true. Default is 1 / 65. + * @param {Integer} params.maxStepNum - Only for THREE.SkinnedMesh and physics is true. Default is 3. + * @param {Vector3} params.gravity - Only for THREE.SkinnedMesh and physics is true. Default ( 0, - 9.8 * 10, 0 ). + * @param {Number} params.delayTime - Only for THREE.Audio. Default is 0.0. + * @return {MMDAnimationHelper} + */ + + + add( object, params = {} ) { if ( object.isSkinnedMesh ) { @@ -99,27 +85,23 @@ THREE.MMDAnimationHelper = ( function () { } else { - throw new Error( 'THREE.MMDAnimationHelper.add: ' - + 'accepts only ' - + 'THREE.SkinnedMesh or ' - + 'THREE.Camera or ' - + 'THREE.Audio instance.' ); + throw new Error( 'THREE.MMDAnimationHelper.add: ' + 'accepts only ' + 'THREE.SkinnedMesh or ' + 'THREE.Camera or ' + 'THREE.Audio instance.' ); } if ( this.configuration.sync ) this._syncDuration(); - return this; - }, - + } /** - * Removes an Three.js Object from helper. - * - * @param {THREE.SkinnedMesh|THREE.Camera|THREE.Audio} object - * @return {THREE.MMDAnimationHelper} - */ - remove: function ( object ) { + * Removes an Three.js Object from helper. + * + * @param {THREE.SkinnedMesh|THREE.Camera|THREE.Audio} object + * @return {MMDAnimationHelper} + */ + + + remove( object ) { if ( object.isSkinnedMesh ) { @@ -135,97 +117,86 @@ THREE.MMDAnimationHelper = ( function () { } else { - throw new Error( 'THREE.MMDAnimationHelper.remove: ' - + 'accepts only ' - + 'THREE.SkinnedMesh or ' - + 'THREE.Camera or ' - + 'THREE.Audio instance.' ); + throw new Error( 'THREE.MMDAnimationHelper.remove: ' + 'accepts only ' + 'THREE.SkinnedMesh or ' + 'THREE.Camera or ' + 'THREE.Audio instance.' ); } if ( this.configuration.sync ) this._syncDuration(); - return this; - }, - + } /** - * Updates the animation. - * - * @param {Number} delta - * @return {THREE.MMDAnimationHelper} - */ - update: function ( delta ) { + * Updates the animation. + * + * @param {Number} delta + * @return {MMDAnimationHelper} + */ + + + update( delta ) { if ( this.audioManager !== null ) this.audioManager.control( delta ); - for ( var i = 0; i < this.meshes.length; i ++ ) { + for ( let i = 0; i < this.meshes.length; i ++ ) { this._animateMesh( this.meshes[ i ], delta ); } if ( this.sharedPhysics ) this._updateSharedPhysics( delta ); - if ( this.camera !== null ) this._animateCamera( this.camera, delta ); - return this; - }, - + } /** - * Changes the pose of SkinnedMesh as VPD specifies. - * - * @param {THREE.SkinnedMesh} mesh - * @param {Object} vpd - VPD content parsed MMDParser - * @param {Object} params - (optional) - * @param {boolean} params.resetPose - Default is true. - * @param {boolean} params.ik - Default is true. - * @param {boolean} params.grant - Default is true. - * @return {THREE.MMDAnimationHelper} - */ - pose: function ( mesh, vpd, params ) { - - params = params || {}; + * Changes the pose of SkinnedMesh as VPD specifies. + * + * @param {THREE.SkinnedMesh} mesh + * @param {Object} vpd - VPD content parsed MMDParser + * @param {Object} params - (optional) + * @param {boolean} params.resetPose - Default is true. + * @param {boolean} params.ik - Default is true. + * @param {boolean} params.grant - Default is true. + * @return {MMDAnimationHelper} + */ - if ( params.resetPose !== false ) mesh.pose(); - var bones = mesh.skeleton.bones; - var boneParams = vpd.bones; + pose( mesh, vpd, params = {} ) { - var boneNameDictionary = {}; + if ( params.resetPose !== false ) mesh.pose(); + const bones = mesh.skeleton.bones; + const boneParams = vpd.bones; + const boneNameDictionary = {}; - for ( var i = 0, il = bones.length; i < il; i ++ ) { + for ( let i = 0, il = bones.length; i < il; i ++ ) { boneNameDictionary[ bones[ i ].name ] = i; } - var vector = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); + const vector = new THREE.Vector3(); + const quaternion = new THREE.Quaternion(); - for ( var i = 0, il = boneParams.length; i < il; i ++ ) { - - var boneParam = boneParams[ i ]; - var boneIndex = boneNameDictionary[ boneParam.name ]; + for ( let i = 0, il = boneParams.length; i < il; i ++ ) { + const boneParam = boneParams[ i ]; + const boneIndex = boneNameDictionary[ boneParam.name ]; if ( boneIndex === undefined ) continue; - - var bone = bones[ boneIndex ]; + const bone = bones[ boneIndex ]; bone.position.add( vector.fromArray( boneParam.translation ) ); bone.quaternion.multiply( quaternion.fromArray( boneParam.quaternion ) ); } - mesh.updateMatrixWorld( true ); + mesh.updateMatrixWorld( true ); // PMX animation system special path + + if ( this.configuration.pmxAnimation && mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx' ) { - // PMX animation system special path - if ( this.configuration.pmxAnimation && - mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx' ) { + const sortedBonesData = this._sortBoneDataArray( mesh.geometry.userData.MMD.bones.slice() ); + + const ikSolver = params.ik !== false ? this._createCCDIKSolver( mesh ) : null; + const grantSolver = params.grant !== false ? this.createGrantSolver( mesh ) : null; - var sortedBonesData = this._sortBoneDataArray( mesh.geometry.userData.MMD.bones.slice() ); - var ikSolver = params.ik !== false ? this._createCCDIKSolver( mesh ) : null; - var grantSolver = params.grant !== false ? this.createGrantSolver( mesh ) : null; this._animatePMXMesh( mesh, sortedBonesData, ikSolver, grantSolver ); } else { @@ -246,21 +217,21 @@ THREE.MMDAnimationHelper = ( function () { return this; - }, - + } /** - * Enabes/Disables an animation feature. - * - * @param {string} key - * @param {boolean} enabled - * @return {THREE.MMDAnimationHelper} - */ - enable: function ( key, enabled ) { + * Enabes/Disables an animation feature. + * + * @param {string} key + * @param {boolean} enabled + * @return {MMDAnimationHelper} + */ + + + enable( key, enabled ) { if ( this.enabled[ key ] === undefined ) { - throw new Error( 'THREE.MMDAnimationHelper.enable: ' - + 'unknown key ' + key ); + throw new Error( 'THREE.MMDAnimationHelper.enable: ' + 'unknown key ' + key ); } @@ -268,7 +239,7 @@ THREE.MMDAnimationHelper = ( function () { if ( key === 'physics' ) { - for ( var i = 0, il = this.meshes.length; i < il; i ++ ) { + for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { this._optimizeIK( this.meshes[ i ], enabled ); @@ -278,33 +249,34 @@ THREE.MMDAnimationHelper = ( function () { return this; - }, - + } /** - * Creates an GrantSolver instance. - * - * @param {THREE.SkinnedMesh} mesh - * @return {GrantSolver} - */ - createGrantSolver: function ( mesh ) { + * Creates an GrantSolver instance. + * + * @param {THREE.SkinnedMesh} mesh + * @return {GrantSolver} + */ + + + createGrantSolver( mesh ) { return new GrantSolver( mesh, mesh.geometry.userData.MMD.grants ); - }, + } // private methods - // private methods - _addMesh: function ( mesh, params ) { + _addMesh( mesh, params ) { if ( this.meshes.indexOf( mesh ) >= 0 ) { - throw new Error( 'THREE.MMDAnimationHelper._addMesh: ' - + 'SkinnedMesh \'' + mesh.name + '\' has already been added.' ); + throw new Error( 'THREE.MMDAnimationHelper._addMesh: ' + 'SkinnedMesh \'' + mesh.name + '\' has already been added.' ); } this.meshes.push( mesh ); - this.objects.set( mesh, { looped: false } ); + this.objects.set( mesh, { + looped: false + } ); this._setupMeshAnimation( mesh, params.animation ); @@ -316,23 +288,19 @@ THREE.MMDAnimationHelper = ( function () { return this; - }, + } - _setupCamera: function ( camera, params ) { + _setupCamera( camera, params ) { if ( this.camera === camera ) { - throw new Error( 'THREE.MMDAnimationHelper._setupCamera: ' - + 'Camera \'' + camera.name + '\' has already been set.' ); + throw new Error( 'THREE.MMDAnimationHelper._setupCamera: ' + 'Camera \'' + camera.name + '\' has already been set.' ); } if ( this.camera ) this.clearCamera( this.camera ); - this.camera = camera; - camera.add( this.cameraTarget ); - this.objects.set( camera, {} ); if ( params.animation !== undefined ) { @@ -343,42 +311,37 @@ THREE.MMDAnimationHelper = ( function () { return this; - }, + } - _setupAudio: function ( audio, params ) { + _setupAudio( audio, params ) { if ( this.audio === audio ) { - throw new Error( 'THREE.MMDAnimationHelper._setupAudio: ' - + 'Audio \'' + audio.name + '\' has already been set.' ); + throw new Error( 'THREE.MMDAnimationHelper._setupAudio: ' + 'Audio \'' + audio.name + '\' has already been set.' ); } if ( this.audio ) this.clearAudio( this.audio ); - this.audio = audio; this.audioManager = new AudioManager( audio, params ); - this.objects.set( this.audioManager, { duration: this.audioManager.duration } ); - return this; - }, + } - _removeMesh: function ( mesh ) { + _removeMesh( mesh ) { - var found = false; - var writeIndex = 0; + let found = false; + let writeIndex = 0; - for ( var i = 0, il = this.meshes.length; i < il; i ++ ) { + for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { if ( this.meshes[ i ] === mesh ) { this.objects.delete( mesh ); found = true; - continue; } @@ -389,78 +352,65 @@ THREE.MMDAnimationHelper = ( function () { if ( ! found ) { - throw new Error( 'THREE.MMDAnimationHelper._removeMesh: ' - + 'SkinnedMesh \'' + mesh.name + '\' has not been added yet.' ); + throw new Error( 'THREE.MMDAnimationHelper._removeMesh: ' + 'SkinnedMesh \'' + mesh.name + '\' has not been added yet.' ); } this.meshes.length = writeIndex; - return this; - }, + } - _clearCamera: function ( camera ) { + _clearCamera( camera ) { if ( camera !== this.camera ) { - throw new Error( 'THREE.MMDAnimationHelper._clearCamera: ' - + 'Camera \'' + camera.name + '\' has not been set yet.' ); + throw new Error( 'THREE.MMDAnimationHelper._clearCamera: ' + 'Camera \'' + camera.name + '\' has not been set yet.' ); } this.camera.remove( this.cameraTarget ); - this.objects.delete( this.camera ); this.camera = null; - return this; - }, + } - _clearAudio: function ( audio ) { + _clearAudio( audio ) { if ( audio !== this.audio ) { - throw new Error( 'THREE.MMDAnimationHelper._clearAudio: ' - + 'Audio \'' + audio.name + '\' has not been set yet.' ); + throw new Error( 'THREE.MMDAnimationHelper._clearAudio: ' + 'Audio \'' + audio.name + '\' has not been set yet.' ); } this.objects.delete( this.audioManager ); - this.audio = null; this.audioManager = null; - return this; - }, + } - _setupMeshAnimation: function ( mesh, animation ) { + _setupMeshAnimation( mesh, animation ) { - var objects = this.objects.get( mesh ); + const objects = this.objects.get( mesh ); if ( animation !== undefined ) { - var animations = Array.isArray( animation ) - ? animation : [ animation ]; - + const animations = Array.isArray( animation ) ? animation : [ animation ]; objects.mixer = new THREE.AnimationMixer( mesh ); - for ( var i = 0, il = animations.length; i < il; i ++ ) { + for ( let i = 0, il = animations.length; i < il; i ++ ) { objects.mixer.clipAction( animations[ i ] ).play(); - } - - // TODO: find a workaround not to access ._clip looking like a private property - objects.mixer.addEventListener( 'loop', function ( event ) { + } // TODO: find a workaround not to access ._clip looking like a private property - var tracks = event.action._clip.tracks; - if ( tracks.length > 0 && - tracks[ 0 ].name.slice( 0, 6 ) !== '.bones' ) return; + objects.mixer.addEventListener( 'loop', function ( event ) { + const tracks = event.action._clip.tracks; + if ( tracks.length > 0 && tracks[ 0 ].name.slice( 0, 6 ) !== '.bones' ) return; objects.looped = true; } ); @@ -469,37 +419,31 @@ THREE.MMDAnimationHelper = ( function () { objects.ikSolver = this._createCCDIKSolver( mesh ); objects.grantSolver = this.createGrantSolver( mesh ); - return this; - }, - - _setupCameraAnimation: function ( camera, animation ) { - - var animations = Array.isArray( animation ) - ? animation : [ animation ]; + } - var objects = this.objects.get( camera ); + _setupCameraAnimation( camera, animation ) { + const animations = Array.isArray( animation ) ? animation : [ animation ]; + const objects = this.objects.get( camera ); objects.mixer = new THREE.AnimationMixer( camera ); - for ( var i = 0, il = animations.length; i < il; i ++ ) { + for ( let i = 0, il = animations.length; i < il; i ++ ) { objects.mixer.clipAction( animations[ i ] ).play(); } - }, - - _setupMeshPhysics: function ( mesh, params ) { + } - var objects = this.objects.get( mesh ); + _setupMeshPhysics( mesh, params ) { - // shared physics is experimental + const objects = this.objects.get( mesh ); // shared physics is experimental if ( params.world === undefined && this.sharedPhysics ) { - var masterPhysics = this._getMasterPhysics(); + const masterPhysics = this._getMasterPhysics(); if ( masterPhysics !== null ) world = masterPhysics.world; // eslint-disable-line no-undef @@ -510,6 +454,7 @@ THREE.MMDAnimationHelper = ( function () { if ( objects.mixer && params.animationWarmup !== false ) { this._animateMesh( mesh, 0 ); + objects.physics.reset(); } @@ -518,42 +463,34 @@ THREE.MMDAnimationHelper = ( function () { this._optimizeIK( mesh, true ); - }, - - _animateMesh: function ( mesh, delta ) { + } - var objects = this.objects.get( mesh ); + _animateMesh( mesh, delta ) { - var mixer = objects.mixer; - var ikSolver = objects.ikSolver; - var grantSolver = objects.grantSolver; - var physics = objects.physics; - var looped = objects.looped; + const objects = this.objects.get( mesh ); + const mixer = objects.mixer; + const ikSolver = objects.ikSolver; + const grantSolver = objects.grantSolver; + const physics = objects.physics; + const looped = objects.looped; if ( mixer && this.enabled.animation ) { // alternate solution to save/restore bones but less performant? //mesh.pose(); //this._updatePropertyMixersBuffer( mesh ); - this._restoreBones( mesh ); mixer.update( delta ); - this._saveBones( mesh ); + this._saveBones( mesh ); // PMX animation system special path + - // PMX animation system special path - if ( this.configuration.pmxAnimation && - mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx' ) { + if ( this.configuration.pmxAnimation && mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx' ) { if ( ! objects.sortedBonesData ) objects.sortedBonesData = this._sortBoneDataArray( mesh.geometry.userData.MMD.bones.slice() ); - this._animatePMXMesh( - mesh, - objects.sortedBonesData, - ikSolver && this.enabled.ik ? ikSolver : null, - grantSolver && this.enabled.grant ? grantSolver : null - ); + this._animatePMXMesh( mesh, objects.sortedBonesData, ikSolver && this.enabled.ik ? ikSolver : null, grantSolver && this.enabled.grant ? grantSolver : null ); } else { @@ -577,7 +514,6 @@ THREE.MMDAnimationHelper = ( function () { if ( looped === true && this.enabled.physics ) { if ( physics && this.configuration.resetPhysicsOnLoop ) physics.reset(); - objects.looped = false; } @@ -589,12 +525,12 @@ THREE.MMDAnimationHelper = ( function () { } - }, - - // Sort bones in order by 1. transformationClass and 2. bone index. + } // Sort bones in order by 1. transformationClass and 2. bone index. // In PMX animation system, bone transformations should be processed // in this order. - _sortBoneDataArray: function ( boneDataArray ) { + + + _sortBoneDataArray( boneDataArray ) { return boneDataArray.sort( function ( a, b ) { @@ -610,154 +546,61 @@ THREE.MMDAnimationHelper = ( function () { } ); - }, - - // PMX Animation system is a bit too complex and doesn't great match to + } // PMX Animation system is a bit too complex and doesn't great match to // Three.js Animation system. This method attempts to simulate it as much as // possible but doesn't perfectly simulate. // This method is more costly than the regular one so // you are recommended to set constructor parameter "pmxAnimation: true" // only if your PMX model animation doesn't work well. // If you need better method you would be required to write your own. - _animatePMXMesh: function () { - - // Keep working quaternions for less GC - var quaternions = []; - var quaternionIndex = 0; - - function getQuaternion() { - - if ( quaternionIndex >= quaternions.length ) { - - quaternions.push( new THREE.Quaternion() ); - - } - - return quaternions[ quaternionIndex ++ ]; - - } - - // Save rotation whose grant and IK are already applied - // used by grant children - var grantResultMap = new Map(); - - function updateOne( mesh, boneIndex, ikSolver, grantSolver ) { - - var bones = mesh.skeleton.bones; - var bonesData = mesh.geometry.userData.MMD.bones; - var boneData = bonesData[ boneIndex ]; - var bone = bones[ boneIndex ]; - - // Return if already updated by being referred as a grant parent. - if ( grantResultMap.has( boneIndex ) ) return; - - var quaternion = getQuaternion(); - - // Initialize grant result here to prevent infinite loop. - // If it's referred before updating with actual result later - // result without applyting IK or grant is gotten - // but better than composing of infinite loop. - grantResultMap.set( boneIndex, quaternion.copy( bone.quaternion ) ); - - // @TODO: Support global grant and grant position - if ( grantSolver && boneData.grant && - ! boneData.grant.isLocal && boneData.grant.affectRotation ) { - - var parentIndex = boneData.grant.parentIndex; - var ratio = boneData.grant.ratio; - - if ( ! grantResultMap.has( parentIndex ) ) { - - updateOne( mesh, parentIndex, ikSolver, grantSolver ); - - } - - grantSolver.addGrantRotation( bone, grantResultMap.get( parentIndex ), ratio ); - - } - - if ( ikSolver && boneData.ik ) { - - // @TODO: Updating world matrices every time solving an IK bone is - // costly. Optimize if possible. - mesh.updateMatrixWorld( true ); - ikSolver.updateOne( boneData.ik ); - - // No confident, but it seems the grant results with ik links should be updated? - var links = boneData.ik.links; - - for ( var i = 0, il = links.length; i < il; i ++ ) { - var link = links[ i ]; - if ( link.enabled === false ) continue; + _animatePMXMesh( mesh, sortedBonesData, ikSolver, grantSolver ) { - var linkIndex = link.index; + _quaternionIndex = 0; - if ( grantResultMap.has( linkIndex ) ) { + _grantResultMap.clear(); - grantResultMap.set( linkIndex, grantResultMap.get( linkIndex ).copy( bones[ linkIndex ].quaternion ) ); + for ( let i = 0, il = sortedBonesData.length; i < il; i ++ ) { - } - - } - - } - - // Update with the actual result here - quaternion.copy( bone.quaternion ); + updateOne( mesh, sortedBonesData[ i ].index, ikSolver, grantSolver ); } - return function ( mesh, sortedBonesData, ikSolver, grantSolver ) { - - quaternionIndex = 0; - grantResultMap.clear(); - - for ( var i = 0, il = sortedBonesData.length; i < il; i ++ ) { - - updateOne( mesh, sortedBonesData[ i ].index, ikSolver, grantSolver ); - - } - - mesh.updateMatrixWorld( true ); - return this; - - }; + mesh.updateMatrixWorld( true ); + return this; - }(), + } - _animateCamera: function ( camera, delta ) { + _animateCamera( camera, delta ) { - var mixer = this.objects.get( camera ).mixer; + const mixer = this.objects.get( camera ).mixer; if ( mixer && this.enabled.cameraAnimation ) { mixer.update( delta ); - camera.updateProjectionMatrix(); - camera.up.set( 0, 1, 0 ); camera.up.applyQuaternion( camera.quaternion ); camera.lookAt( this.cameraTarget.position ); } - }, + } - _optimizeIK: function ( mesh, physicsEnabled ) { + _optimizeIK( mesh, physicsEnabled ) { - var iks = mesh.geometry.userData.MMD.iks; - var bones = mesh.geometry.userData.MMD.bones; + const iks = mesh.geometry.userData.MMD.iks; + const bones = mesh.geometry.userData.MMD.bones; - for ( var i = 0, il = iks.length; i < il; i ++ ) { + for ( let i = 0, il = iks.length; i < il; i ++ ) { - var ik = iks[ i ]; - var links = ik.links; + const ik = iks[ i ]; + const links = ik.links; - for ( var j = 0, jl = links.length; j < jl; j ++ ) { + for ( let j = 0, jl = links.length; j < jl; j ++ ) { - var link = links[ j ]; + const link = links[ j ]; if ( physicsEnabled === true ) { @@ -775,9 +618,9 @@ THREE.MMDAnimationHelper = ( function () { } - }, + } - _createCCDIKSolver: function ( mesh ) { + _createCCDIKSolver( mesh ) { if ( THREE.CCDIKSolver === undefined ) { @@ -787,9 +630,9 @@ THREE.MMDAnimationHelper = ( function () { return new THREE.CCDIKSolver( mesh, mesh.geometry.userData.MMD.iks ); - }, + } - _createMMDPhysics: function ( mesh, params ) { + _createMMDPhysics( mesh, params ) { if ( THREE.MMDPhysics === undefined ) { @@ -797,38 +640,31 @@ THREE.MMDAnimationHelper = ( function () { } - return new THREE.MMDPhysics( - mesh, - mesh.geometry.userData.MMD.rigidBodies, - mesh.geometry.userData.MMD.constraints, - params ); - - }, + return new THREE.MMDPhysics( mesh, mesh.geometry.userData.MMD.rigidBodies, mesh.geometry.userData.MMD.constraints, params ); + } /* - * Detects the longest duration and then sets it to them to sync. - * TODO: Not to access private properties ( ._actions and ._clip ) - */ - _syncDuration: function () { + * Detects the longest duration and then sets it to them to sync. + * TODO: Not to access private properties ( ._actions and ._clip ) + */ - var max = 0.0; - var objects = this.objects; - var meshes = this.meshes; - var camera = this.camera; - var audioManager = this.audioManager; + _syncDuration() { - // get the longest duration + let max = 0.0; + const objects = this.objects; + const meshes = this.meshes; + const camera = this.camera; + const audioManager = this.audioManager; // get the longest duration - for ( var i = 0, il = meshes.length; i < il; i ++ ) { - - var mixer = this.objects.get( meshes[ i ] ).mixer; + for ( let i = 0, il = meshes.length; i < il; i ++ ) { + const mixer = this.objects.get( meshes[ i ] ).mixer; if ( mixer === undefined ) continue; - for ( var j = 0; j < mixer._actions.length; j ++ ) { + for ( let j = 0; j < mixer._actions.length; j ++ ) { - var clip = mixer._actions[ j ]._clip; + const clip = mixer._actions[ j ]._clip; if ( ! objects.has( clip ) ) { @@ -846,13 +682,13 @@ THREE.MMDAnimationHelper = ( function () { if ( camera !== null ) { - var mixer = this.objects.get( camera ).mixer; + const mixer = this.objects.get( camera ).mixer; if ( mixer !== undefined ) { - for ( var i = 0, il = mixer._actions.length; i < il; i ++ ) { + for ( let i = 0, il = mixer._actions.length; i < il; i ++ ) { - var clip = mixer._actions[ i ]._clip; + const clip = mixer._actions[ i ]._clip; if ( ! objects.has( clip ) ) { @@ -876,17 +712,14 @@ THREE.MMDAnimationHelper = ( function () { } - max += this.configuration.afterglow; - - // update the duration - - for ( var i = 0, il = this.meshes.length; i < il; i ++ ) { + max += this.configuration.afterglow; // update the duration - var mixer = this.objects.get( this.meshes[ i ] ).mixer; + for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { + const mixer = this.objects.get( this.meshes[ i ] ).mixer; if ( mixer === undefined ) continue; - for ( var j = 0, jl = mixer._actions.length; j < jl; j ++ ) { + for ( let j = 0, jl = mixer._actions.length; j < jl; j ++ ) { mixer._actions[ j ]._clip.duration = max; @@ -896,11 +729,11 @@ THREE.MMDAnimationHelper = ( function () { if ( camera !== null ) { - var mixer = this.objects.get( camera ).mixer; + const mixer = this.objects.get( camera ).mixer; if ( mixer !== undefined ) { - for ( var i = 0, il = mixer._actions.length; i < il; i ++ ) { + for ( let i = 0, il = mixer._actions.length; i < il; i ++ ) { mixer._actions[ i ]._clip.duration = max; @@ -916,46 +749,42 @@ THREE.MMDAnimationHelper = ( function () { } - }, + } // workaround - // workaround - _updatePropertyMixersBuffer: function ( mesh ) { + _updatePropertyMixersBuffer( mesh ) { - var mixer = this.objects.get( mesh ).mixer; + const mixer = this.objects.get( mesh ).mixer; + const propertyMixers = mixer._bindings; + const accuIndex = mixer._accuIndex; - var propertyMixers = mixer._bindings; - var accuIndex = mixer._accuIndex; - - for ( var i = 0, il = propertyMixers.length; i < il; i ++ ) { - - var propertyMixer = propertyMixers[ i ]; - var buffer = propertyMixer.buffer; - var stride = propertyMixer.valueSize; - var offset = ( accuIndex + 1 ) * stride; + for ( let i = 0, il = propertyMixers.length; i < il; i ++ ) { + const propertyMixer = propertyMixers[ i ]; + const buffer = propertyMixer.buffer; + const stride = propertyMixer.valueSize; + const offset = ( accuIndex + 1 ) * stride; propertyMixer.binding.getValue( buffer, offset ); } - }, - + } /* - * Avoiding these two issues by restore/save bones before/after mixer animation. - * - * 1. PropertyMixer used by AnimationMixer holds cache value in .buffer. - * Calculating IK, Grant, and Physics after mixer animation can break - * the cache coherency. - * - * 2. Applying Grant two or more times without reset the posing breaks model. - */ - _saveBones: function ( mesh ) { + * Avoiding these two issues by restore/save bones before/after mixer animation. + * + * 1. PropertyMixer used by THREE.AnimationMixer holds cache value in .buffer. + * Calculating IK, Grant, and Physics after mixer animation can break + * the cache coherency. + * + * 2. Applying Grant two or more times without reset the posing breaks model. + */ - var objects = this.objects.get( mesh ); - var bones = mesh.skeleton.bones; + _saveBones( mesh ) { - var backupBones = objects.backupBones; + const objects = this.objects.get( mesh ); + const bones = mesh.skeleton.bones; + let backupBones = objects.backupBones; if ( backupBones === undefined ) { @@ -964,45 +793,41 @@ THREE.MMDAnimationHelper = ( function () { } - for ( var i = 0, il = bones.length; i < il; i ++ ) { + for ( let i = 0, il = bones.length; i < il; i ++ ) { - var bone = bones[ i ]; + const bone = bones[ i ]; bone.position.toArray( backupBones, i * 7 ); bone.quaternion.toArray( backupBones, i * 7 + 3 ); } - }, - - _restoreBones: function ( mesh ) { - - var objects = this.objects.get( mesh ); + } - var backupBones = objects.backupBones; + _restoreBones( mesh ) { + const objects = this.objects.get( mesh ); + const backupBones = objects.backupBones; if ( backupBones === undefined ) return; + const bones = mesh.skeleton.bones; - var bones = mesh.skeleton.bones; + for ( let i = 0, il = bones.length; i < il; i ++ ) { - for ( var i = 0, il = bones.length; i < il; i ++ ) { - - var bone = bones[ i ]; + const bone = bones[ i ]; bone.position.fromArray( backupBones, i * 7 ); bone.quaternion.fromArray( backupBones, i * 7 + 3 ); } - }, + } // experimental - // experimental - _getMasterPhysics: function () { + _getMasterPhysics() { if ( this.masterPhysics !== null ) return this.masterPhysics; - for ( var i = 0, il = this.meshes.length; i < il; i ++ ) { + for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { - var physics = this.meshes[ i ].physics; + const physics = this.meshes[ i ].physics; if ( physics !== undefined && physics !== null ) { @@ -1015,19 +840,19 @@ THREE.MMDAnimationHelper = ( function () { return null; - }, + } - _updateSharedPhysics: function ( delta ) { + _updateSharedPhysics( delta ) { if ( this.meshes.length === 0 || ! this.enabled.physics || ! this.sharedPhysics ) return; - var physics = this._getMasterPhysics(); + const physics = this._getMasterPhysics(); if ( physics === null ) return; - for ( var i = 0, il = this.meshes.length; i < il; i ++ ) { + for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { - var p = this.meshes[ i ].physics; + const p = this.meshes[ i ].physics; if ( p !== null && p !== undefined ) { @@ -1039,9 +864,9 @@ THREE.MMDAnimationHelper = ( function () { physics.stepSimulation( delta ); - for ( var i = 0, il = this.meshes.length; i < il; i ++ ) { + for ( let i = 0, il = this.meshes.length; i < il; i ++ ) { - var p = this.meshes[ i ].physics; + const p = this.meshes[ i ].physics; if ( p !== null && p !== undefined ) { @@ -1053,54 +878,125 @@ THREE.MMDAnimationHelper = ( function () { } - }; + } // Keep working quaternions for less GC - // - /** - * @param {THREE.Audio} audio - * @param {Object} params - (optional) - * @param {Nuumber} params.delayTime - */ - function AudioManager( audio, params ) { + const _quaternions = []; + let _quaternionIndex = 0; - params = params || {}; + function getQuaternion() { - this.audio = audio; + if ( _quaternionIndex >= _quaternions.length ) { - this.elapsedTime = 0.0; - this.currentTime = 0.0; - this.delayTime = params.delayTime !== undefined - ? params.delayTime : 0.0; + _quaternions.push( new THREE.Quaternion() ); - this.audioDuration = this.audio.buffer.duration; - this.duration = this.audioDuration + this.delayTime; + } - } + return _quaternions[ _quaternionIndex ++ ]; + + } // Save rotation whose grant and IK are already applied + // used by grant children + + + const _grantResultMap = new Map(); + + function updateOne( mesh, boneIndex, ikSolver, grantSolver ) { + + const bones = mesh.skeleton.bones; + const bonesData = mesh.geometry.userData.MMD.bones; + const boneData = bonesData[ boneIndex ]; + const bone = bones[ boneIndex ]; // Return if already updated by being referred as a grant parent. + + if ( _grantResultMap.has( boneIndex ) ) return; + const quaternion = getQuaternion(); // Initialize grant result here to prevent infinite loop. + // If it's referred before updating with actual result later + // result without applyting IK or grant is gotten + // but better than composing of infinite loop. + + _grantResultMap.set( boneIndex, quaternion.copy( bone.quaternion ) ); // @TODO: Support global grant and grant position + + + if ( grantSolver && boneData.grant && ! boneData.grant.isLocal && boneData.grant.affectRotation ) { + + const parentIndex = boneData.grant.parentIndex; + const ratio = boneData.grant.ratio; + + if ( ! _grantResultMap.has( parentIndex ) ) { + + updateOne( mesh, parentIndex, ikSolver, grantSolver ); + + } + + grantSolver.addGrantRotation( bone, _grantResultMap.get( parentIndex ), ratio ); - AudioManager.prototype = { + } + + if ( ikSolver && boneData.ik ) { + + // @TODO: Updating world matrices every time solving an IK bone is + // costly. Optimize if possible. + mesh.updateMatrixWorld( true ); + ikSolver.updateOne( boneData.ik ); // No confident, but it seems the grant results with ik links should be updated? + + const links = boneData.ik.links; + + for ( let i = 0, il = links.length; i < il; i ++ ) { + + const link = links[ i ]; + if ( link.enabled === false ) continue; + const linkIndex = link.index; + + if ( _grantResultMap.has( linkIndex ) ) { + + _grantResultMap.set( linkIndex, _grantResultMap.get( linkIndex ).copy( bones[ linkIndex ].quaternion ) ); + + } + + } + + } // Update with the actual result here - constructor: AudioManager, + + quaternion.copy( bone.quaternion ); + + } // + + + class AudioManager { /** - * @param {Number} delta - * @return {AudioManager} - */ - control: function ( delta ) { + * @param {THREE.Audio} audio + * @param {Object} params - (optional) + * @param {Nuumber} params.delayTime + */ + constructor( audio, params = {} ) { + + this.audio = audio; + this.elapsedTime = 0.0; + this.currentTime = 0.0; + this.delayTime = params.delayTime !== undefined ? params.delayTime : 0.0; + this.audioDuration = this.audio.buffer.duration; + this.duration = this.audioDuration + this.delayTime; + + } + /** + * @param {Number} delta + * @return {AudioManager} + */ + + + control( delta ) { this.elapsed += delta; this.currentTime += delta; - if ( this._shouldStopAudio() ) this.audio.stop(); if ( this._shouldStartAudio() ) this.audio.play(); - return this; - }, + } // private methods - // private methods - _shouldStartAudio: function () { + _shouldStartAudio() { if ( this.audio.isPlaying ) return false; @@ -1110,52 +1006,51 @@ THREE.MMDAnimationHelper = ( function () { } - if ( this.currentTime < this.delayTime ) return false; - - // 'duration' can be bigger than 'audioDuration + delayTime' because of sync configuration - if ( ( this.currentTime - this.delayTime ) > this.audioDuration ) return false; + if ( this.currentTime < this.delayTime ) return false; // 'duration' can be bigger than 'audioDuration + delayTime' because of sync configuration + if ( this.currentTime - this.delayTime > this.audioDuration ) return false; return true; - }, + } - _shouldStopAudio: function () { + _shouldStopAudio() { - return this.audio.isPlaying && - this.currentTime >= this.duration; + return this.audio.isPlaying && this.currentTime >= this.duration; } - }; + } + const _q = new THREE.Quaternion(); /** - * Solver for Grant (Fuyo in Japanese. I just google translated because - * Fuyo may be MMD specific term and may not be common word in 3D CG terms.) - * Grant propagates a bone's transform to other bones transforms even if - * they are not children. - * @param {THREE.SkinnedMesh} mesh - * @param {Array} grants - */ - function GrantSolver( mesh, grants ) { - - this.mesh = mesh; - this.grants = grants || []; + * Solver for Grant (Fuyo in Japanese. I just google translated because + * Fuyo may be MMD specific term and may not be common word in 3D CG terms.) + * Grant propagates a bone's transform to other bones transforms even if + * they are not children. + * @param {THREE.SkinnedMesh} mesh + * @param {Array} grants + */ - } - GrantSolver.prototype = { + class GrantSolver { + + constructor( mesh, grants = [] ) { - constructor: GrantSolver, + this.mesh = mesh; + this.grants = grants; + } /** - * Solve all the grant bones - * @return {GrantSolver} - */ - update: function () { + * Solve all the grant bones + * @return {GrantSolver} + */ - var grants = this.grants; - for ( var i = 0, il = grants.length; i < il; i ++ ) { + update() { + + const grants = this.grants; + + for ( let i = 0, il = grants.length; i < il; i ++ ) { this.updateOne( grants[ i ] ); @@ -1163,37 +1058,32 @@ THREE.MMDAnimationHelper = ( function () { return this; - }, - + } /** - * Solve a grant bone - * @param {Object} grant - grant parameter - * @return {GrantSolver} - */ - updateOne: function ( grant ) { + * Solve a grant bone + * @param {Object} grant - grant parameter + * @return {GrantSolver} + */ - var bones = this.mesh.skeleton.bones; - var bone = bones[ grant.index ]; - var parentBone = bones[ grant.parentIndex ]; - if ( grant.isLocal ) { + updateOne( grant ) { - // TODO: implement - if ( grant.affectPosition ) { + const bones = this.mesh.skeleton.bones; + const bone = bones[ grant.index ]; + const parentBone = bones[ grant.parentIndex ]; - } + if ( grant.isLocal ) { // TODO: implement - if ( grant.affectRotation ) { + if ( grant.affectPosition ) {} // TODO: implement - } + + if ( grant.affectRotation ) {} } else { // TODO: implement - if ( grant.affectPosition ) { - - } + if ( grant.affectPosition ) {} if ( grant.affectRotation ) { @@ -1205,26 +1095,21 @@ THREE.MMDAnimationHelper = ( function () { return this; - }, - - addGrantRotation: function () { - - var quaternion = new THREE.Quaternion(); + } - return function ( bone, q, ratio ) { + addGrantRotation( bone, q, ratio ) { - quaternion.set( 0, 0, 0, 1 ); - quaternion.slerp( q, ratio ); - bone.quaternion.multiply( quaternion ); + _q.set( 0, 0, 0, 1 ); - return this; + _q.slerp( q, ratio ); - }; + bone.quaternion.multiply( _q ); + return this; - }() + } - }; + } - return MMDAnimationHelper; + THREE.MMDAnimationHelper = MMDAnimationHelper; } )(); diff --git a/examples/js/animation/MMDPhysics.js b/examples/js/animation/MMDPhysics.js index bd330dcd816f84..320eb88a282527 100644 --- a/examples/js/animation/MMDPhysics.js +++ b/examples/js/animation/MMDPhysics.js @@ -1,88 +1,77 @@ -/** +( function () { + + /** * Dependencies * - Ammo.js https://github.com/kripken/ammo.js * * MMDPhysics calculates physics with Ammo(Bullet based JavaScript Physics engine) - * for MMD model loaded by THREE.MMDLoader. + * for MMD model loaded by MMDLoader. * * TODO * - Physics in Worker */ -/* global Ammo */ - -THREE.MMDPhysics = ( function () { - - /** - * @param {THREE.SkinnedMesh} mesh - * @param {Array} rigidBodyParams - * @param {Array} (optional) constraintParams - * @param {Object} params - (optional) - * @param {Number} params.unitStep - Default is 1 / 65. - * @param {Integer} params.maxStepNum - Default is 3. - * @param {THREE.Vector3} params.gravity - Default is ( 0, - 9.8 * 10, 0 ) - */ - function MMDPhysics( mesh, rigidBodyParams, constraintParams, params ) { - - if ( typeof Ammo === 'undefined' ) { + /* global Ammo */ - throw new Error( 'THREE.MMDPhysics: Import ammo.js https://github.com/kripken/ammo.js' ); - - } + class MMDPhysics { - constraintParams = constraintParams || []; - params = params || {}; - - this.manager = new ResourceManager(); - - this.mesh = mesh; - - /* - * I don't know why but 1/60 unitStep easily breaks models - * so I set it 1/65 so far. - * Don't set too small unitStep because - * the smaller unitStep can make the performance worse. - */ - this.unitStep = ( params.unitStep !== undefined ) ? params.unitStep : 1 / 65; - this.maxStepNum = ( params.maxStepNum !== undefined ) ? params.maxStepNum : 3; - this.gravity = new THREE.Vector3( 0, - 9.8 * 10, 0 ); + /** + * @param {THREE.SkinnedMesh} mesh + * @param {Array} rigidBodyParams + * @param {Array} (optional) constraintParams + * @param {Object} params - (optional) + * @param {Number} params.unitStep - Default is 1 / 65. + * @param {Integer} params.maxStepNum - Default is 3. + * @param {Vector3} params.gravity - Default is ( 0, - 9.8 * 10, 0 ) + */ + constructor( mesh, rigidBodyParams, constraintParams = [], params = {} ) { - if ( params.gravity !== undefined ) this.gravity.copy( params.gravity ); + if ( typeof Ammo === 'undefined' ) { - this.world = params.world !== undefined ? params.world : null; // experimental + throw new Error( 'THREE.MMDPhysics: Import ammo.js https://github.com/kripken/ammo.js' ); - this.bodies = []; - this.constraints = []; + } - this._init( mesh, rigidBodyParams, constraintParams ); + this.manager = new ResourceManager(); + this.mesh = mesh; + /* + * I don't know why but 1/60 unitStep easily breaks models + * so I set it 1/65 so far. + * Don't set too small unitStep because + * the smaller unitStep can make the performance worse. + */ - } + this.unitStep = params.unitStep !== undefined ? params.unitStep : 1 / 65; + this.maxStepNum = params.maxStepNum !== undefined ? params.maxStepNum : 3; + this.gravity = new THREE.Vector3( 0, - 9.8 * 10, 0 ); + if ( params.gravity !== undefined ) this.gravity.copy( params.gravity ); + this.world = params.world !== undefined ? params.world : null; // experimental - MMDPhysics.prototype = { + this.bodies = []; + this.constraints = []; - constructor: MMDPhysics, + this._init( mesh, rigidBodyParams, constraintParams ); + } /** - * Advances Physics calculation and updates bones. - * - * @param {Number} delta - time in second - * @return {THREE.MMDPhysics} - */ - update: function ( delta ) { + * Advances Physics calculation and updates bones. + * + * @param {Number} delta - time in second + * @return {MMDPhysics} + */ + - var manager = this.manager; - var mesh = this.mesh; + update( delta ) { - // rigid bodies and constrains are for + const manager = this.manager; + const mesh = this.mesh; // rigid bodies and constrains are for // mesh's world scale (1, 1, 1). // Convert to (1, 1, 1) if it isn't. - var isNonDefaultScale = false; - - var position = manager.allocThreeVector3(); - var quaternion = manager.allocThreeQuaternion(); - var scale = manager.allocThreeVector3(); - + let isNonDefaultScale = false; + const position = manager.allocThreeVector3(); + const quaternion = manager.allocThreeQuaternion(); + const scale = manager.allocThreeVector3(); mesh.matrixWorld.decompose( position, quaternion, scale ); if ( scale.x !== 1 || scale.y !== 1 || scale.z !== 1 ) { @@ -91,33 +80,29 @@ THREE.MMDPhysics = ( function () { } - var parent; + let parent; if ( isNonDefaultScale ) { parent = mesh.parent; - if ( parent !== null ) mesh.parent = null; - scale.copy( this.mesh.scale ); - mesh.scale.set( 1, 1, 1 ); mesh.updateMatrixWorld( true ); - } + } // calculate physics and update bones - // calculate physics and update bones this._updateRigidBodies(); + this._stepSimulation( delta ); - this._updateBones(); - // restore mesh if converted above + this._updateBones(); // restore mesh if converted above + if ( isNonDefaultScale ) { if ( parent !== null ) mesh.parent = parent; - mesh.scale.copy( scale ); } @@ -125,19 +110,19 @@ THREE.MMDPhysics = ( function () { manager.freeThreeVector3( scale ); manager.freeThreeQuaternion( quaternion ); manager.freeThreeVector3( position ); - return this; - }, - + } /** - * Resets rigid bodies transorm to current bone's. - * - * @return {THREE.MMDPhysics} - */ - reset: function () { + * Resets rigid bodies transorm to current bone's. + * + * @return {MMDPhysics} + */ + - for ( var i = 0, il = this.bodies.length; i < il; i ++ ) { + reset() { + + for ( let i = 0, il = this.bodies.length; i < il; i ++ ) { this.bodies[ i ].reset(); @@ -145,17 +130,18 @@ THREE.MMDPhysics = ( function () { return this; - }, - + } /** - * Warm ups Rigid bodies. Calculates cycles steps. - * - * @param {Integer} cycles - * @return {THREE.MMDPhysics} - */ - warmup: function ( cycles ) { + * Warm ups Rigid bodies. Calculates cycles steps. + * + * @param {Integer} cycles + * @return {MMDPhysics} + */ + - for ( var i = 0; i < cycles; i ++ ) { + warmup( cycles ) { + + for ( let i = 0; i < cycles; i ++ ) { this.update( 1 / 60 ); @@ -163,60 +149,53 @@ THREE.MMDPhysics = ( function () { return this; - }, - + } /** - * Sets gravity. - * - * @param {THREE.Vector3} gravity - * @return {MMDPhysicsHelper} - */ - setGravity: function ( gravity ) { + * Sets gravity. + * + * @param {Vector3} gravity + * @return {MMDPhysicsHelper} + */ + + + setGravity( gravity ) { this.world.setGravity( new Ammo.btVector3( gravity.x, gravity.y, gravity.z ) ); this.gravity.copy( gravity ); - return this; - }, - + } /** - * Creates MMDPhysicsHelper - * - * @return {MMDPhysicsHelper} - */ - createHelper: function () { + * Creates MMDPhysicsHelper + * + * @return {MMDPhysicsHelper} + */ - return new MMDPhysicsHelper( this.mesh, this ); - }, + createHelper() { + + return new MMDPhysicsHelper( this.mesh, this ); - // private methods + } // private methods - _init: function ( mesh, rigidBodyParams, constraintParams ) { - var manager = this.manager; + _init( mesh, rigidBodyParams, constraintParams ) { - // rigid body/constraint parameters are for + const manager = this.manager; // rigid body/constraint parameters are for // mesh's default world transform as position(0, 0, 0), // quaternion(0, 0, 0, 1) and scale(0, 0, 0) - var parent = mesh.parent; - + let parent = mesh.parent; if ( parent !== null ) parent = null; - - var currentPosition = manager.allocThreeVector3(); - var currentQuaternion = manager.allocThreeQuaternion(); - var currentScale = manager.allocThreeVector3(); - + const currentPosition = manager.allocThreeVector3(); + const currentQuaternion = manager.allocThreeQuaternion(); + const currentScale = manager.allocThreeVector3(); currentPosition.copy( mesh.position ); currentQuaternion.copy( mesh.quaternion ); currentScale.copy( mesh.scale ); - mesh.position.set( 0, 0, 0 ); mesh.quaternion.set( 0, 0, 0, 1 ); mesh.scale.set( 1, 1, 1 ); - mesh.updateMatrixWorld( true ); if ( this.world === null ) { @@ -227,66 +206,60 @@ THREE.MMDPhysics = ( function () { } this._initRigidBodies( rigidBodyParams ); + this._initConstraints( constraintParams ); if ( parent !== null ) mesh.parent = parent; - mesh.position.copy( currentPosition ); mesh.quaternion.copy( currentQuaternion ); mesh.scale.copy( currentScale ); - mesh.updateMatrixWorld( true ); - this.reset(); - manager.freeThreeVector3( currentPosition ); manager.freeThreeQuaternion( currentQuaternion ); manager.freeThreeVector3( currentScale ); - }, + } - _createWorld: function () { + _createWorld() { - var config = new Ammo.btDefaultCollisionConfiguration(); - var dispatcher = new Ammo.btCollisionDispatcher( config ); - var cache = new Ammo.btDbvtBroadphase(); - var solver = new Ammo.btSequentialImpulseConstraintSolver(); - var world = new Ammo.btDiscreteDynamicsWorld( dispatcher, cache, solver, config ); + const config = new Ammo.btDefaultCollisionConfiguration(); + const dispatcher = new Ammo.btCollisionDispatcher( config ); + const cache = new Ammo.btDbvtBroadphase(); + const solver = new Ammo.btSequentialImpulseConstraintSolver(); + const world = new Ammo.btDiscreteDynamicsWorld( dispatcher, cache, solver, config ); return world; - }, + } - _initRigidBodies: function ( rigidBodies ) { + _initRigidBodies( rigidBodies ) { - for ( var i = 0, il = rigidBodies.length; i < il; i ++ ) { + for ( let i = 0, il = rigidBodies.length; i < il; i ++ ) { - this.bodies.push( new RigidBody( - this.mesh, this.world, rigidBodies[ i ], this.manager ) ); + this.bodies.push( new RigidBody( this.mesh, this.world, rigidBodies[ i ], this.manager ) ); } - }, + } - _initConstraints: function ( constraints ) { + _initConstraints( constraints ) { - for ( var i = 0, il = constraints.length; i < il; i ++ ) { + for ( let i = 0, il = constraints.length; i < il; i ++ ) { - var params = constraints[ i ]; - var bodyA = this.bodies[ params.rigidBodyIndex1 ]; - var bodyB = this.bodies[ params.rigidBodyIndex2 ]; - this.constraints.push( new Constraint( - this.mesh, this.world, bodyA, bodyB, params, this.manager ) ); + const params = constraints[ i ]; + const bodyA = this.bodies[ params.rigidBodyIndex1 ]; + const bodyB = this.bodies[ params.rigidBodyIndex2 ]; + this.constraints.push( new Constraint( this.mesh, this.world, bodyA, bodyB, params, this.manager ) ); } + } - }, - - _stepSimulation: function ( delta ) { + _stepSimulation( delta ) { - var unitStep = this.unitStep; - var stepTime = delta; - var maxStepNum = ( ( delta / unitStep ) | 0 ) + 1; + const unitStep = this.unitStep; + let stepTime = delta; + let maxStepNum = ( delta / unitStep | 0 ) + 1; if ( stepTime < unitStep ) { @@ -303,21 +276,21 @@ THREE.MMDPhysics = ( function () { this.world.stepSimulation( stepTime, maxStepNum, unitStep ); - }, + } - _updateRigidBodies: function () { + _updateRigidBodies() { - for ( var i = 0, il = this.bodies.length; i < il; i ++ ) { + for ( let i = 0, il = this.bodies.length; i < il; i ++ ) { this.bodies[ i ].updateFromBone(); } - }, + } - _updateBones: function () { + _updateBones() { - for ( var i = 0, il = this.bodies.length; i < il; i ++ ) { + for ( let i = 0, il = this.bodies.length; i < il; i ++ ) { this.bodies[ i ].updateBone(); @@ -325,286 +298,253 @@ THREE.MMDPhysics = ( function () { } - }; - + } /** - * This manager's responsibilies are - * - * 1. manage Ammo.js and Three.js object resources and - * improve the performance and the memory consumption by - * reusing objects. - * - * 2. provide simple Ammo object operations. - */ - function ResourceManager() { - - // for Three.js - this.threeVector3s = []; - this.threeMatrix4s = []; - this.threeQuaternions = []; - this.threeEulers = []; - - // for Ammo.js - this.transforms = []; - this.quaternions = []; - this.vector3s = []; + * This manager's responsibilies are + * + * 1. manage Ammo.js and Three.js object resources and + * improve the performance and the memory consumption by + * reusing objects. + * + * 2. provide simple Ammo object operations. + */ - } - ResourceManager.prototype = { + class ResourceManager { + + constructor() { - constructor: ResourceManager, + // for Three.js + this.threeVector3s = []; + this.threeMatrix4s = []; + this.threeQuaternions = []; + this.threeEulers = []; // for Ammo.js - allocThreeVector3: function () { + this.transforms = []; + this.quaternions = []; + this.vector3s = []; - return ( this.threeVector3s.length > 0 ) - ? this.threeVector3s.pop() - : new THREE.Vector3(); + } - }, + allocThreeVector3() { - freeThreeVector3: function ( v ) { + return this.threeVector3s.length > 0 ? this.threeVector3s.pop() : new THREE.Vector3(); + + } + + freeThreeVector3( v ) { this.threeVector3s.push( v ); - }, + } - allocThreeMatrix4: function () { + allocThreeMatrix4() { - return ( this.threeMatrix4s.length > 0 ) - ? this.threeMatrix4s.pop() - : new THREE.Matrix4(); + return this.threeMatrix4s.length > 0 ? this.threeMatrix4s.pop() : new THREE.Matrix4(); - }, + } - freeThreeMatrix4: function ( m ) { + freeThreeMatrix4( m ) { this.threeMatrix4s.push( m ); - }, + } - allocThreeQuaternion: function () { + allocThreeQuaternion() { - return ( this.threeQuaternions.length > 0 ) - ? this.threeQuaternions.pop() - : new THREE.Quaternion(); + return this.threeQuaternions.length > 0 ? this.threeQuaternions.pop() : new THREE.Quaternion(); - }, + } - freeThreeQuaternion: function ( q ) { + freeThreeQuaternion( q ) { this.threeQuaternions.push( q ); - }, + } - allocThreeEuler: function () { + allocThreeEuler() { - return ( this.threeEulers.length > 0 ) - ? this.threeEulers.pop() - : new THREE.Euler(); + return this.threeEulers.length > 0 ? this.threeEulers.pop() : new THREE.Euler(); - }, + } - freeThreeEuler: function ( e ) { + freeThreeEuler( e ) { this.threeEulers.push( e ); - }, + } - allocTransform: function () { + allocTransform() { - return ( this.transforms.length > 0 ) - ? this.transforms.pop() - : new Ammo.btTransform(); + return this.transforms.length > 0 ? this.transforms.pop() : new Ammo.btTransform(); - }, + } - freeTransform: function ( t ) { + freeTransform( t ) { this.transforms.push( t ); - }, + } - allocQuaternion: function () { + allocQuaternion() { - return ( this.quaternions.length > 0 ) - ? this.quaternions.pop() - : new Ammo.btQuaternion(); + return this.quaternions.length > 0 ? this.quaternions.pop() : new Ammo.btQuaternion(); - }, + } - freeQuaternion: function ( q ) { + freeQuaternion( q ) { this.quaternions.push( q ); - }, + } - allocVector3: function () { + allocVector3() { - return ( this.vector3s.length > 0 ) - ? this.vector3s.pop() - : new Ammo.btVector3(); + return this.vector3s.length > 0 ? this.vector3s.pop() : new Ammo.btVector3(); - }, + } - freeVector3: function ( v ) { + freeVector3( v ) { this.vector3s.push( v ); - }, + } - setIdentity: function ( t ) { + setIdentity( t ) { t.setIdentity(); - }, + } - getBasis: function ( t ) { + getBasis( t ) { var q = this.allocQuaternion(); t.getBasis().getRotation( q ); return q; - }, + } - getBasisAsMatrix3: function ( t ) { + getBasisAsMatrix3( t ) { var q = this.getBasis( t ); var m = this.quaternionToMatrix3( q ); this.freeQuaternion( q ); return m; - }, + } - getOrigin: function ( t ) { + getOrigin( t ) { return t.getOrigin(); - }, + } - setOrigin: function ( t, v ) { + setOrigin( t, v ) { t.getOrigin().setValue( v.x(), v.y(), v.z() ); - }, + } - copyOrigin: function ( t1, t2 ) { + copyOrigin( t1, t2 ) { var o = t2.getOrigin(); this.setOrigin( t1, o ); - }, + } - setBasis: function ( t, q ) { + setBasis( t, q ) { t.setRotation( q ); - }, + } - setBasisFromMatrix3: function ( t, m ) { + setBasisFromMatrix3( t, m ) { var q = this.matrix3ToQuaternion( m ); this.setBasis( t, q ); this.freeQuaternion( q ); - }, + } - setOriginFromArray3: function ( t, a ) { + setOriginFromArray3( t, a ) { t.getOrigin().setValue( a[ 0 ], a[ 1 ], a[ 2 ] ); - }, + } - setOriginFromThreeVector3: function ( t, v ) { + setOriginFromThreeVector3( t, v ) { t.getOrigin().setValue( v.x, v.y, v.z ); - }, + } - setBasisFromArray3: function ( t, a ) { + setBasisFromArray3( t, a ) { var thQ = this.allocThreeQuaternion(); var thE = this.allocThreeEuler(); thE.set( a[ 0 ], a[ 1 ], a[ 2 ] ); this.setBasisFromThreeQuaternion( t, thQ.setFromEuler( thE ) ); - this.freeThreeEuler( thE ); this.freeThreeQuaternion( thQ ); - }, + } - setBasisFromThreeQuaternion: function ( t, a ) { + setBasisFromThreeQuaternion( t, a ) { var q = this.allocQuaternion(); - q.setX( a.x ); q.setY( a.y ); q.setZ( a.z ); q.setW( a.w ); this.setBasis( t, q ); - this.freeQuaternion( q ); - }, + } - multiplyTransforms: function ( t1, t2 ) { + multiplyTransforms( t1, t2 ) { var t = this.allocTransform(); this.setIdentity( t ); - var m1 = this.getBasisAsMatrix3( t1 ); var m2 = this.getBasisAsMatrix3( t2 ); - var o1 = this.getOrigin( t1 ); var o2 = this.getOrigin( t2 ); - var v1 = this.multiplyMatrix3ByVector3( m1, o2 ); var v2 = this.addVector3( v1, o1 ); this.setOrigin( t, v2 ); - var m3 = this.multiplyMatrices3( m1, m2 ); this.setBasisFromMatrix3( t, m3 ); - this.freeVector3( v1 ); this.freeVector3( v2 ); - return t; - }, + } - inverseTransform: function ( t ) { + inverseTransform( t ) { var t2 = this.allocTransform(); - var m1 = this.getBasisAsMatrix3( t ); var o = this.getOrigin( t ); - var m2 = this.transposeMatrix3( m1 ); var v1 = this.negativeVector3( o ); var v2 = this.multiplyMatrix3ByVector3( m2, v1 ); - this.setOrigin( t2, v2 ); this.setBasisFromMatrix3( t2, m2 ); - this.freeVector3( v1 ); this.freeVector3( v2 ); - return t2; - }, + } - multiplyMatrices3: function ( m1, m2 ) { + multiplyMatrices3( m1, m2 ) { var m3 = []; - var v10 = this.rowOfMatrix3( m1, 0 ); var v11 = this.rowOfMatrix3( m1, 1 ); var v12 = this.rowOfMatrix3( m1, 2 ); - var v20 = this.columnOfMatrix3( m2, 0 ); var v21 = this.columnOfMatrix3( m2, 1 ); var v22 = this.columnOfMatrix3( m2, 2 ); - m3[ 0 ] = this.dotVectors3( v10, v20 ); m3[ 1 ] = this.dotVectors3( v10, v21 ); m3[ 2 ] = this.dotVectors3( v10, v22 ); @@ -614,78 +554,72 @@ THREE.MMDPhysics = ( function () { m3[ 6 ] = this.dotVectors3( v12, v20 ); m3[ 7 ] = this.dotVectors3( v12, v21 ); m3[ 8 ] = this.dotVectors3( v12, v22 ); - this.freeVector3( v10 ); this.freeVector3( v11 ); this.freeVector3( v12 ); this.freeVector3( v20 ); this.freeVector3( v21 ); this.freeVector3( v22 ); - return m3; - }, + } - addVector3: function ( v1, v2 ) { + addVector3( v1, v2 ) { var v = this.allocVector3(); v.setValue( v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z() ); return v; - }, + } - dotVectors3: function ( v1, v2 ) { + dotVectors3( v1, v2 ) { return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z(); - }, + } - rowOfMatrix3: function ( m, i ) { + rowOfMatrix3( m, i ) { var v = this.allocVector3(); v.setValue( m[ i * 3 + 0 ], m[ i * 3 + 1 ], m[ i * 3 + 2 ] ); return v; - }, + } - columnOfMatrix3: function ( m, i ) { + columnOfMatrix3( m, i ) { var v = this.allocVector3(); v.setValue( m[ i + 0 ], m[ i + 3 ], m[ i + 6 ] ); return v; - }, + } - negativeVector3: function ( v ) { + negativeVector3( v ) { var v2 = this.allocVector3(); v2.setValue( - v.x(), - v.y(), - v.z() ); return v2; - }, + } - multiplyMatrix3ByVector3: function ( m, v ) { + multiplyMatrix3ByVector3( m, v ) { var v4 = this.allocVector3(); - var v0 = this.rowOfMatrix3( m, 0 ); var v1 = this.rowOfMatrix3( m, 1 ); var v2 = this.rowOfMatrix3( m, 2 ); var x = this.dotVectors3( v0, v ); var y = this.dotVectors3( v1, v ); var z = this.dotVectors3( v2, v ); - v4.setValue( x, y, z ); - this.freeVector3( v0 ); this.freeVector3( v1 ); this.freeVector3( v2 ); - return v4; - }, + } - transposeMatrix3: function ( m ) { + transposeMatrix3( m ) { var m2 = []; m2[ 0 ] = m[ 0 ]; @@ -699,29 +633,24 @@ THREE.MMDPhysics = ( function () { m2[ 8 ] = m[ 8 ]; return m2; - }, + } - quaternionToMatrix3: function ( q ) { + quaternionToMatrix3( q ) { var m = []; - var x = q.x(); var y = q.y(); var z = q.z(); var w = q.w(); - var xx = x * x; var yy = y * y; var zz = z * z; - var xy = x * y; var yz = y * z; var zx = z * x; - var xw = x * w; var yw = y * w; var zw = z * w; - m[ 0 ] = 1 - 2 * ( yy + zz ); m[ 1 ] = 2 * ( xy - zw ); m[ 2 ] = 2 * ( zx + yw ); @@ -731,12 +660,11 @@ THREE.MMDPhysics = ( function () { m[ 6 ] = 2 * ( zx - yw ); m[ 7 ] = 2 * ( yz + xw ); m[ 8 ] = 1 - 2 * ( xx + yy ); - return m; - }, + } - matrix3ToQuaternion: function ( m ) { + matrix3ToQuaternion( m ) { var t = m[ 0 ] + m[ 4 ] + m[ 8 ]; var s, x, y, z, w; @@ -749,7 +677,7 @@ THREE.MMDPhysics = ( function () { y = ( m[ 2 ] - m[ 6 ] ) / s; z = ( m[ 3 ] - m[ 1 ] ) / s; - } else if ( ( m[ 0 ] > m[ 4 ] ) && ( m[ 0 ] > m[ 8 ] ) ) { + } else if ( m[ 0 ] > m[ 4 ] && m[ 0 ] > m[ 8 ] ) { s = Math.sqrt( 1.0 + m[ 0 ] - m[ 4 ] - m[ 8 ] ) * 2; w = ( m[ 7 ] - m[ 5 ] ) / s; @@ -784,55 +712,55 @@ THREE.MMDPhysics = ( function () { } - }; - + } /** - * @param {THREE.SkinnedMesh} mesh - * @param {Ammo.btDiscreteDynamicsWorld} world - * @param {Object} params - * @param {ResourceManager} manager - */ - function RigidBody( mesh, world, params, manager ) { - - this.mesh = mesh; - this.world = world; - this.params = params; - this.manager = manager; + * @param {THREE.SkinnedMesh} mesh + * @param {Ammo.btDiscreteDynamicsWorld} world + * @param {Object} params + * @param {ResourceManager} manager + */ - this.body = null; - this.bone = null; - this.boneOffsetForm = null; - this.boneOffsetFormInverse = null; - this._init(); + class RigidBody { - } + constructor( mesh, world, params, manager ) { - RigidBody.prototype = { + this.mesh = mesh; + this.world = world; + this.params = params; + this.manager = manager; + this.body = null; + this.bone = null; + this.boneOffsetForm = null; + this.boneOffsetFormInverse = null; - constructor: MMDPhysics.RigidBody, + this._init(); + } /** - * Resets rigid body transform to the current bone's. - * - * @return {RigidBody} - */ - reset: function () { + * Resets rigid body transform to the current bone's. + * + * @return {RigidBody} + */ + + + reset() { this._setTransformFromBone(); - return this; - }, + return this; + } /** - * Updates rigid body's transform from the current bone. - * - * @return {RidigBody} - */ - updateFromBone: function () { + * Updates rigid body's transform from the current bone. + * + * @return {RidigBody} + */ + - if ( this.params.boneIndex !== - 1 && - this.params.type === 0 ) { + updateFromBone() { + + if ( this.params.boneIndex !== - 1 && this.params.type === 0 ) { this._setTransformFromBone(); @@ -840,17 +768,17 @@ THREE.MMDPhysics = ( function () { return this; - }, - + } /** - * Updates bone from the current ridid body's transform. - * - * @return {RidigBody} - */ - updateBone: function () { + * Updates bone from the current ridid body's transform. + * + * @return {RidigBody} + */ + - if ( this.params.type === 0 || - this.params.boneIndex === - 1 ) { + updateBone() { + + if ( this.params.type === 0 || this.params.boneIndex === - 1 ) { return this; @@ -874,11 +802,10 @@ THREE.MMDPhysics = ( function () { return this; - }, + } // private methods - // private methods - _init: function () { + _init() { function generateShape( p ) { @@ -900,16 +827,13 @@ THREE.MMDPhysics = ( function () { } - var manager = this.manager; - var params = this.params; - var bones = this.mesh.skeleton.bones; - var bone = ( params.boneIndex === - 1 ) - ? new THREE.Bone() - : bones[ params.boneIndex ]; - - var shape = generateShape( params ); - var weight = ( params.type === 0 ) ? 0 : params.weight; - var localInertia = manager.allocVector3(); + const manager = this.manager; + const params = this.params; + const bones = this.mesh.skeleton.bones; + const bone = params.boneIndex === - 1 ? new THREE.Bone() : bones[ params.boneIndex ]; + const shape = generateShape( params ); + const weight = params.type === 0 ? 0 : params.weight; + const localInertia = manager.allocVector3(); localInertia.setValue( 0, 0, 0 ); if ( weight !== 0 ) { @@ -918,163 +842,143 @@ THREE.MMDPhysics = ( function () { } - var boneOffsetForm = manager.allocTransform(); + const boneOffsetForm = manager.allocTransform(); manager.setIdentity( boneOffsetForm ); manager.setOriginFromArray3( boneOffsetForm, params.position ); manager.setBasisFromArray3( boneOffsetForm, params.rotation ); - - var vector = manager.allocThreeVector3(); - var boneForm = manager.allocTransform(); + const vector = manager.allocThreeVector3(); + const boneForm = manager.allocTransform(); manager.setIdentity( boneForm ); manager.setOriginFromThreeVector3( boneForm, bone.getWorldPosition( vector ) ); - - var form = manager.multiplyTransforms( boneForm, boneOffsetForm ); - var state = new Ammo.btDefaultMotionState( form ); - - var info = new Ammo.btRigidBodyConstructionInfo( weight, state, shape, localInertia ); + const form = manager.multiplyTransforms( boneForm, boneOffsetForm ); + const state = new Ammo.btDefaultMotionState( form ); + const info = new Ammo.btRigidBodyConstructionInfo( weight, state, shape, localInertia ); info.set_m_friction( params.friction ); info.set_m_restitution( params.restitution ); - - var body = new Ammo.btRigidBody( info ); + const body = new Ammo.btRigidBody( info ); if ( params.type === 0 ) { body.setCollisionFlags( body.getCollisionFlags() | 2 ); - /* - * It'd be better to comment out this line though in general I should call this method - * because I'm not sure why but physics will be more like MMD's - * if I comment out. - */ + * It'd be better to comment out this line though in general I should call this method + * because I'm not sure why but physics will be more like MMD's + * if I comment out. + */ + body.setActivationState( 4 ); } body.setDamping( params.positionDamping, params.rotationDamping ); body.setSleepingThresholds( 0, 0 ); - this.world.addRigidBody( body, 1 << params.groupIndex, params.groupTarget ); - this.body = body; this.bone = bone; this.boneOffsetForm = boneOffsetForm; this.boneOffsetFormInverse = manager.inverseTransform( boneOffsetForm ); - manager.freeVector3( localInertia ); manager.freeTransform( form ); manager.freeTransform( boneForm ); manager.freeThreeVector3( vector ); - }, - - _getBoneTransform: function () { + } - var manager = this.manager; - var p = manager.allocThreeVector3(); - var q = manager.allocThreeQuaternion(); - var s = manager.allocThreeVector3(); + _getBoneTransform() { + const manager = this.manager; + const p = manager.allocThreeVector3(); + const q = manager.allocThreeQuaternion(); + const s = manager.allocThreeVector3(); this.bone.matrixWorld.decompose( p, q, s ); - - var tr = manager.allocTransform(); + const tr = manager.allocTransform(); manager.setOriginFromThreeVector3( tr, p ); manager.setBasisFromThreeQuaternion( tr, q ); - - var form = manager.multiplyTransforms( tr, this.boneOffsetForm ); - + const form = manager.multiplyTransforms( tr, this.boneOffsetForm ); manager.freeTransform( tr ); manager.freeThreeVector3( s ); manager.freeThreeQuaternion( q ); manager.freeThreeVector3( p ); - return form; - }, + } - _getWorldTransformForBone: function () { + _getWorldTransformForBone() { - var manager = this.manager; - var tr = this.body.getCenterOfMassTransform(); + const manager = this.manager; + const tr = this.body.getCenterOfMassTransform(); return manager.multiplyTransforms( tr, this.boneOffsetFormInverse ); - }, + } - _setTransformFromBone: function () { + _setTransformFromBone() { - var manager = this.manager; - var form = this._getBoneTransform(); + const manager = this.manager; - // TODO: check the most appropriate way to set + const form = this._getBoneTransform(); // TODO: check the most appropriate way to set //this.body.setWorldTransform( form ); + + this.body.setCenterOfMassTransform( form ); this.body.getMotionState().setWorldTransform( form ); - manager.freeTransform( form ); - }, + } - _setPositionFromBone: function () { + _setPositionFromBone() { - var manager = this.manager; - var form = this._getBoneTransform(); + const manager = this.manager; - var tr = manager.allocTransform(); - this.body.getMotionState().getWorldTransform( tr ); - manager.copyOrigin( tr, form ); + const form = this._getBoneTransform(); - // TODO: check the most appropriate way to set + const tr = manager.allocTransform(); + this.body.getMotionState().getWorldTransform( tr ); + manager.copyOrigin( tr, form ); // TODO: check the most appropriate way to set //this.body.setWorldTransform( tr ); + this.body.setCenterOfMassTransform( tr ); this.body.getMotionState().setWorldTransform( tr ); - manager.freeTransform( tr ); manager.freeTransform( form ); - }, - - _updateBoneRotation: function () { + } - var manager = this.manager; + _updateBoneRotation() { - var tr = this._getWorldTransformForBone(); - var q = manager.getBasis( tr ); + const manager = this.manager; - var thQ = manager.allocThreeQuaternion(); - var thQ2 = manager.allocThreeQuaternion(); - var thQ3 = manager.allocThreeQuaternion(); + const tr = this._getWorldTransformForBone(); + const q = manager.getBasis( tr ); + const thQ = manager.allocThreeQuaternion(); + const thQ2 = manager.allocThreeQuaternion(); + const thQ3 = manager.allocThreeQuaternion(); thQ.set( q.x(), q.y(), q.z(), q.w() ); thQ2.setFromRotationMatrix( this.bone.matrixWorld ); thQ2.conjugate(); - thQ2.multiply( thQ ); - - //this.bone.quaternion.multiply( thQ2 ); - - thQ3.setFromRotationMatrix( this.bone.matrix ); + thQ2.multiply( thQ ); //this.bone.quaternion.multiply( thQ2 ); - // Renormalizing quaternion here because repeatedly transforming + thQ3.setFromRotationMatrix( this.bone.matrix ); // Renormalizing quaternion here because repeatedly transforming // quaternion continuously accumulates floating point error and // can end up being overflow. See #15335 - this.bone.quaternion.copy( thQ2.multiply( thQ3 ).normalize() ); + this.bone.quaternion.copy( thQ2.multiply( thQ3 ).normalize() ); manager.freeThreeQuaternion( thQ ); manager.freeThreeQuaternion( thQ2 ); manager.freeThreeQuaternion( thQ3 ); - manager.freeQuaternion( q ); manager.freeTransform( tr ); - }, - - _updateBonePosition: function () { + } - var manager = this.manager; + _updateBonePosition() { - var tr = this._getWorldTransformForBone(); + const manager = this.manager; - var thV = manager.allocThreeVector3(); + const tr = this._getWorldTransformForBone(); - var o = manager.getOrigin( tr ); + const thV = manager.allocThreeVector3(); + const o = manager.getOrigin( tr ); thV.set( o.x(), o.y(), o.z() ); if ( this.bone.parent ) { @@ -1084,94 +988,72 @@ THREE.MMDPhysics = ( function () { } this.bone.position.copy( thV ); - manager.freeThreeVector3( thV ); - manager.freeTransform( tr ); } - }; + } // - /** - * @param {THREE.SkinnedMesh} mesh - * @param {Ammo.btDiscreteDynamicsWorld} world - * @param {RigidBody} bodyA - * @param {RigidBody} bodyB - * @param {Object} params - * @param {ResourceManager} manager - */ - function Constraint( mesh, world, bodyA, bodyB, params, manager ) { - - this.mesh = mesh; - this.world = world; - this.bodyA = bodyA; - this.bodyB = bodyB; - this.params = params; - this.manager = manager; - - this.constraint = null; - - this._init(); - - } - - Constraint.prototype = { - - constructor: Constraint, - - // private method - - _init: function () { - var manager = this.manager; - var params = this.params; - var bodyA = this.bodyA; - var bodyB = this.bodyB; + class Constraint { - var form = manager.allocTransform(); + /** + * @param {THREE.SkinnedMesh} mesh + * @param {Ammo.btDiscreteDynamicsWorld} world + * @param {RigidBody} bodyA + * @param {RigidBody} bodyB + * @param {Object} params + * @param {ResourceManager} manager + */ + constructor( mesh, world, bodyA, bodyB, params, manager ) { + + this.mesh = mesh; + this.world = world; + this.bodyA = bodyA; + this.bodyB = bodyB; + this.params = params; + this.manager = manager; + this.constraint = null; + + this._init(); + + } // private method + + + _init() { + + const manager = this.manager; + const params = this.params; + const bodyA = this.bodyA; + const bodyB = this.bodyB; + const form = manager.allocTransform(); manager.setIdentity( form ); manager.setOriginFromArray3( form, params.position ); manager.setBasisFromArray3( form, params.rotation ); - - var formA = manager.allocTransform(); - var formB = manager.allocTransform(); - + const formA = manager.allocTransform(); + const formB = manager.allocTransform(); bodyA.body.getMotionState().getWorldTransform( formA ); bodyB.body.getMotionState().getWorldTransform( formB ); - - var formInverseA = manager.inverseTransform( formA ); - var formInverseB = manager.inverseTransform( formB ); - - var formA2 = manager.multiplyTransforms( formInverseA, form ); - var formB2 = manager.multiplyTransforms( formInverseB, form ); - - var constraint = new Ammo.btGeneric6DofSpringConstraint( bodyA.body, bodyB.body, formA2, formB2, true ); - - var lll = manager.allocVector3(); - var lul = manager.allocVector3(); - var all = manager.allocVector3(); - var aul = manager.allocVector3(); - - lll.setValue( params.translationLimitation1[ 0 ], - params.translationLimitation1[ 1 ], - params.translationLimitation1[ 2 ] ); - lul.setValue( params.translationLimitation2[ 0 ], - params.translationLimitation2[ 1 ], - params.translationLimitation2[ 2 ] ); - all.setValue( params.rotationLimitation1[ 0 ], - params.rotationLimitation1[ 1 ], - params.rotationLimitation1[ 2 ] ); - aul.setValue( params.rotationLimitation2[ 0 ], - params.rotationLimitation2[ 1 ], - params.rotationLimitation2[ 2 ] ); - + const formInverseA = manager.inverseTransform( formA ); + const formInverseB = manager.inverseTransform( formB ); + const formA2 = manager.multiplyTransforms( formInverseA, form ); + const formB2 = manager.multiplyTransforms( formInverseB, form ); + const constraint = new Ammo.btGeneric6DofSpringConstraint( bodyA.body, bodyB.body, formA2, formB2, true ); + const lll = manager.allocVector3(); + const lul = manager.allocVector3(); + const all = manager.allocVector3(); + const aul = manager.allocVector3(); + lll.setValue( params.translationLimitation1[ 0 ], params.translationLimitation1[ 1 ], params.translationLimitation1[ 2 ] ); + lul.setValue( params.translationLimitation2[ 0 ], params.translationLimitation2[ 1 ], params.translationLimitation2[ 2 ] ); + all.setValue( params.rotationLimitation1[ 0 ], params.rotationLimitation1[ 1 ], params.rotationLimitation1[ 2 ] ); + aul.setValue( params.rotationLimitation2[ 0 ], params.rotationLimitation2[ 1 ], params.rotationLimitation2[ 2 ] ); constraint.setLinearLowerLimit( lll ); constraint.setLinearUpperLimit( lul ); constraint.setAngularLowerLimit( all ); constraint.setAngularUpperLimit( aul ); - for ( var i = 0; i < 3; i ++ ) { + for ( let i = 0; i < 3; i ++ ) { if ( params.springPosition[ i ] !== 0 ) { @@ -1182,7 +1064,7 @@ THREE.MMDPhysics = ( function () { } - for ( var i = 0; i < 3; i ++ ) { + for ( let i = 0; i < 3; i ++ ) { if ( params.springRotation[ i ] !== 0 ) { @@ -1192,16 +1074,17 @@ THREE.MMDPhysics = ( function () { } } - /* - * Currently(10/31/2016) official ammo.js doesn't support - * btGeneric6DofSpringConstraint.setParam method. - * You need custom ammo.js (add the method into idl) if you wanna use. - * By setting this parameter, physics will be more like MMD's - */ + * Currently(10/31/2016) official ammo.js doesn't support + * btGeneric6DofSpringConstraint.setParam method. + * You need custom ammo.js (add the method into idl) if you wanna use. + * By setting this parameter, physics will be more like MMD's + */ + + if ( constraint.setParam !== undefined ) { - for ( var i = 0; i < 6; i ++ ) { + 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 ); @@ -1212,7 +1095,6 @@ THREE.MMDPhysics = ( function () { this.world.addConstraint( constraint, true ); this.constraint = constraint; - manager.freeTransform( form ); manager.freeTransform( formA ); manager.freeTransform( formB ); @@ -1227,129 +1109,97 @@ THREE.MMDPhysics = ( function () { } - }; + } // - /** - * Visualize Rigid bodies - * - * @param {THREE.SkinnedMesh} mesh - * @param {THREE.Physics} physics - */ - function MMDPhysicsHelper( mesh, physics ) { - THREE.Object3D.call( this ); + const _position = new THREE.Vector3(); + + const _quaternion = new THREE.Quaternion(); - this.root = mesh; - this.physics = physics; + const _scale = new THREE.Vector3(); - this.matrix.copy( mesh.matrixWorld ); - this.matrixAutoUpdate = false; + const _matrixWorldInv = new THREE.Matrix4(); - this.materials = []; + class MMDPhysicsHelper extends THREE.Object3D { - this.materials.push( - new THREE.MeshBasicMaterial( { + /** + * Visualize Rigid bodies + * + * @param {THREE.SkinnedMesh} mesh + * @param {Physics} physics + */ + constructor( mesh, physics ) { + + super(); + this.root = mesh; + this.physics = physics; + this.matrix.copy( mesh.matrixWorld ); + this.matrixAutoUpdate = false; + this.materials = []; + this.materials.push( new THREE.MeshBasicMaterial( { color: new THREE.Color( 0xff8888 ), wireframe: true, depthTest: false, depthWrite: false, opacity: 0.25, transparent: true - } ) - ); - - this.materials.push( - new THREE.MeshBasicMaterial( { + } ) ); + this.materials.push( new THREE.MeshBasicMaterial( { color: new THREE.Color( 0x88ff88 ), wireframe: true, depthTest: false, depthWrite: false, opacity: 0.25, transparent: true - } ) - ); - - this.materials.push( - new THREE.MeshBasicMaterial( { + } ) ); + this.materials.push( new THREE.MeshBasicMaterial( { color: new THREE.Color( 0x8888ff ), wireframe: true, depthTest: false, depthWrite: false, opacity: 0.25, transparent: true - } ) - ); - - this._init(); - - } - - MMDPhysicsHelper.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { + } ) ); - constructor: MMDPhysicsHelper, + this._init(); + } /** - * Updates Rigid Bodies visualization. - */ - updateMatrixWorld: function () { - - var position = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); - var scale = new THREE.Vector3(); - var matrixWorldInv = new THREE.Matrix4(); - - return function updateMatrixWorld( force ) { - - var mesh = this.root; + * Updates Rigid Bodies visualization. + */ - if ( this.visible ) { - var bodies = this.physics.bodies; + updateMatrixWorld( force ) { - matrixWorldInv - .copy( mesh.matrixWorld ) - .decompose( position, quaternion, scale ) - .compose( position, quaternion, scale.set( 1, 1, 1 ) ) - .invert(); + var mesh = this.root; - for ( var i = 0, il = bodies.length; i < il; i ++ ) { + if ( this.visible ) { - var body = bodies[ i ].body; - var child = this.children[ i ]; + var bodies = this.physics.bodies; - var tr = body.getCenterOfMassTransform(); - var origin = tr.getOrigin(); - var rotation = tr.getRotation(); + _matrixWorldInv.copy( mesh.matrixWorld ).decompose( _position, _quaternion, _scale ).compose( _position, _quaternion, _scale.set( 1, 1, 1 ) ).invert(); - child.position - .set( origin.x(), origin.y(), origin.z() ) - .applyMatrix4( matrixWorldInv ); + for ( var i = 0, il = bodies.length; i < il; i ++ ) { - child.quaternion - .setFromRotationMatrix( matrixWorldInv ) - .multiply( - quaternion.set( - rotation.x(), rotation.y(), rotation.z(), rotation.w() ) - ); - - } + var body = bodies[ i ].body; + var child = this.children[ i ]; + var tr = body.getCenterOfMassTransform(); + var origin = tr.getOrigin(); + var rotation = tr.getRotation(); + child.position.set( origin.x(), origin.y(), origin.z() ).applyMatrix4( _matrixWorldInv ); + child.quaternion.setFromRotationMatrix( _matrixWorldInv ).multiply( _quaternion.set( rotation.x(), rotation.y(), rotation.z(), rotation.w() ) ); } - this.matrix - .copy( mesh.matrixWorld ) - .decompose( position, quaternion, scale ) - .compose( position, quaternion, scale.set( 1, 1, 1 ) ); - - THREE.Object3D.prototype.updateMatrixWorld.call( this, force ); + } - }; + this.matrix.copy( mesh.matrixWorld ).decompose( _position, _quaternion, _scale ).compose( _position, _quaternion, _scale.set( 1, 1, 1 ) ); + super.updateMatrixWorld( force ); - }(), + } // private method - // private method - _init: function () { + _init() { var bodies = this.physics.bodies; @@ -1371,24 +1221,20 @@ THREE.MMDPhysics = ( function () { } - } + } // copy from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mytest37.js?ver=20160815 + - // 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 THREE.CylinderGeometry( radius, radius, cylinderHeight, segmentsRadius, segmentsHeight, true ); var upperSphere = new THREE.Mesh( new THREE.SphereGeometry( radius, segmentsRadius, segmentsHeight, 0, Math.PI * 2, 0, Math.PI / 2 ) ); var lowerSphere = new THREE.Mesh( new THREE.SphereGeometry( radius, segmentsRadius, segmentsHeight, 0, Math.PI * 2, Math.PI / 2, Math.PI / 2 ) ); - upperSphere.position.set( 0, cylinderHeight / 2, 0 ); lowerSphere.position.set( 0, - cylinderHeight / 2, 0 ); - upperSphere.updateMatrix(); lowerSphere.updateMatrix(); - geometry.merge( upperSphere.geometry, upperSphere.matrix ); geometry.merge( lowerSphere.geometry, lowerSphere.matrix ); - return geometry; } @@ -1402,8 +1248,8 @@ THREE.MMDPhysics = ( function () { } - } ); + } - return MMDPhysics; + THREE.MMDPhysics = MMDPhysics; } )(); diff --git a/examples/js/cameras/CinematicCamera.js b/examples/js/cameras/CinematicCamera.js index f85c35750ca532..86b09e8fcb2bef 100644 --- a/examples/js/cameras/CinematicCamera.js +++ b/examples/js/cameras/CinematicCamera.js @@ -1,200 +1,162 @@ -THREE.CinematicCamera = function ( fov, aspect, near, far ) { +( function () { - THREE.PerspectiveCamera.call( this, fov, aspect, near, far ); + class CinematicCamera extends THREE.PerspectiveCamera { - this.type = 'CinematicCamera'; + constructor( fov, aspect, near, far ) { - this.postprocessing = { enabled: true }; - this.shaderSettings = { - rings: 3, - samples: 4 - }; + super( fov, aspect, near, far ); + this.type = 'CinematicCamera'; + this.postprocessing = { + enabled: true + }; + this.shaderSettings = { + rings: 3, + samples: 4 + }; + const depthShader = THREE.BokehDepthShader; + this.materialDepth = new THREE.ShaderMaterial( { + uniforms: depthShader.uniforms, + vertexShader: depthShader.vertexShader, + fragmentShader: depthShader.fragmentShader + } ); + this.materialDepth.uniforms[ 'mNear' ].value = near; + this.materialDepth.uniforms[ 'mFar' ].value = far; // In case of cinematicCamera, having a default lens set is important - var depthShader = THREE.BokehDepthShader; + this.setLens(); + this.initPostProcessing(); - this.materialDepth = new THREE.ShaderMaterial( { - uniforms: depthShader.uniforms, - vertexShader: depthShader.vertexShader, - fragmentShader: depthShader.fragmentShader - } ); + } // providing fnumber and coc(Circle of Confusion) as extra arguments + // In case of cinematicCamera, having a default lens set is important + // if fnumber and coc are not provided, cinematicCamera tries to act as a basic THREE.PerspectiveCamera - this.materialDepth.uniforms[ 'mNear' ].value = near; - this.materialDepth.uniforms[ 'mFar' ].value = far; - // In case of cinematicCamera, having a default lens set is important - this.setLens(); + setLens( focalLength = 35, filmGauge = 35, fNumber = 8, coc = 0.019 ) { - this.initPostProcessing(); + this.filmGauge = filmGauge; + this.setFocalLength( focalLength ); + this.fNumber = fNumber; + this.coc = coc; // fNumber is focalLength by aperture -}; + this.aperture = focalLength / this.fNumber; // hyperFocal is required to calculate depthOfField when a lens tries to focus at a distance with given fNumber and focalLength -THREE.CinematicCamera.prototype = Object.create( THREE.PerspectiveCamera.prototype ); -THREE.CinematicCamera.prototype.constructor = THREE.CinematicCamera; + this.hyperFocal = focalLength * focalLength / ( this.aperture * this.coc ); + } -// providing fnumber and coc(Circle of Confusion) as extra arguments -THREE.CinematicCamera.prototype.setLens = function ( focalLength, filmGauge, fNumber, coc ) { + linearize( depth ) { - // In case of cinematicCamera, having a default lens set is important - if ( focalLength === undefined ) focalLength = 35; - if ( filmGauge !== undefined ) this.filmGauge = filmGauge; + const zfar = this.far; + const znear = this.near; + return - zfar * znear / ( depth * ( zfar - znear ) - zfar ); - this.setFocalLength( focalLength ); + } - // if fnumber and coc are not provided, cinematicCamera tries to act as a basic PerspectiveCamera - if ( fNumber === undefined ) fNumber = 8; - if ( coc === undefined ) coc = 0.019; + smoothstep( near, far, depth ) { - this.fNumber = fNumber; - this.coc = coc; + const x = this.saturate( ( depth - near ) / ( far - near ) ); + return x * x * ( 3 - 2 * x ); - // fNumber is focalLength by aperture - this.aperture = focalLength / this.fNumber; + } - // hyperFocal is required to calculate depthOfField when a lens tries to focus at a distance with given fNumber and focalLength - this.hyperFocal = ( focalLength * focalLength ) / ( this.aperture * this.coc ); + saturate( x ) { -}; + return Math.max( 0, Math.min( 1, x ) ); -THREE.CinematicCamera.prototype.linearize = function ( depth ) { + } // function for focusing at a distance from the camera - var zfar = this.far; - var znear = this.near; - return - zfar * znear / ( depth * ( zfar - znear ) - zfar ); -}; + focusAt( focusDistance = 20 ) { -THREE.CinematicCamera.prototype.smoothstep = function ( near, far, depth ) { + const focalLength = this.getFocalLength(); // distance from the camera (normal to frustrum) to focus on - var x = this.saturate( ( depth - near ) / ( far - near ) ); - return x * x * ( 3 - 2 * x ); + this.focus = focusDistance; // the nearest point from the camera which is in focus (unused) -}; + this.nearPoint = this.hyperFocal * this.focus / ( this.hyperFocal + ( this.focus - focalLength ) ); // the farthest point from the camera which is in focus (unused) -THREE.CinematicCamera.prototype.saturate = function ( x ) { + this.farPoint = this.hyperFocal * this.focus / ( this.hyperFocal - ( this.focus - focalLength ) ); // the gap or width of the space in which is everything is in focus (unused) - return Math.max( 0, Math.min( 1, x ) ); + this.depthOfField = this.farPoint - this.nearPoint; // Considering minimum distance of focus for a standard lens (unused) -}; + if ( this.depthOfField < 0 ) this.depthOfField = 0; + this.sdistance = this.smoothstep( this.near, this.far, this.focus ); + this.ldistance = this.linearize( 1 - this.sdistance ); + this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = this.ldistance; -// function for focusing at a distance from the camera -THREE.CinematicCamera.prototype.focusAt = function ( focusDistance ) { + } - if ( focusDistance === undefined ) focusDistance = 20; + initPostProcessing() { - var focalLength = this.getFocalLength(); + if ( this.postprocessing.enabled ) { - // distance from the camera (normal to frustrum) to focus on - this.focus = focusDistance; + this.postprocessing.scene = new THREE.Scene(); + this.postprocessing.camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10000, 10000 ); + this.postprocessing.scene.add( this.postprocessing.camera ); + const pars = { + minFilter: THREE.LinearFilter, + magFilter: THREE.LinearFilter, + format: THREE.RGBFormat + }; + this.postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars ); + this.postprocessing.rtTextureColor = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars ); + const bokeh_shader = THREE.BokehShader; + this.postprocessing.bokeh_uniforms = THREE.UniformsUtils.clone( bokeh_shader.uniforms ); + this.postprocessing.bokeh_uniforms[ 'tColor' ].value = this.postprocessing.rtTextureColor.texture; + this.postprocessing.bokeh_uniforms[ 'tDepth' ].value = this.postprocessing.rtTextureDepth.texture; + this.postprocessing.bokeh_uniforms[ 'manualdof' ].value = 0; + this.postprocessing.bokeh_uniforms[ 'shaderFocus' ].value = 0; + this.postprocessing.bokeh_uniforms[ 'fstop' ].value = 2.8; + this.postprocessing.bokeh_uniforms[ 'showFocus' ].value = 1; + this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = 0.1; //console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value ); - // the nearest point from the camera which is in focus (unused) - this.nearPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal + ( this.focus - focalLength ) ); + this.postprocessing.bokeh_uniforms[ 'znear' ].value = this.near; + this.postprocessing.bokeh_uniforms[ 'zfar' ].value = this.near; + this.postprocessing.bokeh_uniforms[ 'textureWidth' ].value = window.innerWidth; + this.postprocessing.bokeh_uniforms[ 'textureHeight' ].value = window.innerHeight; + this.postprocessing.materialBokeh = new THREE.ShaderMaterial( { + uniforms: this.postprocessing.bokeh_uniforms, + vertexShader: bokeh_shader.vertexShader, + fragmentShader: bokeh_shader.fragmentShader, + defines: { + RINGS: this.shaderSettings.rings, + SAMPLES: this.shaderSettings.samples, + DEPTH_PACKING: 1 + } + } ); + this.postprocessing.quad = new THREE.Mesh( new THREE.PlaneGeometry( window.innerWidth, window.innerHeight ), this.postprocessing.materialBokeh ); + this.postprocessing.quad.position.z = - 500; + this.postprocessing.scene.add( this.postprocessing.quad ); - // the farthest point from the camera which is in focus (unused) - this.farPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal - ( this.focus - focalLength ) ); - - // the gap or width of the space in which is everything is in focus (unused) - this.depthOfField = this.farPoint - this.nearPoint; - - // Considering minimum distance of focus for a standard lens (unused) - if ( this.depthOfField < 0 ) this.depthOfField = 0; - - this.sdistance = this.smoothstep( this.near, this.far, this.focus ); - - this.ldistance = this.linearize( 1 - this.sdistance ); - - this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = this.ldistance; - -}; - -THREE.CinematicCamera.prototype.initPostProcessing = function () { - - if ( this.postprocessing.enabled ) { - - this.postprocessing.scene = new THREE.Scene(); - - this.postprocessing.camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10000, 10000 ); - - this.postprocessing.scene.add( this.postprocessing.camera ); - - var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat }; - this.postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars ); - this.postprocessing.rtTextureColor = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars ); - - var bokeh_shader = THREE.BokehShader; - - this.postprocessing.bokeh_uniforms = THREE.UniformsUtils.clone( bokeh_shader.uniforms ); - - this.postprocessing.bokeh_uniforms[ 'tColor' ].value = this.postprocessing.rtTextureColor.texture; - this.postprocessing.bokeh_uniforms[ 'tDepth' ].value = this.postprocessing.rtTextureDepth.texture; - - this.postprocessing.bokeh_uniforms[ 'manualdof' ].value = 0; - this.postprocessing.bokeh_uniforms[ 'shaderFocus' ].value = 0; - - this.postprocessing.bokeh_uniforms[ 'fstop' ].value = 2.8; + } - this.postprocessing.bokeh_uniforms[ 'showFocus' ].value = 1; + } - this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = 0.1; + renderCinematic( scene, renderer ) { - //console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value ); + if ( this.postprocessing.enabled ) { - this.postprocessing.bokeh_uniforms[ 'znear' ].value = this.near; - this.postprocessing.bokeh_uniforms[ 'zfar' ].value = this.near; + const currentRenderTarget = renderer.getRenderTarget(); + renderer.clear(); // Render scene into texture + scene.overrideMaterial = null; + renderer.setRenderTarget( this.postprocessing.rtTextureColor ); + renderer.clear(); + renderer.render( scene, this ); // Render depth into texture - this.postprocessing.bokeh_uniforms[ 'textureWidth' ].value = window.innerWidth; + scene.overrideMaterial = this.materialDepth; + renderer.setRenderTarget( this.postprocessing.rtTextureDepth ); + renderer.clear(); + renderer.render( scene, this ); // Render bokeh composite - this.postprocessing.bokeh_uniforms[ 'textureHeight' ].value = window.innerHeight; + renderer.setRenderTarget( null ); + renderer.render( this.postprocessing.scene, this.postprocessing.camera ); + renderer.setRenderTarget( currentRenderTarget ); - this.postprocessing.materialBokeh = new THREE.ShaderMaterial( { - uniforms: this.postprocessing.bokeh_uniforms, - vertexShader: bokeh_shader.vertexShader, - fragmentShader: bokeh_shader.fragmentShader, - defines: { - RINGS: this.shaderSettings.rings, - SAMPLES: this.shaderSettings.samples, - DEPTH_PACKING: 1 } - } ); - this.postprocessing.quad = new THREE.Mesh( new THREE.PlaneGeometry( window.innerWidth, window.innerHeight ), this.postprocessing.materialBokeh ); - this.postprocessing.quad.position.z = - 500; - this.postprocessing.scene.add( this.postprocessing.quad ); + } } -}; - -THREE.CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) { - - if ( this.postprocessing.enabled ) { - - var currentRenderTarget = renderer.getRenderTarget(); - - renderer.clear(); - - // Render scene into texture - - scene.overrideMaterial = null; - renderer.setRenderTarget( this.postprocessing.rtTextureColor ); - renderer.clear(); - renderer.render( scene, this ); - - // Render depth into texture - - scene.overrideMaterial = this.materialDepth; - renderer.setRenderTarget( this.postprocessing.rtTextureDepth ); - renderer.clear(); - renderer.render( scene, this ); - - // Render bokeh composite - - renderer.setRenderTarget( null ); - renderer.render( this.postprocessing.scene, this.postprocessing.camera ); - - renderer.setRenderTarget( currentRenderTarget ); - - } + THREE.CinematicCamera = CinematicCamera; -}; +} )(); diff --git a/examples/js/controls/DeviceOrientationControls.js b/examples/js/controls/DeviceOrientationControls.js index 0d1be0349f650d..313922d3c4a56d 100644 --- a/examples/js/controls/DeviceOrientationControls.js +++ b/examples/js/controls/DeviceOrientationControls.js @@ -1,155 +1,147 @@ -/** - * W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html) - */ +( function () { -THREE.DeviceOrientationControls = function ( object ) { + const _zee = new THREE.Vector3( 0, 0, 1 ); - if ( window.isSecureContext === false ) { + const _euler = new THREE.Euler(); - console.error( 'THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)' ); + const _q0 = new THREE.Quaternion(); - } - - var scope = this; - var changeEvent = { type: 'change' }; - var EPS = 0.000001; - - this.object = object; - this.object.rotation.reorder( 'YXZ' ); - - this.enabled = true; - - this.deviceOrientation = {}; - this.screenOrientation = 0; - - this.alphaOffset = 0; // radians + const _q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis - var onDeviceOrientationChangeEvent = function ( event ) { - - scope.deviceOrientation = event; + const _changeEvent = { + type: 'change' }; - var onScreenOrientationChangeEvent = function () { + class DeviceOrientationControls extends THREE.EventDispatcher { - scope.screenOrientation = window.orientation || 0; + constructor( object ) { - }; + super(); - // The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' + if ( window.isSecureContext === false ) { - var setObjectQuaternion = function () { + console.error( 'THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)' ); - var zee = new THREE.Vector3( 0, 0, 1 ); + } - var euler = new THREE.Euler(); + const scope = this; + const EPS = 0.000001; + const lastQuaternion = new THREE.Quaternion(); + this.object = object; + this.object.rotation.reorder( 'YXZ' ); + this.enabled = true; + this.deviceOrientation = {}; + this.screenOrientation = 0; + this.alphaOffset = 0; // radians - var q0 = new THREE.Quaternion(); + const onDeviceOrientationChangeEvent = function ( event ) { - var q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis + scope.deviceOrientation = event; - return function ( quaternion, alpha, beta, gamma, orient ) { + }; - euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us + const onScreenOrientationChangeEvent = function () { - quaternion.setFromEuler( euler ); // orient the device + scope.screenOrientation = window.orientation || 0; - quaternion.multiply( q1 ); // camera looks out the back of the device, not the top + }; // The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' - quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation - }; + const setObjectQuaternion = function ( quaternion, alpha, beta, gamma, orient ) { - }(); + _euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us - this.connect = function () { - onScreenOrientationChangeEvent(); // run once on load + quaternion.setFromEuler( _euler ); // orient the device - // iOS 13+ + quaternion.multiply( _q1 ); // camera looks out the back of the device, not the top - if ( window.DeviceOrientationEvent !== undefined && typeof window.DeviceOrientationEvent.requestPermission === 'function' ) { + quaternion.multiply( _q0.setFromAxisAngle( _zee, - orient ) ); // adjust for screen orientation - window.DeviceOrientationEvent.requestPermission().then( function ( response ) { + }; - if ( response == 'granted' ) { + this.connect = function () { - window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent ); - window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent ); + onScreenOrientationChangeEvent(); // run once on load + // iOS 13+ - } + if ( window.DeviceOrientationEvent !== undefined && typeof window.DeviceOrientationEvent.requestPermission === 'function' ) { - } ).catch( function ( error ) { + window.DeviceOrientationEvent.requestPermission().then( function ( response ) { - console.error( 'THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:', error ); + if ( response == 'granted' ) { - } ); + window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent ); + window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent ); - } else { + } - window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent ); - window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent ); + } ).catch( function ( error ) { - } + console.error( 'THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:', error ); - scope.enabled = true; + } ); - }; + } else { - this.disconnect = function () { + window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent ); + window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent ); - window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent ); - window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent ); + } - scope.enabled = false; + scope.enabled = true; - }; + }; - this.update = ( function () { + this.disconnect = function () { - var lastQuaternion = new THREE.Quaternion(); + window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent ); + window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent ); + scope.enabled = false; - return function () { + }; - if ( scope.enabled === false ) return; + this.update = function () { - var device = scope.deviceOrientation; + if ( scope.enabled === false ) return; + const device = scope.deviceOrientation; - if ( device ) { + if ( device ) { - var alpha = device.alpha ? THREE.MathUtils.degToRad( device.alpha ) + scope.alphaOffset : 0; // Z + const alpha = device.alpha ? THREE.MathUtils.degToRad( device.alpha ) + scope.alphaOffset : 0; // Z - var beta = device.beta ? THREE.MathUtils.degToRad( device.beta ) : 0; // X' + const beta = device.beta ? THREE.MathUtils.degToRad( device.beta ) : 0; // X' - var gamma = device.gamma ? THREE.MathUtils.degToRad( device.gamma ) : 0; // Y'' + const gamma = device.gamma ? THREE.MathUtils.degToRad( device.gamma ) : 0; // Y'' - var orient = scope.screenOrientation ? THREE.MathUtils.degToRad( scope.screenOrientation ) : 0; // O + const orient = scope.screenOrientation ? THREE.MathUtils.degToRad( scope.screenOrientation ) : 0; // O - setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient ); + setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient ); - if ( 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + if ( 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { - lastQuaternion.copy( scope.object.quaternion ); - scope.dispatchEvent( changeEvent ); + lastQuaternion.copy( scope.object.quaternion ); + scope.dispatchEvent( _changeEvent ); - } + } - } + } - }; + }; + this.dispose = function () { - } )(); + scope.disconnect(); - this.dispose = function () { + }; - scope.disconnect(); + this.connect(); - }; + } - this.connect(); + } -}; + THREE.DeviceOrientationControls = DeviceOrientationControls; -THREE.DeviceOrientationControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.DeviceOrientationControls.prototype.constructor = THREE.DeviceOrientationControls; +} )(); diff --git a/examples/js/controls/DragControls.js b/examples/js/controls/DragControls.js index d450cf4699a013..8d37f592a40e17 100644 --- a/examples/js/controls/DragControls.js +++ b/examples/js/controls/DragControls.js @@ -1,316 +1,357 @@ -THREE.DragControls = function ( _objects, _camera, _domElement ) { +( function () { - var _plane = new THREE.Plane(); - var _raycaster = new THREE.Raycaster(); + const _plane = new THREE.Plane(); - var _mouse = new THREE.Vector2(); - var _offset = new THREE.Vector3(); - var _intersection = new THREE.Vector3(); - var _worldPosition = new THREE.Vector3(); - var _inverseMatrix = new THREE.Matrix4(); - var _intersections = []; + const _raycaster = new THREE.Raycaster(); - var _selected = null, _hovered = null; + const _mouse = new THREE.Vector2(); - // + const _offset = new THREE.Vector3(); - var scope = this; + const _intersection = new THREE.Vector3(); - function activate() { + const _worldPosition = new THREE.Vector3(); - _domElement.addEventListener( 'pointermove', onPointerMove ); - _domElement.addEventListener( 'pointerdown', onPointerDown ); - _domElement.addEventListener( 'pointerup', onPointerCancel ); - _domElement.addEventListener( 'pointerleave', onPointerCancel ); - _domElement.addEventListener( 'touchmove', onTouchMove ); - _domElement.addEventListener( 'touchstart', onTouchStart ); - _domElement.addEventListener( 'touchend', onTouchEnd ); + const _inverseMatrix = new THREE.Matrix4(); - } + class DragControls extends THREE.EventDispatcher { - function deactivate() { + constructor( _objects, _camera, _domElement ) { - _domElement.removeEventListener( 'pointermove', onPointerMove ); - _domElement.removeEventListener( 'pointerdown', onPointerDown ); - _domElement.removeEventListener( 'pointerup', onPointerCancel ); - _domElement.removeEventListener( 'pointerleave', onPointerCancel ); - _domElement.removeEventListener( 'touchmove', onTouchMove ); - _domElement.removeEventListener( 'touchstart', onTouchStart ); - _domElement.removeEventListener( 'touchend', onTouchEnd ); + super(); + let _selected = null, + _hovered = null; + const _intersections = []; // - _domElement.style.cursor = ''; + const scope = this; - } + function activate() { - function dispose() { + _domElement.addEventListener( 'pointermove', onPointerMove ); - deactivate(); + _domElement.addEventListener( 'pointerdown', onPointerDown ); - } + _domElement.addEventListener( 'pointerup', onPointerCancel ); - function getObjects() { + _domElement.addEventListener( 'pointerleave', onPointerCancel ); - return _objects; + _domElement.addEventListener( 'touchmove', onTouchMove, { + passive: false + } ); - } + _domElement.addEventListener( 'touchstart', onTouchStart, { + passive: false + } ); - function onPointerMove( event ) { + _domElement.addEventListener( 'touchend', onTouchEnd ); - event.preventDefault(); + } - switch ( event.pointerType ) { + function deactivate() { - case 'mouse': - case 'pen': - onMouseMove( event ); - break; + _domElement.removeEventListener( 'pointermove', onPointerMove ); - // TODO touch + _domElement.removeEventListener( 'pointerdown', onPointerDown ); - } + _domElement.removeEventListener( 'pointerup', onPointerCancel ); - } + _domElement.removeEventListener( 'pointerleave', onPointerCancel ); - function onMouseMove( event ) { + _domElement.removeEventListener( 'touchmove', onTouchMove ); - var rect = _domElement.getBoundingClientRect(); + _domElement.removeEventListener( 'touchstart', onTouchStart ); - _mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1; - _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; + _domElement.removeEventListener( 'touchend', onTouchEnd ); - _raycaster.setFromCamera( _mouse, _camera ); + _domElement.style.cursor = ''; - if ( _selected && scope.enabled ) { + } - if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { + function dispose() { - _selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) ); + deactivate(); } - scope.dispatchEvent( { type: 'drag', object: _selected } ); + function getObjects() { - return; - - } + return _objects; - _intersections.length = 0; + } - _raycaster.setFromCamera( _mouse, _camera ); - _raycaster.intersectObjects( _objects, true, _intersections ); + function onPointerMove( event ) { - if ( _intersections.length > 0 ) { + event.preventDefault(); - var object = _intersections[ 0 ].object; + switch ( event.pointerType ) { - _plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( object.matrixWorld ) ); + case 'mouse': + case 'pen': + onMouseMove( event ); + break; + // TODO touch - if ( _hovered !== object && _hovered !== null) { + } - scope.dispatchEvent( { type: 'hoveroff', object: _hovered } ); + } - _domElement.style.cursor = 'auto'; - _hovered = null; + function onMouseMove( event ) { - } - - if ( _hovered !== object ) { + const rect = _domElement.getBoundingClientRect(); - scope.dispatchEvent( { type: 'hoveron', object: object } ); + _mouse.x = ( event.clientX - rect.left ) / rect.width * 2 - 1; + _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; - _domElement.style.cursor = 'pointer'; - _hovered = object; + _raycaster.setFromCamera( _mouse, _camera ); - } + if ( _selected && scope.enabled ) { - } else { + if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { - if ( _hovered !== null ) { + _selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) ); - scope.dispatchEvent( { type: 'hoveroff', object: _hovered } ); + } - _domElement.style.cursor = 'auto'; - _hovered = null; + scope.dispatchEvent( { + type: 'drag', + object: _selected + } ); + return; - } + } - } + _intersections.length = 0; - } + _raycaster.setFromCamera( _mouse, _camera ); - function onPointerDown( event ) { + _raycaster.intersectObjects( _objects, true, _intersections ); - event.preventDefault(); + if ( _intersections.length > 0 ) { - switch ( event.pointerType ) { + const object = _intersections[ 0 ].object; - case 'mouse': - case 'pen': - onMouseDown( event ); - break; + _plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( object.matrixWorld ) ); - // TODO touch + if ( _hovered !== object && _hovered !== null ) { - } + scope.dispatchEvent( { + type: 'hoveroff', + object: _hovered + } ); + _domElement.style.cursor = 'auto'; + _hovered = null; - } + } - function onMouseDown( event ) { + if ( _hovered !== object ) { - event.preventDefault(); + scope.dispatchEvent( { + type: 'hoveron', + object: object + } ); + _domElement.style.cursor = 'pointer'; + _hovered = object; - _intersections.length = 0; + } - _raycaster.setFromCamera( _mouse, _camera ); - _raycaster.intersectObjects( _objects, true, _intersections ); + } else { - if ( _intersections.length > 0 ) { + if ( _hovered !== null ) { - _selected = ( scope.transformGroup === true ) ? _objects[ 0 ] : _intersections[ 0 ].object; + scope.dispatchEvent( { + type: 'hoveroff', + object: _hovered + } ); + _domElement.style.cursor = 'auto'; + _hovered = null; - if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { + } - _inverseMatrix.copy( _selected.parent.matrixWorld ).invert(); - _offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); + } } - _domElement.style.cursor = 'move'; + function onPointerDown( event ) { - scope.dispatchEvent( { type: 'dragstart', object: _selected } ); + event.preventDefault(); - } + switch ( event.pointerType ) { + case 'mouse': + case 'pen': + onMouseDown( event ); + break; + // TODO touch - } + } - function onPointerCancel( event ) { + } - event.preventDefault(); + function onMouseDown( event ) { - switch ( event.pointerType ) { + event.preventDefault(); + _intersections.length = 0; - case 'mouse': - case 'pen': - onMouseCancel( event ); - break; + _raycaster.setFromCamera( _mouse, _camera ); - // TODO touch + _raycaster.intersectObjects( _objects, true, _intersections ); - } + if ( _intersections.length > 0 ) { - } + _selected = scope.transformGroup === true ? _objects[ 0 ] : _intersections[ 0 ].object; - function onMouseCancel( event ) { + if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { - event.preventDefault(); + _inverseMatrix.copy( _selected.parent.matrixWorld ).invert(); - if ( _selected ) { + _offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); - scope.dispatchEvent( { type: 'dragend', object: _selected } ); + } - _selected = null; + _domElement.style.cursor = 'move'; + scope.dispatchEvent( { + type: 'dragstart', + object: _selected + } ); - } + } - _domElement.style.cursor = _hovered ? 'pointer' : 'auto'; + } - } + function onPointerCancel( event ) { + + event.preventDefault(); + + switch ( event.pointerType ) { + + case 'mouse': + case 'pen': + onMouseCancel( event ); + break; + // TODO touch - function onTouchMove( event ) { + } - event.preventDefault(); - event = event.changedTouches[ 0 ]; + } - var rect = _domElement.getBoundingClientRect(); + function onMouseCancel( event ) { - _mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1; - _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; + event.preventDefault(); - _raycaster.setFromCamera( _mouse, _camera ); + if ( _selected ) { - if ( _selected && scope.enabled ) { + scope.dispatchEvent( { + type: 'dragend', + object: _selected + } ); + _selected = null; - if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { + } - _selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) ); + _domElement.style.cursor = _hovered ? 'pointer' : 'auto'; } - scope.dispatchEvent( { type: 'drag', object: _selected } ); + function onTouchMove( event ) { - return; + event.preventDefault(); + event = event.changedTouches[ 0 ]; - } + const rect = _domElement.getBoundingClientRect(); - } + _mouse.x = ( event.clientX - rect.left ) / rect.width * 2 - 1; + _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; - function onTouchStart( event ) { + _raycaster.setFromCamera( _mouse, _camera ); - event.preventDefault(); - event = event.changedTouches[ 0 ]; + if ( _selected && scope.enabled ) { - var rect = _domElement.getBoundingClientRect(); + if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { - _mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1; - _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; + _selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) ); - _intersections.length = 0; + } - _raycaster.setFromCamera( _mouse, _camera ); - _raycaster.intersectObjects( _objects, true, _intersections ); + scope.dispatchEvent( { + type: 'drag', + object: _selected + } ); + return; - if ( _intersections.length > 0 ) { + } - _selected = ( scope.transformGroup === true ) ? _objects[ 0 ] : _intersections[ 0 ].object; + } - _plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); + function onTouchStart( event ) { - if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { + event.preventDefault(); + event = event.changedTouches[ 0 ]; - _inverseMatrix.copy( _selected.parent.matrixWorld ).invert(); - _offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); + const rect = _domElement.getBoundingClientRect(); - } + _mouse.x = ( event.clientX - rect.left ) / rect.width * 2 - 1; + _mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1; + _intersections.length = 0; - _domElement.style.cursor = 'move'; + _raycaster.setFromCamera( _mouse, _camera ); - scope.dispatchEvent( { type: 'dragstart', object: _selected } ); + _raycaster.intersectObjects( _objects, true, _intersections ); - } + if ( _intersections.length > 0 ) { + _selected = scope.transformGroup === true ? _objects[ 0 ] : _intersections[ 0 ].object; - } + _plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); - function onTouchEnd( event ) { + if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) { - event.preventDefault(); + _inverseMatrix.copy( _selected.parent.matrixWorld ).invert(); - if ( _selected ) { + _offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) ); - scope.dispatchEvent( { type: 'dragend', object: _selected } ); + } - _selected = null; + _domElement.style.cursor = 'move'; + scope.dispatchEvent( { + type: 'dragstart', + object: _selected + } ); - } + } + + } - _domElement.style.cursor = 'auto'; + function onTouchEnd( event ) { - } + event.preventDefault(); - activate(); + if ( _selected ) { - // API + scope.dispatchEvent( { + type: 'dragend', + object: _selected + } ); + _selected = null; - this.enabled = true; - this.transformGroup = false; + } - this.activate = activate; - this.deactivate = deactivate; - this.dispose = dispose; - this.getObjects = getObjects; + _domElement.style.cursor = 'auto'; + + } + + activate(); // API + + this.enabled = true; + this.transformGroup = false; + this.activate = activate; + this.deactivate = deactivate; + this.dispose = dispose; + this.getObjects = getObjects; + + } + + } -}; + THREE.DragControls = DragControls; -THREE.DragControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.DragControls.prototype.constructor = THREE.DragControls; +} )(); diff --git a/examples/js/controls/FirstPersonControls.js b/examples/js/controls/FirstPersonControls.js index 2f886b0dc5b57f..87a2974479fd70 100644 --- a/examples/js/controls/FirstPersonControls.js +++ b/examples/js/controls/FirstPersonControls.js @@ -1,287 +1,339 @@ -THREE.FirstPersonControls = function ( object, domElement ) { +( function () { - if ( domElement === undefined ) { + const _lookDirection = new THREE.Vector3(); - console.warn( 'THREE.FirstPersonControls: The second parameter "domElement" is now mandatory.' ); - domElement = document; + const _spherical = new THREE.Spherical(); - } + const _target = new THREE.Vector3(); - this.object = object; - this.domElement = domElement; + class FirstPersonControls { - // API + constructor( object, domElement ) { - this.enabled = true; + if ( domElement === undefined ) { - this.movementSpeed = 1.0; - this.lookSpeed = 0.005; + console.warn( 'THREE.FirstPersonControls: The second parameter "domElement" is now mandatory.' ); + domElement = document; - this.lookVertical = true; - this.autoForward = false; + } - this.activeLook = true; + this.object = object; + this.domElement = domElement; // API - this.heightSpeed = false; - this.heightCoef = 1.0; - this.heightMin = 0.0; - this.heightMax = 1.0; + this.enabled = true; + this.movementSpeed = 1.0; + this.lookSpeed = 0.005; + this.lookVertical = true; + this.autoForward = false; + this.activeLook = true; + this.heightSpeed = false; + this.heightCoef = 1.0; + this.heightMin = 0.0; + this.heightMax = 1.0; + this.constrainVertical = false; + this.verticalMin = 0; + this.verticalMax = Math.PI; + this.mouseDragOn = false; // internals - this.constrainVertical = false; - this.verticalMin = 0; - this.verticalMax = Math.PI; + this.autoSpeedFactor = 0.0; + this.mouseX = 0; + this.mouseY = 0; + this.moveForward = false; + this.moveBackward = false; + this.moveLeft = false; + this.moveRight = false; + this.viewHalfX = 0; + this.viewHalfY = 0; // private variables - this.mouseDragOn = false; + let lat = 0; + let lon = 0; // - // internals + this.handleResize = function () { - this.autoSpeedFactor = 0.0; + if ( this.domElement === document ) { - this.mouseX = 0; - this.mouseY = 0; + this.viewHalfX = window.innerWidth / 2; + this.viewHalfY = window.innerHeight / 2; - this.moveForward = false; - this.moveBackward = false; - this.moveLeft = false; - this.moveRight = false; + } else { - this.viewHalfX = 0; - this.viewHalfY = 0; + this.viewHalfX = this.domElement.offsetWidth / 2; + this.viewHalfY = this.domElement.offsetHeight / 2; - // private variables + } - var lat = 0; - var lon = 0; + }; - var lookDirection = new THREE.Vector3(); - var spherical = new THREE.Spherical(); - var target = new THREE.Vector3(); + this.onMouseDown = function ( event ) { - // + if ( this.domElement !== document ) { - if ( this.domElement !== document ) { + this.domElement.focus(); - this.domElement.setAttribute( 'tabindex', - 1 ); + } - } + event.preventDefault(); - // + if ( this.activeLook ) { - this.handleResize = function () { + switch ( event.button ) { - if ( this.domElement === document ) { + case 0: + this.moveForward = true; + break; - this.viewHalfX = window.innerWidth / 2; - this.viewHalfY = window.innerHeight / 2; + case 2: + this.moveBackward = true; + break; - } else { + } - this.viewHalfX = this.domElement.offsetWidth / 2; - this.viewHalfY = this.domElement.offsetHeight / 2; + } - } + this.mouseDragOn = true; - }; + }; - this.onMouseDown = function ( event ) { + this.onMouseUp = function ( event ) { - if ( this.domElement !== document ) { + event.preventDefault(); - this.domElement.focus(); + if ( this.activeLook ) { - } + switch ( event.button ) { - event.preventDefault(); + case 0: + this.moveForward = false; + break; - if ( this.activeLook ) { + case 2: + this.moveBackward = false; + break; - switch ( event.button ) { + } - case 0: this.moveForward = true; break; - case 2: this.moveBackward = true; break; + } - } - - } + this.mouseDragOn = false; - this.mouseDragOn = true; + }; - }; + this.onMouseMove = function ( event ) { - this.onMouseUp = function ( event ) { - - event.preventDefault(); + if ( this.domElement === document ) { - if ( this.activeLook ) { + this.mouseX = event.pageX - this.viewHalfX; + this.mouseY = event.pageY - this.viewHalfY; - switch ( event.button ) { + } else { - case 0: this.moveForward = false; break; - case 2: this.moveBackward = false; break; + this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; + this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY; - } + } - } + }; - this.mouseDragOn = false; + this.onKeyDown = function ( event ) { - }; + //event.preventDefault(); + switch ( event.code ) { - this.onMouseMove = function ( event ) { + case 'ArrowUp': + case 'KeyW': + this.moveForward = true; + break; - if ( this.domElement === document ) { + case 'ArrowLeft': + case 'KeyA': + this.moveLeft = true; + break; - this.mouseX = event.pageX - this.viewHalfX; - this.mouseY = event.pageY - this.viewHalfY; + case 'ArrowDown': + case 'KeyS': + this.moveBackward = true; + break; - } else { + case 'ArrowRight': + case 'KeyD': + this.moveRight = true; + break; - this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX; - this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY; + case 'KeyR': + this.moveUp = true; + break; - } + case 'KeyF': + this.moveDown = true; + break; - }; + } - this.onKeyDown = function ( event ) { + }; - //event.preventDefault(); + this.onKeyUp = function ( event ) { - switch ( event.code ) { + switch ( event.code ) { - case 'ArrowUp': - case 'KeyW': this.moveForward = true; break; + case 'ArrowUp': + case 'KeyW': + this.moveForward = false; + break; - case 'ArrowLeft': - case 'KeyA': this.moveLeft = true; break; + case 'ArrowLeft': + case 'KeyA': + this.moveLeft = false; + break; - case 'ArrowDown': - case 'KeyS': this.moveBackward = true; break; + case 'ArrowDown': + case 'KeyS': + this.moveBackward = false; + break; - case 'ArrowRight': - case 'KeyD': this.moveRight = true; break; + case 'ArrowRight': + case 'KeyD': + this.moveRight = false; + break; - case 'KeyR': this.moveUp = true; break; - case 'KeyF': this.moveDown = true; break; + case 'KeyR': + this.moveUp = false; + break; - } + case 'KeyF': + this.moveDown = false; + break; - }; + } - this.onKeyUp = function ( event ) { + }; - switch ( event.code ) { + this.lookAt = function ( x, y, z ) { - case 'ArrowUp': - case 'KeyW': this.moveForward = false; break; + if ( x.isVector3 ) { - case 'ArrowLeft': - case 'KeyA': this.moveLeft = false; break; + _target.copy( x ); - case 'ArrowDown': - case 'KeyS': this.moveBackward = false; break; + } else { - case 'ArrowRight': - case 'KeyD': this.moveRight = false; break; + _target.set( x, y, z ); - case 'KeyR': this.moveUp = false; break; - case 'KeyF': this.moveDown = false; break; + } - } + this.object.lookAt( _target ); + setOrientation( this ); + return this; - }; + }; - this.lookAt = function ( x, y, z ) { + this.update = function () { - if ( x.isVector3 ) { + const targetPosition = new THREE.Vector3(); + return function update( delta ) { - target.copy( x ); + if ( this.enabled === false ) return; - } else { + if ( this.heightSpeed ) { - target.set( x, y, z ); + const y = THREE.MathUtils.clamp( this.object.position.y, this.heightMin, this.heightMax ); + const heightDelta = y - this.heightMin; + this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef ); - } + } else { - this.object.lookAt( target ); + this.autoSpeedFactor = 0.0; - setOrientation( this ); + } - return this; + const actualMoveSpeed = delta * this.movementSpeed; + if ( this.moveForward || this.autoForward && ! this.moveBackward ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); + if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed ); + if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed ); + if ( this.moveRight ) this.object.translateX( actualMoveSpeed ); + if ( this.moveUp ) this.object.translateY( actualMoveSpeed ); + if ( this.moveDown ) this.object.translateY( - actualMoveSpeed ); + let actualLookSpeed = delta * this.lookSpeed; - }; + if ( ! this.activeLook ) { - this.update = function () { + actualLookSpeed = 0; - var targetPosition = new THREE.Vector3(); + } - return function update( delta ) { + let verticalLookRatio = 1; - if ( this.enabled === false ) return; + if ( this.constrainVertical ) { - if ( this.heightSpeed ) { + verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin ); - var y = THREE.MathUtils.clamp( this.object.position.y, this.heightMin, this.heightMax ); - var heightDelta = y - this.heightMin; + } - this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef ); + lon -= this.mouseX * actualLookSpeed; + if ( this.lookVertical ) lat -= this.mouseY * actualLookSpeed * verticalLookRatio; + lat = Math.max( - 85, Math.min( 85, lat ) ); + let phi = THREE.MathUtils.degToRad( 90 - lat ); + const theta = THREE.MathUtils.degToRad( lon ); - } else { + if ( this.constrainVertical ) { - this.autoSpeedFactor = 0.0; + phi = THREE.MathUtils.mapLinear( phi, 0, Math.PI, this.verticalMin, this.verticalMax ); - } + } - var actualMoveSpeed = delta * this.movementSpeed; + const position = this.object.position; + targetPosition.setFromSphericalCoords( 1, phi, theta ).add( position ); + this.object.lookAt( targetPosition ); - if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); - if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed ); + }; - if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed ); - if ( this.moveRight ) this.object.translateX( actualMoveSpeed ); + }(); - if ( this.moveUp ) this.object.translateY( actualMoveSpeed ); - if ( this.moveDown ) this.object.translateY( - actualMoveSpeed ); + this.dispose = function () { - var actualLookSpeed = delta * this.lookSpeed; + this.domElement.removeEventListener( 'contextmenu', contextmenu ); + this.domElement.removeEventListener( 'mousedown', _onMouseDown ); + this.domElement.removeEventListener( 'mousemove', _onMouseMove ); + this.domElement.removeEventListener( 'mouseup', _onMouseUp ); + window.removeEventListener( 'keydown', _onKeyDown ); + window.removeEventListener( 'keyup', _onKeyUp ); - if ( ! this.activeLook ) { + }; - actualLookSpeed = 0; + const _onMouseMove = this.onMouseMove.bind( this ); - } + const _onMouseDown = this.onMouseDown.bind( this ); - var verticalLookRatio = 1; + const _onMouseUp = this.onMouseUp.bind( this ); - if ( this.constrainVertical ) { + const _onKeyDown = this.onKeyDown.bind( this ); - verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin ); + const _onKeyUp = this.onKeyUp.bind( this ); - } + this.domElement.addEventListener( 'contextmenu', contextmenu ); + this.domElement.addEventListener( 'mousemove', _onMouseMove ); + this.domElement.addEventListener( 'mousedown', _onMouseDown ); + this.domElement.addEventListener( 'mouseup', _onMouseUp ); + window.addEventListener( 'keydown', _onKeyDown ); + window.addEventListener( 'keyup', _onKeyUp ); - lon -= this.mouseX * actualLookSpeed; - if ( this.lookVertical ) lat -= this.mouseY * actualLookSpeed * verticalLookRatio; + function setOrientation( controls ) { - lat = Math.max( - 85, Math.min( 85, lat ) ); + const quaternion = controls.object.quaternion; - var phi = THREE.MathUtils.degToRad( 90 - lat ); - var theta = THREE.MathUtils.degToRad( lon ); + _lookDirection.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - if ( this.constrainVertical ) { + _spherical.setFromVector3( _lookDirection ); - phi = THREE.MathUtils.mapLinear( phi, 0, Math.PI, this.verticalMin, this.verticalMax ); + lat = 90 - THREE.MathUtils.radToDeg( _spherical.phi ); + lon = THREE.MathUtils.radToDeg( _spherical.theta ); } - var position = this.object.position; - - targetPosition.setFromSphericalCoords( 1, phi, theta ).add( position ); - - this.object.lookAt( targetPosition ); + this.handleResize(); + setOrientation( this ); - }; + } - }(); + } function contextmenu( event ) { @@ -289,56 +341,6 @@ THREE.FirstPersonControls = function ( object, domElement ) { } - this.dispose = function () { - - this.domElement.removeEventListener( 'contextmenu', contextmenu ); - this.domElement.removeEventListener( 'mousedown', _onMouseDown ); - this.domElement.removeEventListener( 'mousemove', _onMouseMove ); - this.domElement.removeEventListener( 'mouseup', _onMouseUp ); - - window.removeEventListener( 'keydown', _onKeyDown ); - window.removeEventListener( 'keyup', _onKeyUp ); - - }; - - var _onMouseMove = bind( this, this.onMouseMove ); - var _onMouseDown = bind( this, this.onMouseDown ); - var _onMouseUp = bind( this, this.onMouseUp ); - var _onKeyDown = bind( this, this.onKeyDown ); - var _onKeyUp = bind( this, this.onKeyUp ); - - this.domElement.addEventListener( 'contextmenu', contextmenu ); - this.domElement.addEventListener( 'mousemove', _onMouseMove ); - this.domElement.addEventListener( 'mousedown', _onMouseDown ); - this.domElement.addEventListener( 'mouseup', _onMouseUp ); - - window.addEventListener( 'keydown', _onKeyDown ); - window.addEventListener( 'keyup', _onKeyUp ); - - function bind( scope, fn ) { - - return function () { - - fn.apply( scope, arguments ); - - }; - - } - - function setOrientation( controls ) { - - var quaternion = controls.object.quaternion; - - lookDirection.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - spherical.setFromVector3( lookDirection ); - - lat = 90 - THREE.MathUtils.radToDeg( spherical.phi ); - lon = THREE.MathUtils.radToDeg( spherical.theta ); - - } - - this.handleResize(); - - setOrientation( this ); + THREE.FirstPersonControls = FirstPersonControls; -}; +} )(); diff --git a/examples/js/controls/FlyControls.js b/examples/js/controls/FlyControls.js index 2b3fb71d36f1a9..d3fb2049df16ce 100644 --- a/examples/js/controls/FlyControls.js +++ b/examples/js/controls/FlyControls.js @@ -1,267 +1,357 @@ -THREE.FlyControls = function ( object, domElement ) { +( function () { - if ( domElement === undefined ) { + const _changeEvent = { + type: 'change' + }; - console.warn( 'THREE.FlyControls: The second parameter "domElement" is now mandatory.' ); - domElement = document; + class FlyControls extends THREE.EventDispatcher { - } + constructor( object, domElement ) { - this.object = object; - this.domElement = domElement; + super(); - if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 ); + if ( domElement === undefined ) { - // API + console.warn( 'THREE.FlyControls: The second parameter "domElement" is now mandatory.' ); + domElement = document; - this.movementSpeed = 1.0; - this.rollSpeed = 0.005; + } - this.dragToLook = false; - this.autoForward = false; + this.object = object; + this.domElement = domElement; // API + + this.movementSpeed = 1.0; + this.rollSpeed = 0.005; + this.dragToLook = false; + this.autoForward = false; // disable default target object behavior + // internals + + const scope = this; + const EPS = 0.000001; + const lastQuaternion = new THREE.Quaternion(); + const lastPosition = new THREE.Vector3(); + this.tmpQuaternion = new THREE.Quaternion(); + this.mouseStatus = 0; + this.moveState = { + up: 0, + down: 0, + left: 0, + right: 0, + forward: 0, + back: 0, + pitchUp: 0, + pitchDown: 0, + yawLeft: 0, + yawRight: 0, + rollLeft: 0, + rollRight: 0 + }; + this.moveVector = new THREE.Vector3( 0, 0, 0 ); + this.rotationVector = new THREE.Vector3( 0, 0, 0 ); - // disable default target object behavior + this.keydown = function ( event ) { - // internals + if ( event.altKey ) { - var scope = this; - var changeEvent = { type: 'change' }; - var EPS = 0.000001; + return; - this.tmpQuaternion = new THREE.Quaternion(); + } //event.preventDefault(); - this.mouseStatus = 0; - this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 }; - this.moveVector = new THREE.Vector3( 0, 0, 0 ); - this.rotationVector = new THREE.Vector3( 0, 0, 0 ); + switch ( event.code ) { - this.keydown = function ( event ) { + case 'ShiftLeft': + case 'ShiftRight': + this.movementSpeedMultiplier = .1; + break; - if ( event.altKey ) { + case 'KeyW': + this.moveState.forward = 1; + break; - return; + case 'KeyS': + this.moveState.back = 1; + break; - } + case 'KeyA': + this.moveState.left = 1; + break; - //event.preventDefault(); + case 'KeyD': + this.moveState.right = 1; + break; - switch ( event.code ) { + case 'KeyR': + this.moveState.up = 1; + break; - case 'ShiftLeft': - case 'ShiftRight': this.movementSpeedMultiplier = .1; break; + case 'KeyF': + this.moveState.down = 1; + break; - case 'KeyW': this.moveState.forward = 1; break; - case 'KeyS': this.moveState.back = 1; break; + case 'ArrowUp': + this.moveState.pitchUp = 1; + break; - case 'KeyA': this.moveState.left = 1; break; - case 'KeyD': this.moveState.right = 1; break; + case 'ArrowDown': + this.moveState.pitchDown = 1; + break; - case 'KeyR': this.moveState.up = 1; break; - case 'KeyF': this.moveState.down = 1; break; + case 'ArrowLeft': + this.moveState.yawLeft = 1; + break; - case 'ArrowUp': this.moveState.pitchUp = 1; break; - case 'ArrowDown': this.moveState.pitchDown = 1; break; + case 'ArrowRight': + this.moveState.yawRight = 1; + break; - case 'ArrowLeft': this.moveState.yawLeft = 1; break; - case 'ArrowRight': this.moveState.yawRight = 1; break; + case 'KeyQ': + this.moveState.rollLeft = 1; + break; - case 'KeyQ': this.moveState.rollLeft = 1; break; - case 'KeyE': this.moveState.rollRight = 1; break; + case 'KeyE': + this.moveState.rollRight = 1; + break; - } + } - this.updateMovementVector(); - this.updateRotationVector(); + this.updateMovementVector(); + this.updateRotationVector(); - }; + }; - this.keyup = function ( event ) { + this.keyup = function ( event ) { - switch ( event.code ) { + switch ( event.code ) { - case 'ShiftLeft': - case 'ShiftRight': this.movementSpeedMultiplier = 1; break; + case 'ShiftLeft': + case 'ShiftRight': + this.movementSpeedMultiplier = 1; + break; - case 'KeyW': this.moveState.forward = 0; break; - case 'KeyS': this.moveState.back = 0; break; + case 'KeyW': + this.moveState.forward = 0; + break; - case 'KeyA': this.moveState.left = 0; break; - case 'KeyD': this.moveState.right = 0; break; + case 'KeyS': + this.moveState.back = 0; + break; - case 'KeyR': this.moveState.up = 0; break; - case 'KeyF': this.moveState.down = 0; break; + case 'KeyA': + this.moveState.left = 0; + break; - case 'ArrowUp': this.moveState.pitchUp = 0; break; - case 'ArrowDown': this.moveState.pitchDown = 0; break; + case 'KeyD': + this.moveState.right = 0; + break; - case 'ArrowLeft': this.moveState.yawLeft = 0; break; - case 'ArrowRight': this.moveState.yawRight = 0; break; + case 'KeyR': + this.moveState.up = 0; + break; - case 'KeyQ': this.moveState.rollLeft = 0; break; - case 'KeyE': this.moveState.rollRight = 0; break; + case 'KeyF': + this.moveState.down = 0; + break; - } + case 'ArrowUp': + this.moveState.pitchUp = 0; + break; - this.updateMovementVector(); - this.updateRotationVector(); + case 'ArrowDown': + this.moveState.pitchDown = 0; + break; - }; + case 'ArrowLeft': + this.moveState.yawLeft = 0; + break; - this.mousedown = function ( event ) { + case 'ArrowRight': + this.moveState.yawRight = 0; + break; - if ( this.domElement !== document ) { + case 'KeyQ': + this.moveState.rollLeft = 0; + break; - this.domElement.focus(); + case 'KeyE': + this.moveState.rollRight = 0; + break; - } + } - event.preventDefault(); + this.updateMovementVector(); + this.updateRotationVector(); - if ( this.dragToLook ) { + }; - this.mouseStatus ++; + this.mousedown = function ( event ) { - } else { + if ( this.domElement !== document ) { - switch ( event.button ) { + this.domElement.focus(); - case 0: this.moveState.forward = 1; break; - case 2: this.moveState.back = 1; break; + } - } + event.preventDefault(); - this.updateMovementVector(); + if ( this.dragToLook ) { - } + this.mouseStatus ++; - }; + } else { - this.mousemove = function ( event ) { + switch ( event.button ) { - if ( ! this.dragToLook || this.mouseStatus > 0 ) { + case 0: + this.moveState.forward = 1; + break; - var container = this.getContainerDimensions(); - var halfWidth = container.size[ 0 ] / 2; - var halfHeight = container.size[ 1 ] / 2; + case 2: + this.moveState.back = 1; + break; - this.moveState.yawLeft = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth ) / halfWidth; - this.moveState.pitchDown = ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight; + } - this.updateRotationVector(); + this.updateMovementVector(); - } + } - }; + }; - this.mouseup = function ( event ) { + this.mousemove = function ( event ) { - event.preventDefault(); + if ( ! this.dragToLook || this.mouseStatus > 0 ) { - if ( this.dragToLook ) { + const container = this.getContainerDimensions(); + const halfWidth = container.size[ 0 ] / 2; + const halfHeight = container.size[ 1 ] / 2; + this.moveState.yawLeft = - ( event.pageX - container.offset[ 0 ] - halfWidth ) / halfWidth; + this.moveState.pitchDown = ( event.pageY - container.offset[ 1 ] - halfHeight ) / halfHeight; + this.updateRotationVector(); - this.mouseStatus --; + } - this.moveState.yawLeft = this.moveState.pitchDown = 0; + }; - } else { + this.mouseup = function ( event ) { - switch ( event.button ) { + event.preventDefault(); - case 0: this.moveState.forward = 0; break; - case 2: this.moveState.back = 0; break; + if ( this.dragToLook ) { - } + this.mouseStatus --; + this.moveState.yawLeft = this.moveState.pitchDown = 0; - this.updateMovementVector(); + } else { - } + switch ( event.button ) { - this.updateRotationVector(); + case 0: + this.moveState.forward = 0; + break; - }; + case 2: + this.moveState.back = 0; + break; - this.update = function () { + } - var lastQuaternion = new THREE.Quaternion(); - var lastPosition = new THREE.Vector3(); + this.updateMovementVector(); - return function ( delta ) { + } - var moveMult = delta * scope.movementSpeed; - var rotMult = delta * scope.rollSpeed; + this.updateRotationVector(); - scope.object.translateX( scope.moveVector.x * moveMult ); - scope.object.translateY( scope.moveVector.y * moveMult ); - scope.object.translateZ( scope.moveVector.z * moveMult ); + }; - scope.tmpQuaternion.set( scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1 ).normalize(); - scope.object.quaternion.multiply( scope.tmpQuaternion ); + this.update = function ( delta ) { - if ( - lastPosition.distanceToSquared( scope.object.position ) > EPS || - 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS - ) { + const moveMult = delta * scope.movementSpeed; + const rotMult = delta * scope.rollSpeed; + scope.object.translateX( scope.moveVector.x * moveMult ); + scope.object.translateY( scope.moveVector.y * moveMult ); + scope.object.translateZ( scope.moveVector.z * moveMult ); + scope.tmpQuaternion.set( scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1 ).normalize(); + scope.object.quaternion.multiply( scope.tmpQuaternion ); - scope.dispatchEvent( changeEvent ); - lastQuaternion.copy( scope.object.quaternion ); - lastPosition.copy( scope.object.position ); + if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { - } + scope.dispatchEvent( _changeEvent ); + lastQuaternion.copy( scope.object.quaternion ); + lastPosition.copy( scope.object.position ); - }; + } - }(); + }; - this.updateMovementVector = function () { + this.updateMovementVector = function () { - var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0; + const forward = this.moveState.forward || this.autoForward && ! this.moveState.back ? 1 : 0; + this.moveVector.x = - this.moveState.left + this.moveState.right; + this.moveVector.y = - this.moveState.down + this.moveState.up; + this.moveVector.z = - forward + this.moveState.back; //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); - this.moveVector.x = ( - this.moveState.left + this.moveState.right ); - this.moveVector.y = ( - this.moveState.down + this.moveState.up ); - this.moveVector.z = ( - forward + this.moveState.back ); + }; - //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] ); + this.updateRotationVector = function () { - }; + this.rotationVector.x = - this.moveState.pitchDown + this.moveState.pitchUp; + this.rotationVector.y = - this.moveState.yawRight + this.moveState.yawLeft; + this.rotationVector.z = - this.moveState.rollRight + this.moveState.rollLeft; //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); - this.updateRotationVector = function () { + }; - this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp ); - this.rotationVector.y = ( - this.moveState.yawRight + this.moveState.yawLeft ); - this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft ); + this.getContainerDimensions = function () { - //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] ); + if ( this.domElement != document ) { - }; + return { + size: [ this.domElement.offsetWidth, this.domElement.offsetHeight ], + offset: [ this.domElement.offsetLeft, this.domElement.offsetTop ] + }; + + } else { - this.getContainerDimensions = function () { + return { + size: [ window.innerWidth, window.innerHeight ], + offset: [ 0, 0 ] + }; - if ( this.domElement != document ) { + } - return { - size: [ this.domElement.offsetWidth, this.domElement.offsetHeight ], - offset: [ this.domElement.offsetLeft, this.domElement.offsetTop ] }; - } else { + this.dispose = function () { + + this.domElement.removeEventListener( 'contextmenu', contextmenu ); + this.domElement.removeEventListener( 'mousedown', _mousedown ); + this.domElement.removeEventListener( 'mousemove', _mousemove ); + this.domElement.removeEventListener( 'mouseup', _mouseup ); + window.removeEventListener( 'keydown', _keydown ); + window.removeEventListener( 'keyup', _keyup ); - return { - size: [ window.innerWidth, window.innerHeight ], - offset: [ 0, 0 ] }; - } + const _mousemove = this.mousemove.bind( this ); - }; + const _mousedown = this.mousedown.bind( this ); + + const _mouseup = this.mouseup.bind( this ); - function bind( scope, fn ) { + const _keydown = this.keydown.bind( this ); - return function () { + const _keyup = this.keyup.bind( this ); - fn.apply( scope, arguments ); + this.domElement.addEventListener( 'contextmenu', contextmenu ); + this.domElement.addEventListener( 'mousemove', _mousemove ); + this.domElement.addEventListener( 'mousedown', _mousedown ); + this.domElement.addEventListener( 'mouseup', _mouseup ); + window.addEventListener( 'keydown', _keydown ); + window.addEventListener( 'keyup', _keyup ); + this.updateMovementVector(); + this.updateRotationVector(); - }; + } } @@ -271,37 +361,6 @@ THREE.FlyControls = function ( object, domElement ) { } - this.dispose = function () { - - this.domElement.removeEventListener( 'contextmenu', contextmenu ); - this.domElement.removeEventListener( 'mousedown', _mousedown ); - this.domElement.removeEventListener( 'mousemove', _mousemove ); - this.domElement.removeEventListener( 'mouseup', _mouseup ); - - window.removeEventListener( 'keydown', _keydown ); - window.removeEventListener( 'keyup', _keyup ); - - }; - - var _mousemove = bind( this, this.mousemove ); - var _mousedown = bind( this, this.mousedown ); - var _mouseup = bind( this, this.mouseup ); - var _keydown = bind( this, this.keydown ); - var _keyup = bind( this, this.keyup ); - - this.domElement.addEventListener( 'contextmenu', contextmenu ); - - this.domElement.addEventListener( 'mousemove', _mousemove ); - this.domElement.addEventListener( 'mousedown', _mousedown ); - this.domElement.addEventListener( 'mouseup', _mouseup ); - - window.addEventListener( 'keydown', _keydown ); - window.addEventListener( 'keyup', _keyup ); - - this.updateMovementVector(); - this.updateRotationVector(); - -}; + THREE.FlyControls = FlyControls; -THREE.FlyControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.FlyControls.prototype.constructor = THREE.FlyControls; +} )(); diff --git a/examples/js/controls/OrbitControls.js b/examples/js/controls/OrbitControls.js index 68693a82760205..0873097102ca98 100644 --- a/examples/js/controls/OrbitControls.js +++ b/examples/js/controls/OrbitControls.js @@ -1,1215 +1,1045 @@ -// This set of controls performs orbiting, dollying (zooming), and panning. -// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). -// -// Orbit - left mouse / touch: one-finger move -// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish -// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move - -THREE.OrbitControls = function ( object, domElement ) { - - if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' ); - if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); - - this.object = object; - this.domElement = domElement; - - // Set to false to disable this control - this.enabled = true; - - // "target" sets the location of focus, where the object orbits around - this.target = new THREE.Vector3(); - - // How far you can dolly in and out ( PerspectiveCamera only ) - this.minDistance = 0; - this.maxDistance = Infinity; - - // How far you can zoom in and out ( OrthographicCamera only ) - this.minZoom = 0; - this.maxZoom = Infinity; - - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - this.minPolarAngle = 0; // radians - this.maxPolarAngle = Math.PI; // radians - - // How far you can orbit horizontally, upper and lower limits. - // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) - this.minAzimuthAngle = - Infinity; // radians - this.maxAzimuthAngle = Infinity; // radians - - // Set to true to enable damping (inertia) - // If damping is enabled, you must call controls.update() in your animation loop - this.enableDamping = false; - this.dampingFactor = 0.05; - - // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. - // Set to false to disable zooming - this.enableZoom = true; - this.zoomSpeed = 1.0; - - // Set to false to disable rotating - this.enableRotate = true; - this.rotateSpeed = 1.0; - - // Set to false to disable panning - this.enablePan = true; - this.panSpeed = 1.0; - this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up - this.keyPanSpeed = 7.0; // pixels moved per arrow key push - - // Set to true to automatically rotate around the target - // If auto-rotate is enabled, you must call controls.update() in your animation loop - this.autoRotate = false; - this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60 - - // The four arrow keys - this.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' }; - - // Mouse buttons - this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; - - // Touch fingers - this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; - - // for reset - this.target0 = this.target.clone(); - this.position0 = this.object.position.clone(); - this.zoom0 = this.object.zoom; - - // the target DOM element for key events - this._domElementKeyEvents = null; +( function () { + // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). // - // public methods - // - - this.getPolarAngle = function () { - - return spherical.phi; + // Orbit - left mouse / touch: one-finger move + // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish + // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + const _changeEvent = { + type: 'change' }; - - this.getAzimuthalAngle = function () { - - return spherical.theta; - + const _startEvent = { + type: 'start' }; - - this.listenToKeyEvents = function ( domElement ) { - - domElement.addEventListener( 'keydown', onKeyDown ); - this._domElementKeyEvents = domElement; - + const _endEvent = { + type: 'end' }; - this.saveState = function () { + class OrbitControls extends THREE.EventDispatcher { - scope.target0.copy( scope.target ); - scope.position0.copy( scope.object.position ); - scope.zoom0 = scope.object.zoom; + constructor( object, domElement ) { - }; + super(); + if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' ); + if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); + this.object = object; + this.domElement = domElement; // Set to false to disable this control - this.reset = function () { + this.enabled = true; // "target" sets the location of focus, where the object orbits around - scope.target.copy( scope.target0 ); - scope.object.position.copy( scope.position0 ); - scope.object.zoom = scope.zoom0; + this.target = new THREE.Vector3(); // How far you can dolly in and out ( PerspectiveCamera only ) - scope.object.updateProjectionMatrix(); - scope.dispatchEvent( changeEvent ); + this.minDistance = 0; + this.maxDistance = Infinity; // How far you can zoom in and out ( OrthographicCamera only ) - scope.update(); + this.minZoom = 0; + this.maxZoom = Infinity; // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. - state = STATE.NONE; + this.minPolarAngle = 0; // radians - }; + this.maxPolarAngle = Math.PI; // radians + // How far you can orbit horizontally, upper and lower limits. + // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) - // this method is exposed, but perhaps it would be better if we can make it private... - this.update = function () { + this.minAzimuthAngle = - Infinity; // radians - var offset = new THREE.Vector3(); + this.maxAzimuthAngle = Infinity; // radians + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop - // so camera.up is the orbit axis - var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); - var quatInverse = quat.clone().invert(); + this.enableDamping = false; + this.dampingFactor = 0.05; // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming - var lastPosition = new THREE.Vector3(); - var lastQuaternion = new THREE.Quaternion(); + this.enableZoom = true; + this.zoomSpeed = 1.0; // Set to false to disable rotating - var twoPI = 2 * Math.PI; + this.enableRotate = true; + this.rotateSpeed = 1.0; // Set to false to disable panning - return function update() { + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up - var position = scope.object.position; + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop - offset.copy( position ).sub( scope.target ); + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60 + // The four arrow keys - // rotate offset to "y-axis-is-up" space - offset.applyQuaternion( quat ); + this.keys = { + LEFT: 'ArrowLeft', + UP: 'ArrowUp', + RIGHT: 'ArrowRight', + BOTTOM: 'ArrowDown' + }; // Mouse buttons - // angle from z-axis around y-axis - spherical.setFromVector3( offset ); + this.mouseButtons = { + LEFT: THREE.MOUSE.ROTATE, + MIDDLE: THREE.MOUSE.DOLLY, + RIGHT: THREE.MOUSE.PAN + }; // Touch fingers - if ( scope.autoRotate && state === STATE.NONE ) { + this.touches = { + ONE: THREE.TOUCH.ROTATE, + TWO: THREE.TOUCH.DOLLY_PAN + }; // for reset - rotateLeft( getAutoRotationAngle() ); + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; // the target DOM element for key events - } + this._domElementKeyEvents = null; // + // public methods + // - if ( scope.enableDamping ) { + this.getPolarAngle = function () { - spherical.theta += sphericalDelta.theta * scope.dampingFactor; - spherical.phi += sphericalDelta.phi * scope.dampingFactor; + return spherical.phi; - } else { + }; - spherical.theta += sphericalDelta.theta; - spherical.phi += sphericalDelta.phi; + this.getAzimuthalAngle = function () { - } + return spherical.theta; - // restrict theta to be between desired limits + }; - var min = scope.minAzimuthAngle; - var max = scope.maxAzimuthAngle; + this.listenToKeyEvents = function ( domElement ) { - if ( isFinite( min ) && isFinite( max ) ) { + domElement.addEventListener( 'keydown', onKeyDown ); + this._domElementKeyEvents = domElement; - if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI; - - if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; - - if ( min <= max ) { - - spherical.theta = Math.max( min, Math.min( max, spherical.theta ) ); - - } else { - - spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ? - Math.max( min, spherical.theta ) : - Math.min( max, spherical.theta ); - - } - - } + }; - // restrict phi to be between desired limits - spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + this.saveState = function () { - spherical.makeSafe(); + scope.target0.copy( scope.target ); + scope.position0.copy( scope.object.position ); + scope.zoom0 = scope.object.zoom; + }; - spherical.radius *= scale; + this.reset = function () { - // restrict radius to be between desired limits - spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.zoom = scope.zoom0; + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( _changeEvent ); + scope.update(); + state = STATE.NONE; - // move target to panned location + }; // this method is exposed, but perhaps it would be better if we can make it private... - if ( scope.enableDamping === true ) { - scope.target.addScaledVector( panOffset, scope.dampingFactor ); + this.update = function () { - } else { + const offset = new THREE.Vector3(); // so camera.up is the orbit axis - scope.target.add( panOffset ); + const quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); + const quatInverse = quat.clone().invert(); + const lastPosition = new THREE.Vector3(); + const lastQuaternion = new THREE.Quaternion(); + const twoPI = 2 * Math.PI; + return function update() { - } + const position = scope.object.position; + offset.copy( position ).sub( scope.target ); // rotate offset to "y-axis-is-up" space - offset.setFromSpherical( spherical ); + offset.applyQuaternion( quat ); // angle from z-axis around y-axis - // rotate offset back to "camera-up-vector-is-up" space - offset.applyQuaternion( quatInverse ); + spherical.setFromVector3( offset ); - position.copy( scope.target ).add( offset ); + if ( scope.autoRotate && state === STATE.NONE ) { - scope.object.lookAt( scope.target ); + rotateLeft( getAutoRotationAngle() ); - if ( scope.enableDamping === true ) { + } - sphericalDelta.theta *= ( 1 - scope.dampingFactor ); - sphericalDelta.phi *= ( 1 - scope.dampingFactor ); + if ( scope.enableDamping ) { - panOffset.multiplyScalar( 1 - scope.dampingFactor ); + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; - } else { + } else { - sphericalDelta.set( 0, 0, 0 ); + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; - panOffset.set( 0, 0, 0 ); + } // restrict theta to be between desired limits - } - scale = 1; + let min = scope.minAzimuthAngle; + let max = scope.maxAzimuthAngle; - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + if ( isFinite( min ) && isFinite( max ) ) { - if ( zoomChanged || - lastPosition.distanceToSquared( scope.object.position ) > EPS || - 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI; + if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; - scope.dispatchEvent( changeEvent ); + if ( min <= max ) { - lastPosition.copy( scope.object.position ); - lastQuaternion.copy( scope.object.quaternion ); - zoomChanged = false; + spherical.theta = Math.max( min, Math.min( max, spherical.theta ) ); - return true; + } else { - } + spherical.theta = spherical.theta > ( min + max ) / 2 ? Math.max( min, spherical.theta ) : Math.min( max, spherical.theta ); - return false; + } - }; + } // restrict phi to be between desired limits - }(); - this.dispose = function () { + spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + spherical.makeSafe(); + spherical.radius *= scale; // restrict radius to be between desired limits - scope.domElement.removeEventListener( 'contextmenu', onContextMenu ); + spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); // move target to panned location - scope.domElement.removeEventListener( 'pointerdown', onPointerDown ); - scope.domElement.removeEventListener( 'wheel', onMouseWheel ); + if ( scope.enableDamping === true ) { - scope.domElement.removeEventListener( 'touchstart', onTouchStart ); - scope.domElement.removeEventListener( 'touchend', onTouchEnd ); - scope.domElement.removeEventListener( 'touchmove', onTouchMove ); + scope.target.addScaledVector( panOffset, scope.dampingFactor ); - scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + } else { + scope.target.add( panOffset ); - if ( scope._domElementKeyEvents !== null ) { + } - scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown ); + offset.setFromSpherical( spherical ); // rotate offset back to "camera-up-vector-is-up" space - } + offset.applyQuaternion( quatInverse ); + position.copy( scope.target ).add( offset ); + scope.object.lookAt( scope.target ); - //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + if ( scope.enableDamping === true ) { - }; + sphericalDelta.theta *= 1 - scope.dampingFactor; + sphericalDelta.phi *= 1 - scope.dampingFactor; + panOffset.multiplyScalar( 1 - scope.dampingFactor ); - // - // internals - // + } else { - var scope = this; - - var changeEvent = { type: 'change' }; - var startEvent = { type: 'start' }; - var endEvent = { type: 'end' }; - - var STATE = { - NONE: - 1, - ROTATE: 0, - DOLLY: 1, - PAN: 2, - TOUCH_ROTATE: 3, - TOUCH_PAN: 4, - TOUCH_DOLLY_PAN: 5, - TOUCH_DOLLY_ROTATE: 6 - }; + sphericalDelta.set( 0, 0, 0 ); + panOffset.set( 0, 0, 0 ); - var state = STATE.NONE; + } - var EPS = 0.000001; + scale = 1; // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - // current position in spherical coordinates - var spherical = new THREE.Spherical(); - var sphericalDelta = new THREE.Spherical(); + if ( zoomChanged || lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { - var scale = 1; - var panOffset = new THREE.Vector3(); - var zoomChanged = false; + scope.dispatchEvent( _changeEvent ); + lastPosition.copy( scope.object.position ); + lastQuaternion.copy( scope.object.quaternion ); + zoomChanged = false; + return true; - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); + } - var panStart = new THREE.Vector2(); - var panEnd = new THREE.Vector2(); - var panDelta = new THREE.Vector2(); + return false; - var dollyStart = new THREE.Vector2(); - var dollyEnd = new THREE.Vector2(); - var dollyDelta = new THREE.Vector2(); + }; - function getAutoRotationAngle() { + }(); - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + this.dispose = function () { - } + scope.domElement.removeEventListener( 'contextmenu', onContextMenu ); + scope.domElement.removeEventListener( 'pointerdown', onPointerDown ); + scope.domElement.removeEventListener( 'wheel', onMouseWheel ); + scope.domElement.removeEventListener( 'touchstart', onTouchStart ); + scope.domElement.removeEventListener( 'touchend', onTouchEnd ); + scope.domElement.removeEventListener( 'touchmove', onTouchMove ); + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); - function getZoomScale() { + if ( scope._domElementKeyEvents !== null ) { - return Math.pow( 0.95, scope.zoomSpeed ); - - } - - function rotateLeft( angle ) { - - sphericalDelta.theta -= angle; - - } - - function rotateUp( angle ) { - - sphericalDelta.phi -= angle; - - } + scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown ); - var panLeft = function () { + } //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? - var v = new THREE.Vector3(); + }; // + // internals + // - return function panLeft( distance, objectMatrix ) { - v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix - v.multiplyScalar( - distance ); + const scope = this; + const STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + let state = STATE.NONE; + const EPS = 0.000001; // current position in spherical coordinates - panOffset.add( v ); + const spherical = new THREE.Spherical(); + const sphericalDelta = new THREE.Spherical(); + let scale = 1; + const panOffset = new THREE.Vector3(); + let zoomChanged = false; + const rotateStart = new THREE.Vector2(); + const rotateEnd = new THREE.Vector2(); + const rotateDelta = new THREE.Vector2(); + const panStart = new THREE.Vector2(); + const panEnd = new THREE.Vector2(); + const panDelta = new THREE.Vector2(); + const dollyStart = new THREE.Vector2(); + const dollyEnd = new THREE.Vector2(); + const dollyDelta = new THREE.Vector2(); - }; + function getAutoRotationAngle() { - }(); - - var panUp = function () { - - var v = new THREE.Vector3(); - - return function panUp( distance, objectMatrix ) { - - if ( scope.screenSpacePanning === true ) { - - v.setFromMatrixColumn( objectMatrix, 1 ); - - } else { - - v.setFromMatrixColumn( objectMatrix, 0 ); - v.crossVectors( scope.object.up, v ); + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } - v.multiplyScalar( distance ); - - panOffset.add( v ); - - }; - - }(); - - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { - - var offset = new THREE.Vector3(); - - return function pan( deltaX, deltaY ) { - - var element = scope.domElement; - - if ( scope.object.isPerspectiveCamera ) { - - // perspective - var position = scope.object.position; - offset.copy( position ).sub( scope.target ); - var targetDistance = offset.length(); - - // half of the fov is center to top of screen - targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); - - // we use only clientHeight here so aspect ratio does not distort speed - panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); - panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); - - } else if ( scope.object.isOrthographicCamera ) { - - // orthographic - panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); - panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + function getZoomScale() { - } else { - - // camera neither orthographic nor perspective - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); - scope.enablePan = false; + return Math.pow( 0.95, scope.zoomSpeed ); } - }; - - }(); - - function dollyOut( dollyScale ) { - - if ( scope.object.isPerspectiveCamera ) { - - scale /= dollyScale; - - } else if ( scope.object.isOrthographicCamera ) { + function rotateLeft( angle ) { - scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); - scope.object.updateProjectionMatrix(); - zoomChanged = true; + sphericalDelta.theta -= angle; - } else { - - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); - scope.enableZoom = false; - - } - - } - - function dollyIn( dollyScale ) { - - if ( scope.object.isPerspectiveCamera ) { + } - scale *= dollyScale; + function rotateUp( angle ) { - } else if ( scope.object.isOrthographicCamera ) { + sphericalDelta.phi -= angle; - scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); - scope.object.updateProjectionMatrix(); - zoomChanged = true; + } - } else { + const panLeft = function () { - console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); - scope.enableZoom = false; + const v = new THREE.Vector3(); + return function panLeft( distance, objectMatrix ) { - } + v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix - } + v.multiplyScalar( - distance ); + panOffset.add( v ); - // - // event callbacks - update the object state - // + }; - function handleMouseDownRotate( event ) { + }(); - rotateStart.set( event.clientX, event.clientY ); + const panUp = function () { - } + const v = new THREE.Vector3(); + return function panUp( distance, objectMatrix ) { - function handleMouseDownDolly( event ) { + if ( scope.screenSpacePanning === true ) { - dollyStart.set( event.clientX, event.clientY ); + v.setFromMatrixColumn( objectMatrix, 1 ); - } + } else { - function handleMouseDownPan( event ) { + v.setFromMatrixColumn( objectMatrix, 0 ); + v.crossVectors( scope.object.up, v ); - panStart.set( event.clientX, event.clientY ); + } - } + v.multiplyScalar( distance ); + panOffset.add( v ); - function handleMouseMoveRotate( event ) { + }; - rotateEnd.set( event.clientX, event.clientY ); + }(); // deltaX and deltaY are in pixels; right and down are positive - rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); - var element = scope.domElement; + const pan = function () { - rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + const offset = new THREE.Vector3(); + return function pan( deltaX, deltaY ) { - rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + const element = scope.domElement; - rotateStart.copy( rotateEnd ); + if ( scope.object.isPerspectiveCamera ) { - scope.update(); + // perspective + const position = scope.object.position; + offset.copy( position ).sub( scope.target ); + let targetDistance = offset.length(); // half of the fov is center to top of screen - } + targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 ); // we use only clientHeight here so aspect ratio does not distort speed - function handleMouseMoveDolly( event ) { + panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); + panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); - dollyEnd.set( event.clientX, event.clientY ); + } else if ( scope.object.isOrthographicCamera ) { - dollyDelta.subVectors( dollyEnd, dollyStart ); + // orthographic + panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); + panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); - if ( dollyDelta.y > 0 ) { + } else { - dollyOut( getZoomScale() ); + // camera neither orthographic nor perspective + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); + scope.enablePan = false; - } else if ( dollyDelta.y < 0 ) { + } - dollyIn( getZoomScale() ); + }; - } + }(); - dollyStart.copy( dollyEnd ); + function dollyOut( dollyScale ) { - scope.update(); + if ( scope.object.isPerspectiveCamera ) { - } + scale /= dollyScale; - function handleMouseMovePan( event ) { + } else if ( scope.object.isOrthographicCamera ) { - panEnd.set( event.clientX, event.clientY ); + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; - panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + } else { - pan( panDelta.x, panDelta.y ); + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; - panStart.copy( panEnd ); + } - scope.update(); + } - } + function dollyIn( dollyScale ) { - function handleMouseUp( /*event*/ ) { + if ( scope.object.isPerspectiveCamera ) { - // no-op + scale *= dollyScale; - } + } else if ( scope.object.isOrthographicCamera ) { - function handleMouseWheel( event ) { + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; - if ( event.deltaY < 0 ) { + } else { - dollyIn( getZoomScale() ); + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; - } else if ( event.deltaY > 0 ) { + } - dollyOut( getZoomScale() ); + } // + // event callbacks - update the object state + // - } - scope.update(); + function handleMouseDownRotate( event ) { - } + rotateStart.set( event.clientX, event.clientY ); - function handleKeyDown( event ) { + } - var needsUpdate = false; + function handleMouseDownDolly( event ) { - switch ( event.code ) { + dollyStart.set( event.clientX, event.clientY ); - case scope.keys.UP: - pan( 0, scope.keyPanSpeed ); - needsUpdate = true; - break; + } - case scope.keys.BOTTOM: - pan( 0, - scope.keyPanSpeed ); - needsUpdate = true; - break; + function handleMouseDownPan( event ) { - case scope.keys.LEFT: - pan( scope.keyPanSpeed, 0 ); - needsUpdate = true; - break; + panStart.set( event.clientX, event.clientY ); - case scope.keys.RIGHT: - pan( - scope.keyPanSpeed, 0 ); - needsUpdate = true; - break; + } - } + function handleMouseMoveRotate( event ) { - if ( needsUpdate ) { + rotateEnd.set( event.clientX, event.clientY ); + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + const element = scope.domElement; + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height - // prevent the browser from scrolling on cursor keys - event.preventDefault(); + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + rotateStart.copy( rotateEnd ); + scope.update(); - scope.update(); + } - } + function handleMouseMoveDolly( event ) { + dollyEnd.set( event.clientX, event.clientY ); + dollyDelta.subVectors( dollyEnd, dollyStart ); - } + if ( dollyDelta.y > 0 ) { - function handleTouchStartRotate( event ) { + dollyOut( getZoomScale() ); - if ( event.touches.length == 1 ) { + } else if ( dollyDelta.y < 0 ) { - rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + dollyIn( getZoomScale() ); - } else { + } - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + dollyStart.copy( dollyEnd ); + scope.update(); - rotateStart.set( x, y ); + } - } + function handleMouseMovePan( event ) { - } + panEnd.set( event.clientX, event.clientY ); + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + pan( panDelta.x, panDelta.y ); + panStart.copy( panEnd ); + scope.update(); - function handleTouchStartPan( event ) { + } - if ( event.touches.length == 1 ) { + function handleMouseUp( ) { // no-op + } - panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + function handleMouseWheel( event ) { - } else { + if ( event.deltaY < 0 ) { - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + dollyIn( getZoomScale() ); - panStart.set( x, y ); + } else if ( event.deltaY > 0 ) { - } + dollyOut( getZoomScale() ); - } + } - function handleTouchStartDolly( event ) { + scope.update(); - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + } - var distance = Math.sqrt( dx * dx + dy * dy ); + function handleKeyDown( event ) { - dollyStart.set( 0, distance ); + let needsUpdate = false; - } + switch ( event.code ) { - function handleTouchStartDollyPan( event ) { + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + needsUpdate = true; + break; - if ( scope.enableZoom ) handleTouchStartDolly( event ); + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + needsUpdate = true; + break; - if ( scope.enablePan ) handleTouchStartPan( event ); + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; - } + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; - function handleTouchStartDollyRotate( event ) { + } - if ( scope.enableZoom ) handleTouchStartDolly( event ); + if ( needsUpdate ) { - if ( scope.enableRotate ) handleTouchStartRotate( event ); + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + scope.update(); - } + } - function handleTouchMoveRotate( event ) { + } - if ( event.touches.length == 1 ) { + function handleTouchStartRotate( event ) { - rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + if ( event.touches.length == 1 ) { - } else { + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + } else { - rotateEnd.set( x, y ); + const x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + const y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + rotateStart.set( x, y ); - } + } - rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + } - var element = scope.domElement; + function handleTouchStartPan( event ) { - rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + if ( event.touches.length == 1 ) { - rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - rotateStart.copy( rotateEnd ); + } else { - } + const x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + const y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + panStart.set( x, y ); - function handleTouchMovePan( event ) { + } - if ( event.touches.length == 1 ) { + } - panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + function handleTouchStartDolly( event ) { - } else { + const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + const distance = Math.sqrt( dx * dx + dy * dy ); + dollyStart.set( 0, distance ); - var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); - var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + } - panEnd.set( x, y ); + function handleTouchStartDollyPan( event ) { - } + if ( scope.enableZoom ) handleTouchStartDolly( event ); + if ( scope.enablePan ) handleTouchStartPan( event ); - panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + } - pan( panDelta.x, panDelta.y ); + function handleTouchStartDollyRotate( event ) { - panStart.copy( panEnd ); + if ( scope.enableZoom ) handleTouchStartDolly( event ); + if ( scope.enableRotate ) handleTouchStartRotate( event ); - } + } - function handleTouchMoveDolly( event ) { + function handleTouchMoveRotate( event ) { - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + if ( event.touches.length == 1 ) { - var distance = Math.sqrt( dx * dx + dy * dy ); + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - dollyEnd.set( 0, distance ); + } else { - dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + const x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + const y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + rotateEnd.set( x, y ); - dollyOut( dollyDelta.y ); + } - dollyStart.copy( dollyEnd ); + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + const element = scope.domElement; + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height - } + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + rotateStart.copy( rotateEnd ); - function handleTouchMoveDollyPan( event ) { + } - if ( scope.enableZoom ) handleTouchMoveDolly( event ); + function handleTouchMovePan( event ) { - if ( scope.enablePan ) handleTouchMovePan( event ); + if ( event.touches.length == 1 ) { - } + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); - function handleTouchMoveDollyRotate( event ) { + } else { - if ( scope.enableZoom ) handleTouchMoveDolly( event ); + const x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + const y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + panEnd.set( x, y ); - if ( scope.enableRotate ) handleTouchMoveRotate( event ); + } - } + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + pan( panDelta.x, panDelta.y ); + panStart.copy( panEnd ); - function handleTouchEnd( /*event*/ ) { + } - // no-op + function handleTouchMoveDolly( event ) { - } + const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + const distance = Math.sqrt( dx * dx + dy * dy ); + dollyEnd.set( 0, distance ); + dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + dollyOut( dollyDelta.y ); + dollyStart.copy( dollyEnd ); - // - // event handlers - FSM: listen for events and reset state - // - - function onPointerDown( event ) { + } - if ( scope.enabled === false ) return; + function handleTouchMoveDollyPan( event ) { - switch ( event.pointerType ) { + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + if ( scope.enablePan ) handleTouchMovePan( event ); - case 'mouse': - case 'pen': - onMouseDown( event ); - break; + } - // TODO touch + function handleTouchMoveDollyRotate( event ) { - } + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + if ( scope.enableRotate ) handleTouchMoveRotate( event ); - } + } - function onPointerMove( event ) { + function handleTouchEnd( ) { // no-op + } // + // event handlers - FSM: listen for events and reset state + // - if ( scope.enabled === false ) return; - switch ( event.pointerType ) { + function onPointerDown( event ) { - case 'mouse': - case 'pen': - onMouseMove( event ); - break; + if ( scope.enabled === false ) return; - // TODO touch + switch ( event.pointerType ) { - } + case 'mouse': + case 'pen': + onMouseDown( event ); + break; + // TODO touch - } + } - function onPointerUp( event ) { + } - switch ( event.pointerType ) { + function onPointerMove( event ) { - case 'mouse': - case 'pen': - onMouseUp( event ); - break; + if ( scope.enabled === false ) return; - // TODO touch + switch ( event.pointerType ) { - } + case 'mouse': + case 'pen': + onMouseMove( event ); + break; + // TODO touch - } + } - function onMouseDown( event ) { + } - // Prevent the browser from scrolling. - event.preventDefault(); + function onPointerUp( event ) { - // Manually set the focus since calling preventDefault above - // prevents the browser from setting it automatically. + switch ( event.pointerType ) { - scope.domElement.focus ? scope.domElement.focus() : window.focus(); + case 'mouse': + case 'pen': + onMouseUp( event ); + break; + // TODO touch - var mouseAction; + } - switch ( event.button ) { + } - case 0: + function onMouseDown( event ) { - mouseAction = scope.mouseButtons.LEFT; - break; + // Prevent the browser from scrolling. + event.preventDefault(); // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. - case 1: + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + let mouseAction; - mouseAction = scope.mouseButtons.MIDDLE; - break; + switch ( event.button ) { - case 2: + case 0: + mouseAction = scope.mouseButtons.LEFT; + break; - mouseAction = scope.mouseButtons.RIGHT; - break; + case 1: + mouseAction = scope.mouseButtons.MIDDLE; + break; - default: + case 2: + mouseAction = scope.mouseButtons.RIGHT; + break; - mouseAction = - 1; + default: + mouseAction = - 1; - } + } - switch ( mouseAction ) { + switch ( mouseAction ) { - case THREE.MOUSE.DOLLY: + case THREE.MOUSE.DOLLY: + if ( scope.enableZoom === false ) return; + handleMouseDownDolly( event ); + state = STATE.DOLLY; + break; - if ( scope.enableZoom === false ) return; + case THREE.MOUSE.ROTATE: + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { - handleMouseDownDolly( event ); + if ( scope.enablePan === false ) return; + handleMouseDownPan( event ); + state = STATE.PAN; - state = STATE.DOLLY; + } else { - break; + if ( scope.enableRotate === false ) return; + handleMouseDownRotate( event ); + state = STATE.ROTATE; - case THREE.MOUSE.ROTATE: + } - if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + break; - if ( scope.enablePan === false ) return; + case THREE.MOUSE.PAN: + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { - handleMouseDownPan( event ); + if ( scope.enableRotate === false ) return; + handleMouseDownRotate( event ); + state = STATE.ROTATE; - state = STATE.PAN; + } else { - } else { + if ( scope.enablePan === false ) return; + handleMouseDownPan( event ); + state = STATE.PAN; - if ( scope.enableRotate === false ) return; + } - handleMouseDownRotate( event ); + break; - state = STATE.ROTATE; + default: + state = STATE.NONE; } - break; + if ( state !== STATE.NONE ) { - case THREE.MOUSE.PAN: + scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); + scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); + scope.dispatchEvent( _startEvent ); - if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + } - if ( scope.enableRotate === false ) return; + } - handleMouseDownRotate( event ); + function onMouseMove( event ) { - state = STATE.ROTATE; + if ( scope.enabled === false ) return; + event.preventDefault(); - } else { + switch ( state ) { - if ( scope.enablePan === false ) return; + case STATE.ROTATE: + if ( scope.enableRotate === false ) return; + handleMouseMoveRotate( event ); + break; - handleMouseDownPan( event ); + case STATE.DOLLY: + if ( scope.enableZoom === false ) return; + handleMouseMoveDolly( event ); + break; - state = STATE.PAN; + case STATE.PAN: + if ( scope.enablePan === false ) return; + handleMouseMovePan( event ); + break; } - break; + } - default: + function onMouseUp( event ) { + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + if ( scope.enabled === false ) return; + handleMouseUp( event ); + scope.dispatchEvent( _endEvent ); state = STATE.NONE; - } - - if ( state !== STATE.NONE ) { - - scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); - - scope.dispatchEvent( startEvent ); - - } - - } - - function onMouseMove( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - switch ( state ) { - - case STATE.ROTATE: - - if ( scope.enableRotate === false ) return; - - handleMouseMoveRotate( event ); - - break; - - case STATE.DOLLY: - - if ( scope.enableZoom === false ) return; - - handleMouseMoveDolly( event ); - - break; - - case STATE.PAN: + } - if ( scope.enablePan === false ) return; + function onMouseWheel( event ) { - handleMouseMovePan( event ); + if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE ) return; + event.preventDefault(); + scope.dispatchEvent( _startEvent ); + handleMouseWheel( event ); + scope.dispatchEvent( _endEvent ); - break; + } - } + function onKeyDown( event ) { - } + if ( scope.enabled === false || scope.enablePan === false ) return; + handleKeyDown( event ); - function onMouseUp( event ) { + } - scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + function onTouchStart( event ) { - if ( scope.enabled === false ) return; + if ( scope.enabled === false ) return; + event.preventDefault(); // prevent scrolling - handleMouseUp( event ); + switch ( event.touches.length ) { - scope.dispatchEvent( endEvent ); + case 1: + switch ( scope.touches.ONE ) { - state = STATE.NONE; + case THREE.TOUCH.ROTATE: + if ( scope.enableRotate === false ) return; + handleTouchStartRotate( event ); + state = STATE.TOUCH_ROTATE; + break; - } + case THREE.TOUCH.PAN: + if ( scope.enablePan === false ) return; + handleTouchStartPan( event ); + state = STATE.TOUCH_PAN; + break; - function onMouseWheel( event ) { + default: + state = STATE.NONE; - if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; + } - event.preventDefault(); + break; - scope.dispatchEvent( startEvent ); + case 2: + switch ( scope.touches.TWO ) { - handleMouseWheel( event ); + case THREE.TOUCH.DOLLY_PAN: + if ( scope.enableZoom === false && scope.enablePan === false ) return; + handleTouchStartDollyPan( event ); + state = STATE.TOUCH_DOLLY_PAN; + break; - scope.dispatchEvent( endEvent ); + case THREE.TOUCH.DOLLY_ROTATE: + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + handleTouchStartDollyRotate( event ); + state = STATE.TOUCH_DOLLY_ROTATE; + break; - } + default: + state = STATE.NONE; - function onKeyDown( event ) { + } - if ( scope.enabled === false || scope.enablePan === false ) return; + break; - handleKeyDown( event ); + default: + state = STATE.NONE; - } + } - function onTouchStart( event ) { + if ( state !== STATE.NONE ) { - if ( scope.enabled === false ) return; + scope.dispatchEvent( _startEvent ); - event.preventDefault(); // prevent scrolling + } - switch ( event.touches.length ) { + } - case 1: + function onTouchMove( event ) { - switch ( scope.touches.ONE ) { + if ( scope.enabled === false ) return; + event.preventDefault(); // prevent scrolling - case THREE.TOUCH.ROTATE: + switch ( state ) { + case STATE.TOUCH_ROTATE: if ( scope.enableRotate === false ) return; - - handleTouchStartRotate( event ); - - state = STATE.TOUCH_ROTATE; - + handleTouchMoveRotate( event ); + scope.update(); break; - case THREE.TOUCH.PAN: - + case STATE.TOUCH_PAN: if ( scope.enablePan === false ) return; - - handleTouchStartPan( event ); - - state = STATE.TOUCH_PAN; - + handleTouchMovePan( event ); + scope.update(); break; - default: - - state = STATE.NONE; - - } - - break; - - case 2: - - switch ( scope.touches.TWO ) { - - case THREE.TOUCH.DOLLY_PAN: - + case STATE.TOUCH_DOLLY_PAN: if ( scope.enableZoom === false && scope.enablePan === false ) return; - - handleTouchStartDollyPan( event ); - - state = STATE.TOUCH_DOLLY_PAN; - + handleTouchMoveDollyPan( event ); + scope.update(); break; - case THREE.TOUCH.DOLLY_ROTATE: - + case STATE.TOUCH_DOLLY_ROTATE: if ( scope.enableZoom === false && scope.enableRotate === false ) return; - - handleTouchStartDollyRotate( event ); - - state = STATE.TOUCH_DOLLY_ROTATE; - + handleTouchMoveDollyRotate( event ); + scope.update(); break; default: - state = STATE.NONE; } - break; + } - default: + function onTouchEnd( event ) { + if ( scope.enabled === false ) return; + handleTouchEnd( event ); + scope.dispatchEvent( _endEvent ); state = STATE.NONE; - } - - if ( state !== STATE.NONE ) { - - scope.dispatchEvent( startEvent ); - - } - - } - - function onTouchMove( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); // prevent scrolling - - switch ( state ) { - - case STATE.TOUCH_ROTATE: - - if ( scope.enableRotate === false ) return; - - handleTouchMoveRotate( event ); - - scope.update(); - - break; - - case STATE.TOUCH_PAN: - - if ( scope.enablePan === false ) return; - - handleTouchMovePan( event ); - - scope.update(); - - break; - - case STATE.TOUCH_DOLLY_PAN: - - if ( scope.enableZoom === false && scope.enablePan === false ) return; - - handleTouchMoveDollyPan( event ); - - scope.update(); - - break; - - case STATE.TOUCH_DOLLY_ROTATE: + } - if ( scope.enableZoom === false && scope.enableRotate === false ) return; + function onContextMenu( event ) { - handleTouchMoveDollyRotate( event ); + if ( scope.enabled === false ) return; + event.preventDefault(); - scope.update(); + } // - break; - default: + scope.domElement.addEventListener( 'contextmenu', onContextMenu ); + scope.domElement.addEventListener( 'pointerdown', onPointerDown ); + scope.domElement.addEventListener( 'wheel', onMouseWheel, { + passive: false + } ); + scope.domElement.addEventListener( 'touchstart', onTouchStart, { + passive: false + } ); + scope.domElement.addEventListener( 'touchend', onTouchEnd ); + scope.domElement.addEventListener( 'touchmove', onTouchMove, { + passive: false + } ); // force an update at start - state = STATE.NONE; + this.update(); } - } - - function onTouchEnd( event ) { - - if ( scope.enabled === false ) return; - - handleTouchEnd( event ); - - scope.dispatchEvent( endEvent ); - - state = STATE.NONE; - - } - - function onContextMenu( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - } - + } // This set of controls performs orbiting, dollying (zooming), and panning. + // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). + // This is very similar to OrbitControls, another set of touch behavior // + // Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate + // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish + // Pan - left mouse, or arrow keys / touch: one-finger move - scope.domElement.addEventListener( 'contextmenu', onContextMenu ); - - scope.domElement.addEventListener( 'pointerdown', onPointerDown ); - scope.domElement.addEventListener( 'wheel', onMouseWheel ); - - scope.domElement.addEventListener( 'touchstart', onTouchStart ); - scope.domElement.addEventListener( 'touchend', onTouchEnd ); - scope.domElement.addEventListener( 'touchmove', onTouchMove ); - - // force an update at start - - this.update(); -}; + class MapControls extends OrbitControls { -THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; + constructor( object, domElement ) { + super( object, domElement ); + this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up -// This set of controls performs orbiting, dollying (zooming), and panning. -// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). -// This is very similar to OrbitControls, another set of touch behavior -// -// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate -// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish -// Pan - left mouse, or arrow keys / touch: one-finger move + this.mouseButtons.LEFT = THREE.MOUSE.PAN; + this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; + this.touches.ONE = THREE.TOUCH.PAN; + this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; -THREE.MapControls = function ( object, domElement ) { - - THREE.OrbitControls.call( this, object, domElement ); - - this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up - - this.mouseButtons.LEFT = THREE.MOUSE.PAN; - this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; + } - this.touches.ONE = THREE.TOUCH.PAN; - this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; + } -}; + THREE.MapControls = MapControls; + THREE.OrbitControls = OrbitControls; -THREE.MapControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.MapControls.prototype.constructor = THREE.MapControls; +} )(); diff --git a/examples/js/controls/PointerLockControls.js b/examples/js/controls/PointerLockControls.js index 7dda79645112f6..c46fb38653c746 100644 --- a/examples/js/controls/PointerLockControls.js +++ b/examples/js/controls/PointerLockControls.js @@ -1,156 +1,160 @@ -THREE.PointerLockControls = function ( camera, domElement ) { +( function () { - if ( domElement === undefined ) { + const _euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); - console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' ); - domElement = document.body; + const _vector = new THREE.Vector3(); - } + const _changeEvent = { + type: 'change' + }; + const _lockEvent = { + type: 'lock' + }; + const _unlockEvent = { + type: 'unlock' + }; - this.domElement = domElement; - this.isLocked = false; + const _PI_2 = Math.PI / 2; - // Set to constrain the pitch of the camera - // Range is 0 to Math.PI radians - this.minPolarAngle = 0; // radians - this.maxPolarAngle = Math.PI; // radians + class PointerLockControls extends THREE.EventDispatcher { - // - // internals - // + constructor( camera, domElement ) { - var scope = this; + super(); - var changeEvent = { type: 'change' }; - var lockEvent = { type: 'lock' }; - var unlockEvent = { type: 'unlock' }; + if ( domElement === undefined ) { - var euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); + console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' ); + domElement = document.body; - var PI_2 = Math.PI / 2; + } - var vec = new THREE.Vector3(); + this.domElement = domElement; + this.isLocked = false; // Set to constrain the pitch of the camera + // Range is 0 to Math.PI radians - function onMouseMove( event ) { + this.minPolarAngle = 0; // radians - if ( scope.isLocked === false ) return; + this.maxPolarAngle = Math.PI; // radians - var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; - var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + const scope = this; - euler.setFromQuaternion( camera.quaternion ); + function onMouseMove( event ) { - euler.y -= movementX * 0.002; - euler.x -= movementY * 0.002; + if ( scope.isLocked === false ) return; + const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; - euler.x = Math.max( PI_2 - scope.maxPolarAngle, Math.min( PI_2 - scope.minPolarAngle, euler.x ) ); + _euler.setFromQuaternion( camera.quaternion ); - camera.quaternion.setFromEuler( euler ); + _euler.y -= movementX * 0.002; + _euler.x -= movementY * 0.002; + _euler.x = Math.max( _PI_2 - scope.maxPolarAngle, Math.min( _PI_2 - scope.minPolarAngle, _euler.x ) ); + camera.quaternion.setFromEuler( _euler ); + scope.dispatchEvent( _changeEvent ); - scope.dispatchEvent( changeEvent ); + } - } + function onPointerlockChange() { - function onPointerlockChange() { + if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) { - if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) { + scope.dispatchEvent( _lockEvent ); + scope.isLocked = true; - scope.dispatchEvent( lockEvent ); + } else { - scope.isLocked = true; + scope.dispatchEvent( _unlockEvent ); + scope.isLocked = false; - } else { + } - scope.dispatchEvent( unlockEvent ); + } - scope.isLocked = false; + function onPointerlockError() { - } + console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); - } + } - function onPointerlockError() { + this.connect = function () { - console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); + scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange ); + scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError ); - } + }; - this.connect = function () { + this.disconnect = function () { - scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove ); - scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange ); - scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError ); + scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange ); + scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError ); - }; + }; - this.disconnect = function () { + this.dispose = function () { - scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove ); - scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange ); - scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError ); + this.disconnect(); - }; + }; - this.dispose = function () { + this.getObject = function () { - this.disconnect(); + // retaining this method for backward compatibility + return camera; - }; + }; - this.getObject = function () { // retaining this method for backward compatibility + this.getDirection = function () { - return camera; + const direction = new THREE.Vector3( 0, 0, - 1 ); + return function ( v ) { - }; - - this.getDirection = function () { - - var direction = new THREE.Vector3( 0, 0, - 1 ); + return v.copy( direction ).applyQuaternion( camera.quaternion ); - return function ( v ) { + }; - return v.copy( direction ).applyQuaternion( camera.quaternion ); + }(); - }; + this.moveForward = function ( distance ) { - }(); + // move forward parallel to the xz-plane + // assumes camera.up is y-up + _vector.setFromMatrixColumn( camera.matrix, 0 ); - this.moveForward = function ( distance ) { + _vector.crossVectors( camera.up, _vector ); - // move forward parallel to the xz-plane - // assumes camera.up is y-up + camera.position.addScaledVector( _vector, distance ); - vec.setFromMatrixColumn( camera.matrix, 0 ); + }; - vec.crossVectors( camera.up, vec ); + this.moveRight = function ( distance ) { - camera.position.addScaledVector( vec, distance ); - - }; + _vector.setFromMatrixColumn( camera.matrix, 0 ); - this.moveRight = function ( distance ) { + camera.position.addScaledVector( _vector, distance ); - vec.setFromMatrixColumn( camera.matrix, 0 ); + }; - camera.position.addScaledVector( vec, distance ); + this.lock = function () { - }; + this.domElement.requestPointerLock(); - this.lock = function () { + }; - this.domElement.requestPointerLock(); + this.unlock = function () { - }; + scope.domElement.ownerDocument.exitPointerLock(); - this.unlock = function () { + }; - scope.domElement.ownerDocument.exitPointerLock(); + this.connect(); - }; + } - this.connect(); + } -}; + THREE.PointerLockControls = PointerLockControls; -THREE.PointerLockControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.PointerLockControls.prototype.constructor = THREE.PointerLockControls; +} )(); diff --git a/examples/js/controls/TrackballControls.js b/examples/js/controls/TrackballControls.js index afd9d66e3d7933..8aa5f63d075fee 100644 --- a/examples/js/controls/TrackballControls.js +++ b/examples/js/controls/TrackballControls.js @@ -1,739 +1,723 @@ -THREE.TrackballControls = function ( object, domElement ) { +( function () { - if ( domElement === undefined ) console.warn( 'THREE.TrackballControls: The second parameter "domElement" is now mandatory.' ); - if ( domElement === document ) console.error( 'THREE.TrackballControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); - - var scope = this; - var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 }; - - this.object = object; - this.domElement = domElement; - - // API - - this.enabled = true; - - this.screen = { left: 0, top: 0, width: 0, height: 0 }; - - this.rotateSpeed = 1.0; - this.zoomSpeed = 1.2; - this.panSpeed = 0.3; - - this.noRotate = false; - this.noZoom = false; - this.noPan = false; - - this.staticMoving = false; - this.dynamicDampingFactor = 0.2; - - this.minDistance = 0; - this.maxDistance = Infinity; - - this.keys = [ 'KeyA' /*A*/, 'KeyS' /*S*/, 'KeyD' /*D*/ ]; + const _changeEvent = { + type: 'change' + }; + const _startEvent = { + type: 'start' + }; + const _endEvent = { + type: 'end' + }; - this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; + class TrackballControls extends THREE.EventDispatcher { + + constructor( object, domElement ) { + + super(); + if ( domElement === undefined ) console.warn( 'THREE.TrackballControls: The second parameter "domElement" is now mandatory.' ); + if ( domElement === document ) console.error( 'THREE.TrackballControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); + const scope = this; + const STATE = { + NONE: - 1, + ROTATE: 0, + ZOOM: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_ZOOM_PAN: 4 + }; + this.object = object; + this.domElement = domElement; // API + + this.enabled = true; + this.screen = { + left: 0, + top: 0, + width: 0, + height: 0 + }; + this.rotateSpeed = 1.0; + this.zoomSpeed = 1.2; + this.panSpeed = 0.3; + this.noRotate = false; + this.noZoom = false; + this.noPan = false; + this.staticMoving = false; + this.dynamicDampingFactor = 0.2; + this.minDistance = 0; + this.maxDistance = Infinity; + this.keys = [ 'KeyA', + /*A*/ + 'KeyS', + /*S*/ + 'KeyD' + /*D*/ + ]; + this.mouseButtons = { + LEFT: THREE.MOUSE.ROTATE, + MIDDLE: THREE.MOUSE.DOLLY, + RIGHT: THREE.MOUSE.PAN + }; // internals + + this.target = new THREE.Vector3(); + const EPS = 0.000001; + const lastPosition = new THREE.Vector3(); + let lastZoom = 1; + let _state = STATE.NONE, + _keyState = STATE.NONE, + _touchZoomDistanceStart = 0, + _touchZoomDistanceEnd = 0, + _lastAngle = 0; + + const _eye = new THREE.Vector3(), + _movePrev = new THREE.Vector2(), + _moveCurr = new THREE.Vector2(), + _lastAxis = new THREE.Vector3(), + _zoomStart = new THREE.Vector2(), + _zoomEnd = new THREE.Vector2(), + _panStart = new THREE.Vector2(), + _panEnd = new THREE.Vector2(); // for reset - // internals - this.target = new THREE.Vector3(); + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.up0 = this.object.up.clone(); + this.zoom0 = this.object.zoom; // methods - var EPS = 0.000001; + this.handleResize = function () { - var lastPosition = new THREE.Vector3(); - var lastZoom = 1; + const box = scope.domElement.getBoundingClientRect(); // adjustments come from similar code in the jquery offset() function - var _state = STATE.NONE, - _keyState = STATE.NONE, + const d = scope.domElement.ownerDocument.documentElement; + scope.screen.left = box.left + window.pageXOffset - d.clientLeft; + scope.screen.top = box.top + window.pageYOffset - d.clientTop; + scope.screen.width = box.width; + scope.screen.height = box.height; - _eye = new THREE.Vector3(), + }; - _movePrev = new THREE.Vector2(), - _moveCurr = new THREE.Vector2(), + const getMouseOnScreen = function () { - _lastAxis = new THREE.Vector3(), - _lastAngle = 0, + const vector = new THREE.Vector2(); + return function getMouseOnScreen( pageX, pageY ) { - _zoomStart = new THREE.Vector2(), - _zoomEnd = new THREE.Vector2(), + vector.set( ( pageX - scope.screen.left ) / scope.screen.width, ( pageY - scope.screen.top ) / scope.screen.height ); + return vector; - _touchZoomDistanceStart = 0, - _touchZoomDistanceEnd = 0, + }; - _panStart = new THREE.Vector2(), - _panEnd = new THREE.Vector2(); + }(); - // for reset + const getMouseOnCircle = function () { - this.target0 = this.target.clone(); - this.position0 = this.object.position.clone(); - this.up0 = this.object.up.clone(); - this.zoom0 = this.object.zoom; + const vector = new THREE.Vector2(); + return function getMouseOnCircle( pageX, pageY ) { - // events + vector.set( ( pageX - scope.screen.width * 0.5 - scope.screen.left ) / ( scope.screen.width * 0.5 ), ( scope.screen.height + 2 * ( scope.screen.top - pageY ) ) / scope.screen.width // screen.width intentional + ); + return vector; - var changeEvent = { type: 'change' }; - var startEvent = { type: 'start' }; - var endEvent = { type: 'end' }; + }; + }(); - // methods + this.rotateCamera = function () { - this.handleResize = function () { + const axis = new THREE.Vector3(), + quaternion = new THREE.Quaternion(), + eyeDirection = new THREE.Vector3(), + objectUpDirection = new THREE.Vector3(), + objectSidewaysDirection = new THREE.Vector3(), + moveDirection = new THREE.Vector3(); + return function rotateCamera() { - var box = scope.domElement.getBoundingClientRect(); - // adjustments come from similar code in the jquery offset() function - var d = scope.domElement.ownerDocument.documentElement; - scope.screen.left = box.left + window.pageXOffset - d.clientLeft; - scope.screen.top = box.top + window.pageYOffset - d.clientTop; - scope.screen.width = box.width; - scope.screen.height = box.height; + moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 ); + let angle = moveDirection.length(); - }; + if ( angle ) { - var getMouseOnScreen = ( function () { + _eye.copy( scope.object.position ).sub( scope.target ); - var vector = new THREE.Vector2(); + eyeDirection.copy( _eye ).normalize(); + objectUpDirection.copy( scope.object.up ).normalize(); + objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize(); + objectUpDirection.setLength( _moveCurr.y - _movePrev.y ); + objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x ); + moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) ); + axis.crossVectors( moveDirection, _eye ).normalize(); + angle *= scope.rotateSpeed; + quaternion.setFromAxisAngle( axis, angle ); - return function getMouseOnScreen( pageX, pageY ) { + _eye.applyQuaternion( quaternion ); - vector.set( - ( pageX - scope.screen.left ) / scope.screen.width, - ( pageY - scope.screen.top ) / scope.screen.height - ); + scope.object.up.applyQuaternion( quaternion ); - return vector; + _lastAxis.copy( axis ); - }; + _lastAngle = angle; - }() ); + } else if ( ! scope.staticMoving && _lastAngle ) { - var getMouseOnCircle = ( function () { + _lastAngle *= Math.sqrt( 1.0 - scope.dynamicDampingFactor ); - var vector = new THREE.Vector2(); + _eye.copy( scope.object.position ).sub( scope.target ); - return function getMouseOnCircle( pageX, pageY ) { + quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); - vector.set( - ( ( pageX - scope.screen.width * 0.5 - scope.screen.left ) / ( scope.screen.width * 0.5 ) ), - ( ( scope.screen.height + 2 * ( scope.screen.top - pageY ) ) / scope.screen.width ) // screen.width intentional - ); + _eye.applyQuaternion( quaternion ); - return vector; + scope.object.up.applyQuaternion( quaternion ); - }; + } - }() ); + _movePrev.copy( _moveCurr ); - this.rotateCamera = ( function () { + }; - var axis = new THREE.Vector3(), - quaternion = new THREE.Quaternion(), - eyeDirection = new THREE.Vector3(), - objectUpDirection = new THREE.Vector3(), - objectSidewaysDirection = new THREE.Vector3(), - moveDirection = new THREE.Vector3(), - angle; + }(); - return function rotateCamera() { + this.zoomCamera = function () { - moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 ); - angle = moveDirection.length(); + let factor; - if ( angle ) { + if ( _state === STATE.TOUCH_ZOOM_PAN ) { - _eye.copy( scope.object.position ).sub( scope.target ); + factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; + _touchZoomDistanceStart = _touchZoomDistanceEnd; - eyeDirection.copy( _eye ).normalize(); - objectUpDirection.copy( scope.object.up ).normalize(); - objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize(); + if ( scope.object.isPerspectiveCamera ) { - objectUpDirection.setLength( _moveCurr.y - _movePrev.y ); - objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x ); + _eye.multiplyScalar( factor ); - moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) ); + } else if ( scope.object.isOrthographicCamera ) { - axis.crossVectors( moveDirection, _eye ).normalize(); + scope.object.zoom *= factor; + scope.object.updateProjectionMatrix(); - angle *= scope.rotateSpeed; - quaternion.setFromAxisAngle( axis, angle ); + } else { - _eye.applyQuaternion( quaternion ); - scope.object.up.applyQuaternion( quaternion ); + console.warn( 'THREE.TrackballControls: Unsupported camera type' ); - _lastAxis.copy( axis ); - _lastAngle = angle; + } - } else if ( ! scope.staticMoving && _lastAngle ) { + } else { - _lastAngle *= Math.sqrt( 1.0 - scope.dynamicDampingFactor ); - _eye.copy( scope.object.position ).sub( scope.target ); - quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); - _eye.applyQuaternion( quaternion ); - scope.object.up.applyQuaternion( quaternion ); + factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * scope.zoomSpeed; - } + if ( factor !== 1.0 && factor > 0.0 ) { - _movePrev.copy( _moveCurr ); + if ( scope.object.isPerspectiveCamera ) { - }; + _eye.multiplyScalar( factor ); - }() ); + } else if ( scope.object.isOrthographicCamera ) { + scope.object.zoom /= factor; + scope.object.updateProjectionMatrix(); - this.zoomCamera = function () { + } else { - var factor; + console.warn( 'THREE.TrackballControls: Unsupported camera type' ); - if ( _state === STATE.TOUCH_ZOOM_PAN ) { + } - factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; - _touchZoomDistanceStart = _touchZoomDistanceEnd; + } - if ( scope.object.isPerspectiveCamera ) { + if ( scope.staticMoving ) { - _eye.multiplyScalar( factor ); + _zoomStart.copy( _zoomEnd ); - } else if ( scope.object.isOrthographicCamera ) { + } else { - scope.object.zoom *= factor; - scope.object.updateProjectionMatrix(); + _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; - } else { + } - console.warn( 'THREE.TrackballControls: Unsupported camera type' ); + } - } + }; - } else { + this.panCamera = function () { - factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * scope.zoomSpeed; + const mouseChange = new THREE.Vector2(), + objectUp = new THREE.Vector3(), + pan = new THREE.Vector3(); + return function panCamera() { - if ( factor !== 1.0 && factor > 0.0 ) { + mouseChange.copy( _panEnd ).sub( _panStart ); - if ( scope.object.isPerspectiveCamera ) { + if ( mouseChange.lengthSq() ) { - _eye.multiplyScalar( factor ); + if ( scope.object.isOrthographicCamera ) { - } else if ( scope.object.isOrthographicCamera ) { + const scale_x = ( scope.object.right - scope.object.left ) / scope.object.zoom / scope.domElement.clientWidth; + const scale_y = ( scope.object.top - scope.object.bottom ) / scope.object.zoom / scope.domElement.clientWidth; + mouseChange.x *= scale_x; + mouseChange.y *= scale_y; - scope.object.zoom /= factor; - scope.object.updateProjectionMatrix(); + } - } else { + mouseChange.multiplyScalar( _eye.length() * scope.panSpeed ); + pan.copy( _eye ).cross( scope.object.up ).setLength( mouseChange.x ); + pan.add( objectUp.copy( scope.object.up ).setLength( mouseChange.y ) ); + scope.object.position.add( pan ); + scope.target.add( pan ); - console.warn( 'THREE.TrackballControls: Unsupported camera type' ); + if ( scope.staticMoving ) { - } + _panStart.copy( _panEnd ); - } + } else { - if ( scope.staticMoving ) { + _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( scope.dynamicDampingFactor ) ); - _zoomStart.copy( _zoomEnd ); + } - } else { + } - _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; + }; - } + }(); - } + this.checkDistances = function () { - }; + if ( ! scope.noZoom || ! scope.noPan ) { - this.panCamera = ( function () { + if ( _eye.lengthSq() > scope.maxDistance * scope.maxDistance ) { - var mouseChange = new THREE.Vector2(), - objectUp = new THREE.Vector3(), - pan = new THREE.Vector3(); + scope.object.position.addVectors( scope.target, _eye.setLength( scope.maxDistance ) ); - return function panCamera() { + _zoomStart.copy( _zoomEnd ); - mouseChange.copy( _panEnd ).sub( _panStart ); + } - if ( mouseChange.lengthSq() ) { + if ( _eye.lengthSq() < scope.minDistance * scope.minDistance ) { - if ( scope.object.isOrthographicCamera ) { + scope.object.position.addVectors( scope.target, _eye.setLength( scope.minDistance ) ); - var scale_x = ( scope.object.right - scope.object.left ) / scope.object.zoom / scope.domElement.clientWidth; - var scale_y = ( scope.object.top - scope.object.bottom ) / scope.object.zoom / scope.domElement.clientWidth; + _zoomStart.copy( _zoomEnd ); - mouseChange.x *= scale_x; - mouseChange.y *= scale_y; + } } - mouseChange.multiplyScalar( _eye.length() * scope.panSpeed ); - - pan.copy( _eye ).cross( scope.object.up ).setLength( mouseChange.x ); - pan.add( objectUp.copy( scope.object.up ).setLength( mouseChange.y ) ); + }; - scope.object.position.add( pan ); - scope.target.add( pan ); + this.update = function () { - if ( scope.staticMoving ) { + _eye.subVectors( scope.object.position, scope.target ); - _panStart.copy( _panEnd ); + if ( ! scope.noRotate ) { - } else { - - _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( scope.dynamicDampingFactor ) ); + scope.rotateCamera(); } - } - - }; - - }() ); - - this.checkDistances = function () { - - if ( ! scope.noZoom || ! scope.noPan ) { + if ( ! scope.noZoom ) { - if ( _eye.lengthSq() > scope.maxDistance * scope.maxDistance ) { + scope.zoomCamera(); - scope.object.position.addVectors( scope.target, _eye.setLength( scope.maxDistance ) ); - _zoomStart.copy( _zoomEnd ); - - } - - if ( _eye.lengthSq() < scope.minDistance * scope.minDistance ) { - - scope.object.position.addVectors( scope.target, _eye.setLength( scope.minDistance ) ); - _zoomStart.copy( _zoomEnd ); - - } - - } - - }; - - this.update = function () { - - _eye.subVectors( scope.object.position, scope.target ); + } - if ( ! scope.noRotate ) { + if ( ! scope.noPan ) { - scope.rotateCamera(); + scope.panCamera(); - } + } - if ( ! scope.noZoom ) { + scope.object.position.addVectors( scope.target, _eye ); - scope.zoomCamera(); + if ( scope.object.isPerspectiveCamera ) { - } + scope.checkDistances(); + scope.object.lookAt( scope.target ); - if ( ! scope.noPan ) { + if ( lastPosition.distanceToSquared( scope.object.position ) > EPS ) { - scope.panCamera(); + scope.dispatchEvent( _changeEvent ); + lastPosition.copy( scope.object.position ); - } + } - scope.object.position.addVectors( scope.target, _eye ); + } else if ( scope.object.isOrthographicCamera ) { - if ( scope.object.isPerspectiveCamera ) { + scope.object.lookAt( scope.target ); - scope.checkDistances(); + if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || lastZoom !== scope.object.zoom ) { - scope.object.lookAt( scope.target ); + scope.dispatchEvent( _changeEvent ); + lastPosition.copy( scope.object.position ); + lastZoom = scope.object.zoom; - if ( lastPosition.distanceToSquared( scope.object.position ) > EPS ) { + } - scope.dispatchEvent( changeEvent ); + } else { - lastPosition.copy( scope.object.position ); + console.warn( 'THREE.TrackballControls: Unsupported camera type' ); - } + } - } else if ( scope.object.isOrthographicCamera ) { + }; - scope.object.lookAt( scope.target ); + this.reset = function () { - if ( lastPosition.distanceToSquared( scope.object.position ) > EPS || lastZoom !== scope.object.zoom ) { + _state = STATE.NONE; + _keyState = STATE.NONE; + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.up.copy( scope.up0 ); + scope.object.zoom = scope.zoom0; + scope.object.updateProjectionMatrix(); - scope.dispatchEvent( changeEvent ); + _eye.subVectors( scope.object.position, scope.target ); + scope.object.lookAt( scope.target ); + scope.dispatchEvent( _changeEvent ); lastPosition.copy( scope.object.position ); lastZoom = scope.object.zoom; - } + }; // listeners - } else { - console.warn( 'THREE.TrackballControls: Unsupported camera type' ); + function onPointerDown( event ) { - } - - }; - - this.reset = function () { + if ( scope.enabled === false ) return; - _state = STATE.NONE; - _keyState = STATE.NONE; + switch ( event.pointerType ) { - scope.target.copy( scope.target0 ); - scope.object.position.copy( scope.position0 ); - scope.object.up.copy( scope.up0 ); - scope.object.zoom = scope.zoom0; + case 'mouse': + case 'pen': + onMouseDown( event ); + break; + // TODO touch - scope.object.updateProjectionMatrix(); - - _eye.subVectors( scope.object.position, scope.target ); - - scope.object.lookAt( scope.target ); - - scope.dispatchEvent( changeEvent ); + } - lastPosition.copy( scope.object.position ); - lastZoom = scope.object.zoom; + } - }; + function onPointerMove( event ) { - // listeners + if ( scope.enabled === false ) return; - function onPointerDown( event ) { + switch ( event.pointerType ) { - if ( scope.enabled === false ) return; + case 'mouse': + case 'pen': + onMouseMove( event ); + break; + // TODO touch - switch ( event.pointerType ) { + } - case 'mouse': - case 'pen': - onMouseDown( event ); - break; + } - // TODO touch + function onPointerUp( event ) { - } + if ( scope.enabled === false ) return; - } + switch ( event.pointerType ) { - function onPointerMove( event ) { + case 'mouse': + case 'pen': + onMouseUp( event ); + break; + // TODO touch - if ( scope.enabled === false ) return; + } - switch ( event.pointerType ) { + } - case 'mouse': - case 'pen': - onMouseMove( event ); - break; + function keydown( event ) { - // TODO touch + if ( scope.enabled === false ) return; + window.removeEventListener( 'keydown', keydown ); - } + if ( _keyState !== STATE.NONE ) { - } + return; - function onPointerUp( event ) { + } else if ( event.code === scope.keys[ STATE.ROTATE ] && ! scope.noRotate ) { - if ( scope.enabled === false ) return; + _keyState = STATE.ROTATE; - switch ( event.pointerType ) { + } else if ( event.code === scope.keys[ STATE.ZOOM ] && ! scope.noZoom ) { - case 'mouse': - case 'pen': - onMouseUp( event ); - break; + _keyState = STATE.ZOOM; - // TODO touch + } else if ( event.code === scope.keys[ STATE.PAN ] && ! scope.noPan ) { - } + _keyState = STATE.PAN; - } + } - function keydown( event ) { + } - if ( scope.enabled === false ) return; + function keyup() { - window.removeEventListener( 'keydown', keydown ); + if ( scope.enabled === false ) return; + _keyState = STATE.NONE; + window.addEventListener( 'keydown', keydown ); - if ( _keyState !== STATE.NONE ) { + } - return; + function onMouseDown( event ) { - } else if ( event.code === scope.keys[ STATE.ROTATE ] && ! scope.noRotate ) { + event.preventDefault(); - _keyState = STATE.ROTATE; + if ( _state === STATE.NONE ) { - } else if ( event.code === scope.keys[ STATE.ZOOM ] && ! scope.noZoom ) { + switch ( event.button ) { - _keyState = STATE.ZOOM; + case scope.mouseButtons.LEFT: + _state = STATE.ROTATE; + break; - } else if ( event.code === scope.keys[ STATE.PAN ] && ! scope.noPan ) { + case scope.mouseButtons.MIDDLE: + _state = STATE.ZOOM; + break; - _keyState = STATE.PAN; + case scope.mouseButtons.RIGHT: + _state = STATE.PAN; + break; - } + default: + _state = STATE.NONE; - } + } - function keyup() { + } - if ( scope.enabled === false ) return; + const state = _keyState !== STATE.NONE ? _keyState : _state; - _keyState = STATE.NONE; + if ( state === STATE.ROTATE && ! scope.noRotate ) { - window.addEventListener( 'keydown', keydown ); + _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); - } + _movePrev.copy( _moveCurr ); - function onMouseDown( event ) { + } else if ( state === STATE.ZOOM && ! scope.noZoom ) { - event.preventDefault(); + _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); - if ( _state === STATE.NONE ) { + _zoomEnd.copy( _zoomStart ); - switch ( event.button ) { + } else if ( state === STATE.PAN && ! scope.noPan ) { - case scope.mouseButtons.LEFT: - _state = STATE.ROTATE; - break; + _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); - case scope.mouseButtons.MIDDLE: - _state = STATE.ZOOM; - break; + _panEnd.copy( _panStart ); - case scope.mouseButtons.RIGHT: - _state = STATE.PAN; - break; + } - default: - _state = STATE.NONE; + scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); + scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); + scope.dispatchEvent( _startEvent ); } - } + function onMouseMove( event ) { - var state = ( _keyState !== STATE.NONE ) ? _keyState : _state; + if ( scope.enabled === false ) return; + event.preventDefault(); + const state = _keyState !== STATE.NONE ? _keyState : _state; - if ( state === STATE.ROTATE && ! scope.noRotate ) { + if ( state === STATE.ROTATE && ! scope.noRotate ) { - _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); - _movePrev.copy( _moveCurr ); + _movePrev.copy( _moveCurr ); - } else if ( state === STATE.ZOOM && ! scope.noZoom ) { + _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); - _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); - _zoomEnd.copy( _zoomStart ); + } else if ( state === STATE.ZOOM && ! scope.noZoom ) { - } else if ( state === STATE.PAN && ! scope.noPan ) { + _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); - _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); - _panEnd.copy( _panStart ); - - } + } else if ( state === STATE.PAN && ! scope.noPan ) { - scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); + _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); - scope.dispatchEvent( startEvent ); - - } - - function onMouseMove( event ) { + } - if ( scope.enabled === false ) return; + } - event.preventDefault(); + function onMouseUp( event ) { - var state = ( _keyState !== STATE.NONE ) ? _keyState : _state; + if ( scope.enabled === false ) return; + event.preventDefault(); + _state = STATE.NONE; + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + scope.dispatchEvent( _endEvent ); - if ( state === STATE.ROTATE && ! scope.noRotate ) { + } - _movePrev.copy( _moveCurr ); - _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); + function mousewheel( event ) { - } else if ( state === STATE.ZOOM && ! scope.noZoom ) { + if ( scope.enabled === false ) return; + if ( scope.noZoom === true ) return; + event.preventDefault(); - _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); + switch ( event.deltaMode ) { - } else if ( state === STATE.PAN && ! scope.noPan ) { + case 2: + // Zoom in pages + _zoomStart.y -= event.deltaY * 0.025; + break; - _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); + case 1: + // Zoom in lines + _zoomStart.y -= event.deltaY * 0.01; + break; - } + default: + // undefined, 0, assume pixels + _zoomStart.y -= event.deltaY * 0.00025; + break; - } + } - function onMouseUp( event ) { + scope.dispatchEvent( _startEvent ); + scope.dispatchEvent( _endEvent ); - if ( scope.enabled === false ) return; + } - event.preventDefault(); + function touchstart( event ) { - _state = STATE.NONE; + if ( scope.enabled === false ) return; + event.preventDefault(); - scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + switch ( event.touches.length ) { - scope.dispatchEvent( endEvent ); + case 1: + _state = STATE.TOUCH_ROTATE; - } + _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - function mousewheel( event ) { + _movePrev.copy( _moveCurr ); - if ( scope.enabled === false ) return; + break; - if ( scope.noZoom === true ) return; + default: + // 2 or more + _state = STATE.TOUCH_ZOOM_PAN; + const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); + const x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; + const y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; - event.preventDefault(); + _panStart.copy( getMouseOnScreen( x, y ) ); - switch ( event.deltaMode ) { + _panEnd.copy( _panStart ); - case 2: - // Zoom in pages - _zoomStart.y -= event.deltaY * 0.025; - break; + break; - case 1: - // Zoom in lines - _zoomStart.y -= event.deltaY * 0.01; - break; + } - default: - // undefined, 0, assume pixels - _zoomStart.y -= event.deltaY * 0.00025; - break; + scope.dispatchEvent( _startEvent ); - } + } - scope.dispatchEvent( startEvent ); - scope.dispatchEvent( endEvent ); + function touchmove( event ) { - } + if ( scope.enabled === false ) return; + event.preventDefault(); - function touchstart( event ) { + switch ( event.touches.length ) { - if ( scope.enabled === false ) return; + case 1: + _movePrev.copy( _moveCurr ); - event.preventDefault(); + _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - switch ( event.touches.length ) { + break; - case 1: - _state = STATE.TOUCH_ROTATE; - _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - _movePrev.copy( _moveCurr ); - break; + default: + // 2 or more + const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ); + const x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; + const y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; - default: // 2 or more - _state = STATE.TOUCH_ZOOM_PAN; - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; - _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); + _panEnd.copy( getMouseOnScreen( x, y ) ); - var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; - var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; - _panStart.copy( getMouseOnScreen( x, y ) ); - _panEnd.copy( _panStart ); - break; + break; - } + } - scope.dispatchEvent( startEvent ); + } - } + function touchend( event ) { - function touchmove( event ) { + if ( scope.enabled === false ) return; - if ( scope.enabled === false ) return; + switch ( event.touches.length ) { - event.preventDefault(); + case 0: + _state = STATE.NONE; + break; - switch ( event.touches.length ) { + case 1: + _state = STATE.TOUCH_ROTATE; - case 1: - _movePrev.copy( _moveCurr ); - _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - break; + _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - default: // 2 or more - var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; - var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; - _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ); + _movePrev.copy( _moveCurr ); - var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; - var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; - _panEnd.copy( getMouseOnScreen( x, y ) ); - break; + break; - } + } - } + scope.dispatchEvent( _endEvent ); - function touchend( event ) { + } - if ( scope.enabled === false ) return; + function contextmenu( event ) { - switch ( event.touches.length ) { + if ( scope.enabled === false ) return; + event.preventDefault(); - case 0: - _state = STATE.NONE; - break; + } - case 1: - _state = STATE.TOUCH_ROTATE; - _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - _movePrev.copy( _moveCurr ); - break; + this.dispose = function () { + + scope.domElement.removeEventListener( 'contextmenu', contextmenu ); + scope.domElement.removeEventListener( 'pointerdown', onPointerDown ); + scope.domElement.removeEventListener( 'wheel', mousewheel ); + scope.domElement.removeEventListener( 'touchstart', touchstart ); + scope.domElement.removeEventListener( 'touchend', touchend ); + scope.domElement.removeEventListener( 'touchmove', touchmove ); + scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); + scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + window.removeEventListener( 'keydown', keydown ); + window.removeEventListener( 'keyup', keyup ); + + }; + + this.domElement.addEventListener( 'contextmenu', contextmenu ); + this.domElement.addEventListener( 'pointerdown', onPointerDown ); + this.domElement.addEventListener( 'wheel', mousewheel, { + passive: false + } ); + this.domElement.addEventListener( 'touchstart', touchstart, { + passive: false + } ); + this.domElement.addEventListener( 'touchend', touchend ); + this.domElement.addEventListener( 'touchmove', touchmove, { + passive: false + } ); + this.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); + this.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); + window.addEventListener( 'keydown', keydown ); + window.addEventListener( 'keyup', keyup ); + this.handleResize(); // force an update at start + + this.update(); } - scope.dispatchEvent( endEvent ); - } - function contextmenu( event ) { - - if ( scope.enabled === false ) return; - - event.preventDefault(); - - } - - this.dispose = function () { - - scope.domElement.removeEventListener( 'contextmenu', contextmenu ); - - scope.domElement.removeEventListener( 'pointerdown', onPointerDown ); - scope.domElement.removeEventListener( 'wheel', mousewheel ); - - scope.domElement.removeEventListener( 'touchstart', touchstart ); - scope.domElement.removeEventListener( 'touchend', touchend ); - scope.domElement.removeEventListener( 'touchmove', touchmove ); - - scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); - - window.removeEventListener( 'keydown', keydown ); - window.removeEventListener( 'keyup', keyup ); - - }; - - this.domElement.addEventListener( 'contextmenu', contextmenu ); - - this.domElement.addEventListener( 'pointerdown', onPointerDown ); - this.domElement.addEventListener( 'wheel', mousewheel ); - - this.domElement.addEventListener( 'touchstart', touchstart ); - this.domElement.addEventListener( 'touchend', touchend ); - this.domElement.addEventListener( 'touchmove', touchmove ); - - this.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); - this.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); - - window.addEventListener( 'keydown', keydown ); - window.addEventListener( 'keyup', keyup ); - - this.handleResize(); - - // force an update at start - this.update(); - -}; + THREE.TrackballControls = TrackballControls; -THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); -THREE.TrackballControls.prototype.constructor = THREE.TrackballControls; +} )(); diff --git a/examples/js/controls/TransformControls.js b/examples/js/controls/TransformControls.js index de4ddeb2d69ced..8422db8a2bd9f8 100644 --- a/examples/js/controls/TransformControls.js +++ b/examples/js/controls/TransformControls.js @@ -1,587 +1,613 @@ -THREE.TransformControls = function ( camera, domElement ) { +( function () { - if ( domElement === undefined ) { + const _raycaster = new THREE.Raycaster(); - console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' ); - domElement = document; + const _tempVector = new THREE.Vector3(); - } + const _tempVector2 = new THREE.Vector3(); - THREE.Object3D.call( this ); + const _tempQuaternion = new THREE.Quaternion(); - this.visible = false; - this.domElement = domElement; + const _unit = { + X: new THREE.Vector3( 1, 0, 0 ), + Y: new THREE.Vector3( 0, 1, 0 ), + Z: new THREE.Vector3( 0, 0, 1 ) + }; + const _changeEvent = { + type: 'change' + }; + const _mouseDownEvent = { + type: 'mouseDown' + }; + const _mouseUpEvent = { + type: 'mouseUp', + mode: null + }; + const _objectChangeEvent = { + type: 'objectChange' + }; - var _gizmo = new THREE.TransformControlsGizmo(); - this.add( _gizmo ); + class TransformControls extends THREE.Object3D { - var _plane = new THREE.TransformControlsPlane(); - this.add( _plane ); + constructor( camera, domElement ) { - var scope = this; + super(); - // Define properties with getters/setter - // Setting the defined property will automatically trigger change event - // Defined properties are passed down to gizmo and plane + if ( domElement === undefined ) { - defineProperty( 'camera', camera ); - defineProperty( 'object', undefined ); - defineProperty( 'enabled', true ); - defineProperty( 'axis', null ); - defineProperty( 'mode', 'translate' ); - defineProperty( 'translationSnap', null ); - defineProperty( 'rotationSnap', null ); - defineProperty( 'scaleSnap', null ); - defineProperty( 'space', 'world' ); - defineProperty( 'size', 1 ); - defineProperty( 'dragging', false ); - defineProperty( 'showX', true ); - defineProperty( 'showY', true ); - defineProperty( 'showZ', true ); + console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' ); + domElement = document; - var changeEvent = { type: 'change' }; - var mouseDownEvent = { type: 'mouseDown' }; - var mouseUpEvent = { type: 'mouseUp', mode: scope.mode }; - var objectChangeEvent = { type: 'objectChange' }; + } - // Reusable utility variables + this.visible = false; + this.domElement = domElement; - var raycaster = new THREE.Raycaster(); + const _gizmo = new TransformControlsGizmo(); - function intersectObjectWithRay( object, raycaster, includeInvisible ) { + this._gizmo = _gizmo; + this.add( _gizmo ); - var allIntersections = raycaster.intersectObject( object, true ); + const _plane = new TransformControlsPlane(); - for ( var i = 0; i < allIntersections.length; i ++ ) { + this._plane = _plane; + this.add( _plane ); + const scope = this; // Defined getter, setter and store for a property - if ( allIntersections[ i ].object.visible || includeInvisible ) { + function defineProperty( propName, defaultValue ) { - return allIntersections[ i ]; + let propValue = defaultValue; + Object.defineProperty( scope, propName, { + get: function () { - } + return propValue !== undefined ? propValue : defaultValue; - } + }, + set: function ( value ) { - return false; + if ( propValue !== value ) { - } + propValue = value; + _plane[ propName ] = value; + _gizmo[ propName ] = value; + scope.dispatchEvent( { + type: propName + '-changed', + value: value + } ); + scope.dispatchEvent( _changeEvent ); - var _tempVector = new THREE.Vector3(); - var _tempVector2 = new THREE.Vector3(); - var _tempQuaternion = new THREE.Quaternion(); - var _unit = { - X: new THREE.Vector3( 1, 0, 0 ), - Y: new THREE.Vector3( 0, 1, 0 ), - Z: new THREE.Vector3( 0, 0, 1 ) - }; + } - var pointStart = new THREE.Vector3(); - var pointEnd = new THREE.Vector3(); - var offset = new THREE.Vector3(); - var rotationAxis = new THREE.Vector3(); - var startNorm = new THREE.Vector3(); - var endNorm = new THREE.Vector3(); - var rotationAngle = 0; - - var cameraPosition = new THREE.Vector3(); - var cameraQuaternion = new THREE.Quaternion(); - var cameraScale = new THREE.Vector3(); - - var parentPosition = new THREE.Vector3(); - var parentQuaternion = new THREE.Quaternion(); - var parentQuaternionInv = new THREE.Quaternion(); - var parentScale = new THREE.Vector3(); - - var worldPositionStart = new THREE.Vector3(); - var worldQuaternionStart = new THREE.Quaternion(); - var worldScaleStart = new THREE.Vector3(); - - var worldPosition = new THREE.Vector3(); - var worldQuaternion = new THREE.Quaternion(); - var worldQuaternionInv = new THREE.Quaternion(); - var worldScale = new THREE.Vector3(); - - var eye = new THREE.Vector3(); - - var positionStart = new THREE.Vector3(); - var quaternionStart = new THREE.Quaternion(); - var scaleStart = new THREE.Vector3(); - - // TODO: remove properties unused in plane and gizmo - - defineProperty( 'worldPosition', worldPosition ); - defineProperty( 'worldPositionStart', worldPositionStart ); - defineProperty( 'worldQuaternion', worldQuaternion ); - defineProperty( 'worldQuaternionStart', worldQuaternionStart ); - defineProperty( 'cameraPosition', cameraPosition ); - defineProperty( 'cameraQuaternion', cameraQuaternion ); - defineProperty( 'pointStart', pointStart ); - defineProperty( 'pointEnd', pointEnd ); - defineProperty( 'rotationAxis', rotationAxis ); - defineProperty( 'rotationAngle', rotationAngle ); - defineProperty( 'eye', eye ); - - { - - domElement.addEventListener( 'pointerdown', onPointerDown ); - domElement.addEventListener( 'pointermove', onPointerHover ); - scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp ); + } + } ); + scope[ propName ] = defaultValue; + _plane[ propName ] = defaultValue; + _gizmo[ propName ] = defaultValue; + + } // Define properties with getters/setter + // Setting the defined property will automatically trigger change event + // Defined properties are passed down to gizmo and plane + + + defineProperty( 'camera', camera ); + defineProperty( 'object', undefined ); + defineProperty( 'enabled', true ); + defineProperty( 'axis', null ); + defineProperty( 'mode', 'translate' ); + defineProperty( 'translationSnap', null ); + defineProperty( 'rotationSnap', null ); + defineProperty( 'scaleSnap', null ); + defineProperty( 'space', 'world' ); + defineProperty( 'size', 1 ); + defineProperty( 'dragging', false ); + defineProperty( 'showX', true ); + defineProperty( 'showY', true ); + defineProperty( 'showZ', true ); // Reusable utility variables + + const worldPosition = new THREE.Vector3(); + const worldPositionStart = new THREE.Vector3(); + const worldQuaternion = new THREE.Quaternion(); + const worldQuaternionStart = new THREE.Quaternion(); + const cameraPosition = new THREE.Vector3(); + const cameraQuaternion = new THREE.Quaternion(); + const pointStart = new THREE.Vector3(); + const pointEnd = new THREE.Vector3(); + const rotationAxis = new THREE.Vector3(); + const rotationAngle = 0; + const eye = new THREE.Vector3(); // TODO: remove properties unused in plane and gizmo + + defineProperty( 'worldPosition', worldPosition ); + defineProperty( 'worldPositionStart', worldPositionStart ); + defineProperty( 'worldQuaternion', worldQuaternion ); + defineProperty( 'worldQuaternionStart', worldQuaternionStart ); + defineProperty( 'cameraPosition', cameraPosition ); + defineProperty( 'cameraQuaternion', cameraQuaternion ); + defineProperty( 'pointStart', pointStart ); + defineProperty( 'pointEnd', pointEnd ); + defineProperty( 'rotationAxis', rotationAxis ); + defineProperty( 'rotationAngle', rotationAngle ); + defineProperty( 'eye', eye ); + this._offset = new THREE.Vector3(); + this._startNorm = new THREE.Vector3(); + this._endNorm = new THREE.Vector3(); + this._cameraScale = new THREE.Vector3(); + this._parentPosition = new THREE.Vector3(); + this._parentQuaternion = new THREE.Quaternion(); + this._parentQuaternionInv = new THREE.Quaternion(); + this._parentScale = new THREE.Vector3(); + this._worldScaleStart = new THREE.Vector3(); + this._worldQuaternionInv = new THREE.Quaternion(); + this._worldScale = new THREE.Vector3(); + this._positionStart = new THREE.Vector3(); + this._quaternionStart = new THREE.Quaternion(); + this._scaleStart = new THREE.Vector3(); + this._getPointer = getPointer.bind( this ); + this._onPointerDown = onPointerDown.bind( this ); + this._onPointerHover = onPointerHover.bind( this ); + this._onPointerMove = onPointerMove.bind( this ); + this._onPointerUp = onPointerUp.bind( this ); + this.domElement.addEventListener( 'pointerdown', this._onPointerDown ); + this.domElement.addEventListener( 'pointermove', this._onPointerHover ); + this.domElement.ownerDocument.addEventListener( 'pointerup', this._onPointerUp ); + + } // updateMatrixWorld updates key transformation variables + + + updateMatrixWorld() { + + if ( this.object !== undefined ) { - } + this.object.updateMatrixWorld(); - this.dispose = function () { + if ( this.object.parent === null ) { - domElement.removeEventListener( 'pointerdown', onPointerDown ); - domElement.removeEventListener( 'pointermove', onPointerHover ); - scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); - scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp ); + console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' ); - this.traverse( function ( child ) { + } else { - if ( child.geometry ) child.geometry.dispose(); - if ( child.material ) child.material.dispose(); + this.object.parent.matrixWorld.decompose( this._parentPosition, this._parentQuaternion, this._parentScale ); - } ); + } - }; + this.object.matrixWorld.decompose( this.worldPosition, this.worldQuaternion, this._worldScale ); - // Set current object - this.attach = function ( object ) { + this._parentQuaternionInv.copy( this._parentQuaternion ).invert(); - this.object = object; - this.visible = true; + this._worldQuaternionInv.copy( this.worldQuaternion ).invert(); - return this; + } - }; + this.camera.updateMatrixWorld(); + this.camera.matrixWorld.decompose( this.cameraPosition, this.cameraQuaternion, this._cameraScale ); + this.eye.copy( this.cameraPosition ).sub( this.worldPosition ).normalize(); + super.updateMatrixWorld( this ); - // Detatch from object - this.detach = function () { + } - this.object = undefined; - this.visible = false; - this.axis = null; + pointerHover( pointer ) { - return this; + if ( this.object === undefined || this.dragging === true ) return; - }; + _raycaster.setFromCamera( pointer, this.camera ); - // Defined getter, setter and store for a property - function defineProperty( propName, defaultValue ) { + const intersect = intersectObjectWithRay( this._gizmo.picker[ this.mode ], _raycaster ); - var propValue = defaultValue; + if ( intersect ) { - Object.defineProperty( scope, propName, { + this.axis = intersect.object.name; - get: function () { + } else { - return propValue !== undefined ? propValue : defaultValue; + this.axis = null; - }, + } - set: function ( value ) { + } - if ( propValue !== value ) { + pointerDown( pointer ) { - propValue = value; - _plane[ propName ] = value; - _gizmo[ propName ] = value; + if ( this.object === undefined || this.dragging === true || pointer.button !== 0 ) return; - scope.dispatchEvent( { type: propName + '-changed', value: value } ); - scope.dispatchEvent( changeEvent ); + if ( this.axis !== null ) { - } + _raycaster.setFromCamera( pointer, this.camera ); - } + const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true ); - } ); + if ( planeIntersect ) { - scope[ propName ] = defaultValue; - _plane[ propName ] = defaultValue; - _gizmo[ propName ] = defaultValue; + let space = this.space; - } + if ( this.mode === 'scale' ) { - // updateMatrixWorld updates key transformation variables - this.updateMatrixWorld = function () { + space = 'local'; - if ( this.object !== undefined ) { + } else if ( this.axis === 'E' || this.axis === 'XYZE' || this.axis === 'XYZ' ) { - this.object.updateMatrixWorld(); + space = 'world'; - if ( this.object.parent === null ) { + } - console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' ); + if ( space === 'local' && this.mode === 'rotate' ) { - } else { + const snap = this.rotationSnap; + if ( this.axis === 'X' && snap ) this.object.rotation.x = Math.round( this.object.rotation.x / snap ) * snap; + if ( this.axis === 'Y' && snap ) this.object.rotation.y = Math.round( this.object.rotation.y / snap ) * snap; + if ( this.axis === 'Z' && snap ) this.object.rotation.z = Math.round( this.object.rotation.z / snap ) * snap; - this.object.parent.matrixWorld.decompose( parentPosition, parentQuaternion, parentScale ); + } - } + this.object.updateMatrixWorld(); + this.object.parent.updateMatrixWorld(); - this.object.matrixWorld.decompose( worldPosition, worldQuaternion, worldScale ); + this._positionStart.copy( this.object.position ); - parentQuaternionInv.copy( parentQuaternion ).invert(); - worldQuaternionInv.copy( worldQuaternion ).invert(); + this._quaternionStart.copy( this.object.quaternion ); - } + this._scaleStart.copy( this.object.scale ); - this.camera.updateMatrixWorld(); - this.camera.matrixWorld.decompose( cameraPosition, cameraQuaternion, cameraScale ); + this.object.matrixWorld.decompose( this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart ); + this.pointStart.copy( planeIntersect.point ).sub( this.worldPositionStart ); - eye.copy( cameraPosition ).sub( worldPosition ).normalize(); + } - THREE.Object3D.prototype.updateMatrixWorld.call( this ); + this.dragging = true; + _mouseDownEvent.mode = this.mode; + this.dispatchEvent( _mouseDownEvent ); - }; + } - this.pointerHover = function ( pointer ) { + } - if ( this.object === undefined || this.dragging === true ) return; + pointerMove( pointer ) { - raycaster.setFromCamera( pointer, this.camera ); + const axis = this.axis; + const mode = this.mode; + const object = this.object; + let space = this.space; - var intersect = intersectObjectWithRay( _gizmo.picker[ this.mode ], raycaster ); + if ( mode === 'scale' ) { - if ( intersect ) { + space = 'local'; - this.axis = intersect.object.name; + } else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) { - } else { + space = 'world'; - this.axis = null; + } - } + if ( object === undefined || axis === null || this.dragging === false || pointer.button !== - 1 ) return; - }; + _raycaster.setFromCamera( pointer, this.camera ); - this.pointerDown = function ( pointer ) { + const planeIntersect = intersectObjectWithRay( this._plane, _raycaster, true ); + if ( ! planeIntersect ) return; + this.pointEnd.copy( planeIntersect.point ).sub( this.worldPositionStart ); - if ( this.object === undefined || this.dragging === true || pointer.button !== 0 ) return; + if ( mode === 'translate' ) { - if ( this.axis !== null ) { + // Apply translate + this._offset.copy( this.pointEnd ).sub( this.pointStart ); - raycaster.setFromCamera( pointer, this.camera ); + if ( space === 'local' && axis !== 'XYZ' ) { - var planeIntersect = intersectObjectWithRay( _plane, raycaster, true ); + this._offset.applyQuaternion( this._worldQuaternionInv ); - if ( planeIntersect ) { + } - var space = this.space; + if ( axis.indexOf( 'X' ) === - 1 ) this._offset.x = 0; + if ( axis.indexOf( 'Y' ) === - 1 ) this._offset.y = 0; + if ( axis.indexOf( 'Z' ) === - 1 ) this._offset.z = 0; - if ( this.mode === 'scale' ) { + if ( space === 'local' && axis !== 'XYZ' ) { - space = 'local'; + this._offset.applyQuaternion( this._quaternionStart ).divide( this._parentScale ); - } else if ( this.axis === 'E' || this.axis === 'XYZE' || this.axis === 'XYZ' ) { + } else { - space = 'world'; + this._offset.applyQuaternion( this._parentQuaternionInv ).divide( this._parentScale ); } - if ( space === 'local' && this.mode === 'rotate' ) { + object.position.copy( this._offset ).add( this._positionStart ); // Apply translation snap - var snap = this.rotationSnap; + if ( this.translationSnap ) { - if ( this.axis === 'X' && snap ) this.object.rotation.x = Math.round( this.object.rotation.x / snap ) * snap; - if ( this.axis === 'Y' && snap ) this.object.rotation.y = Math.round( this.object.rotation.y / snap ) * snap; - if ( this.axis === 'Z' && snap ) this.object.rotation.z = Math.round( this.object.rotation.z / snap ) * snap; + if ( space === 'local' ) { - } + object.position.applyQuaternion( _tempQuaternion.copy( this._quaternionStart ).invert() ); - this.object.updateMatrixWorld(); - this.object.parent.updateMatrixWorld(); + if ( axis.search( 'X' ) !== - 1 ) { - positionStart.copy( this.object.position ); - quaternionStart.copy( this.object.quaternion ); - scaleStart.copy( this.object.scale ); + object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap; - this.object.matrixWorld.decompose( worldPositionStart, worldQuaternionStart, worldScaleStart ); + } - pointStart.copy( planeIntersect.point ).sub( worldPositionStart ); + if ( axis.search( 'Y' ) !== - 1 ) { - } + object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap; - this.dragging = true; - mouseDownEvent.mode = this.mode; - this.dispatchEvent( mouseDownEvent ); + } - } + if ( axis.search( 'Z' ) !== - 1 ) { - }; + object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap; - this.pointerMove = function ( pointer ) { + } - var axis = this.axis; - var mode = this.mode; - var object = this.object; - var space = this.space; + object.position.applyQuaternion( this._quaternionStart ); - if ( mode === 'scale' ) { + } - space = 'local'; + if ( space === 'world' ) { - } else if ( axis === 'E' || axis === 'XYZE' || axis === 'XYZ' ) { + if ( object.parent ) { - space = 'world'; + object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) ); - } + } - if ( object === undefined || axis === null || this.dragging === false || pointer.button !== - 1 ) return; + if ( axis.search( 'X' ) !== - 1 ) { - raycaster.setFromCamera( pointer, this.camera ); + object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap; - var planeIntersect = intersectObjectWithRay( _plane, raycaster, true ); + } - if ( ! planeIntersect ) return; + if ( axis.search( 'Y' ) !== - 1 ) { - pointEnd.copy( planeIntersect.point ).sub( worldPositionStart ); + object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap; - if ( mode === 'translate' ) { + } - // Apply translate + if ( axis.search( 'Z' ) !== - 1 ) { - offset.copy( pointEnd ).sub( pointStart ); + object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap; - if ( space === 'local' && axis !== 'XYZ' ) { + } - offset.applyQuaternion( worldQuaternionInv ); + if ( object.parent ) { - } + object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) ); - if ( axis.indexOf( 'X' ) === - 1 ) offset.x = 0; - if ( axis.indexOf( 'Y' ) === - 1 ) offset.y = 0; - if ( axis.indexOf( 'Z' ) === - 1 ) offset.z = 0; + } - if ( space === 'local' && axis !== 'XYZ' ) { + } - offset.applyQuaternion( quaternionStart ).divide( parentScale ); + } - } else { + } else if ( mode === 'scale' ) { - offset.applyQuaternion( parentQuaternionInv ).divide( parentScale ); + if ( axis.search( 'XYZ' ) !== - 1 ) { - } + let d = this.pointEnd.length() / this.pointStart.length(); + if ( this.pointEnd.dot( this.pointStart ) < 0 ) d *= - 1; - object.position.copy( offset ).add( positionStart ); + _tempVector2.set( d, d, d ); - // Apply translation snap + } else { - if ( this.translationSnap ) { + _tempVector.copy( this.pointStart ); - if ( space === 'local' ) { + _tempVector2.copy( this.pointEnd ); - object.position.applyQuaternion( _tempQuaternion.copy( quaternionStart ).invert() ); + _tempVector.applyQuaternion( this._worldQuaternionInv ); - if ( axis.search( 'X' ) !== - 1 ) { + _tempVector2.applyQuaternion( this._worldQuaternionInv ); - object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap; + _tempVector2.divide( _tempVector ); - } - - if ( axis.search( 'Y' ) !== - 1 ) { + if ( axis.search( 'X' ) === - 1 ) { - object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap; + _tempVector2.x = 1; } - if ( axis.search( 'Z' ) !== - 1 ) { + if ( axis.search( 'Y' ) === - 1 ) { - object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap; + _tempVector2.y = 1; } - object.position.applyQuaternion( quaternionStart ); + if ( axis.search( 'Z' ) === - 1 ) { - } + _tempVector2.z = 1; - if ( space === 'world' ) { + } - if ( object.parent ) { + } // Apply scale - object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) ); - } + object.scale.copy( this._scaleStart ).multiply( _tempVector2 ); + + if ( this.scaleSnap ) { if ( axis.search( 'X' ) !== - 1 ) { - object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap; + object.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap; } if ( axis.search( 'Y' ) !== - 1 ) { - object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap; + object.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap; } if ( axis.search( 'Z' ) !== - 1 ) { - object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap; + object.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap; } - if ( object.parent ) { + } - object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) ); + } else if ( mode === 'rotate' ) { - } + this._offset.copy( this.pointEnd ).sub( this.pointStart ); - } + const ROTATION_SPEED = 20 / this.worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) ); - } + if ( axis === 'E' ) { - } else if ( mode === 'scale' ) { + this.rotationAxis.copy( this.eye ); + this.rotationAngle = this.pointEnd.angleTo( this.pointStart ); - if ( axis.search( 'XYZ' ) !== - 1 ) { + this._startNorm.copy( this.pointStart ).normalize(); - var d = pointEnd.length() / pointStart.length(); + this._endNorm.copy( this.pointEnd ).normalize(); - if ( pointEnd.dot( pointStart ) < 0 ) d *= - 1; + this.rotationAngle *= this._endNorm.cross( this._startNorm ).dot( this.eye ) < 0 ? 1 : - 1; - _tempVector2.set( d, d, d ); + } else if ( axis === 'XYZE' ) { - } else { + this.rotationAxis.copy( this._offset ).cross( this.eye ).normalize(); + this.rotationAngle = this._offset.dot( _tempVector.copy( this.rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED; - _tempVector.copy( pointStart ); - _tempVector2.copy( pointEnd ); + } else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) { - _tempVector.applyQuaternion( worldQuaternionInv ); - _tempVector2.applyQuaternion( worldQuaternionInv ); + this.rotationAxis.copy( _unit[ axis ] ); - _tempVector2.divide( _tempVector ); + _tempVector.copy( _unit[ axis ] ); - if ( axis.search( 'X' ) === - 1 ) { + if ( space === 'local' ) { - _tempVector2.x = 1; + _tempVector.applyQuaternion( this.worldQuaternion ); - } + } - if ( axis.search( 'Y' ) === - 1 ) { + this.rotationAngle = this._offset.dot( _tempVector.cross( this.eye ).normalize() ) * ROTATION_SPEED; - _tempVector2.y = 1; + } // Apply rotation snap - } - if ( axis.search( 'Z' ) === - 1 ) { + if ( this.rotationSnap ) this.rotationAngle = Math.round( this.rotationAngle / this.rotationSnap ) * this.rotationSnap; // Apply rotate + + if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) { + + object.quaternion.copy( this._quaternionStart ); + object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) ).normalize(); + + } else { - _tempVector2.z = 1; + this.rotationAxis.applyQuaternion( this._parentQuaternionInv ); + object.quaternion.copy( _tempQuaternion.setFromAxisAngle( this.rotationAxis, this.rotationAngle ) ); + object.quaternion.multiply( this._quaternionStart ).normalize(); } } - // Apply scale + this.dispatchEvent( _changeEvent ); + this.dispatchEvent( _objectChangeEvent ); - object.scale.copy( scaleStart ).multiply( _tempVector2 ); + } - if ( this.scaleSnap ) { + pointerUp( pointer ) { - if ( axis.search( 'X' ) !== - 1 ) { + if ( pointer.button !== 0 ) return; - object.scale.x = Math.round( object.scale.x / this.scaleSnap ) * this.scaleSnap || this.scaleSnap; + if ( this.dragging && this.axis !== null ) { - } + _mouseUpEvent.mode = this.mode; + this.dispatchEvent( _mouseUpEvent ); - if ( axis.search( 'Y' ) !== - 1 ) { - - object.scale.y = Math.round( object.scale.y / this.scaleSnap ) * this.scaleSnap || this.scaleSnap; + } - } + this.dragging = false; + this.axis = null; - if ( axis.search( 'Z' ) !== - 1 ) { + } - object.scale.z = Math.round( object.scale.z / this.scaleSnap ) * this.scaleSnap || this.scaleSnap; + dispose() { - } + this.domElement.removeEventListener( 'pointerdown', this._onPointerDown ); + this.domElement.removeEventListener( 'pointermove', this._onPointerHover ); + this.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove ); + this.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp ); + this.traverse( function ( child ) { - } + if ( child.geometry ) child.geometry.dispose(); + if ( child.material ) child.material.dispose(); - } else if ( mode === 'rotate' ) { + } ); - offset.copy( pointEnd ).sub( pointStart ); + } // Set current object - var ROTATION_SPEED = 20 / worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) ); - if ( axis === 'E' ) { + attach( object ) { - rotationAxis.copy( eye ); - rotationAngle = pointEnd.angleTo( pointStart ); + this.object = object; + this.visible = true; + return this; - startNorm.copy( pointStart ).normalize(); - endNorm.copy( pointEnd ).normalize(); + } // Detatch from object - rotationAngle *= ( endNorm.cross( startNorm ).dot( eye ) < 0 ? 1 : - 1 ); - } else if ( axis === 'XYZE' ) { + detach() { - rotationAxis.copy( offset ).cross( eye ).normalize(); - rotationAngle = offset.dot( _tempVector.copy( rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED; + this.object = undefined; + this.visible = false; + this.axis = null; + return this; - } else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) { + } // TODO: deprecate - rotationAxis.copy( _unit[ axis ] ); - _tempVector.copy( _unit[ axis ] ); + getMode() { - if ( space === 'local' ) { + return this.mode; - _tempVector.applyQuaternion( worldQuaternion ); + } - } + setMode( mode ) { - rotationAngle = offset.dot( _tempVector.cross( eye ).normalize() ) * ROTATION_SPEED; + this.mode = mode; - } + } - // Apply rotation snap + setTranslationSnap( translationSnap ) { - if ( this.rotationSnap ) rotationAngle = Math.round( rotationAngle / this.rotationSnap ) * this.rotationSnap; + this.translationSnap = translationSnap; - this.rotationAngle = rotationAngle; + } - // Apply rotate - if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) { + setRotationSnap( rotationSnap ) { - object.quaternion.copy( quaternionStart ); - object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) ).normalize(); + this.rotationSnap = rotationSnap; - } else { + } - rotationAxis.applyQuaternion( parentQuaternionInv ); - object.quaternion.copy( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) ); - object.quaternion.multiply( quaternionStart ).normalize(); + setScaleSnap( scaleSnap ) { - } + this.scaleSnap = scaleSnap; } - this.dispatchEvent( changeEvent ); - this.dispatchEvent( objectChangeEvent ); + setSize( size ) { - }; - - this.pointerUp = function ( pointer ) { + this.size = size; - if ( pointer.button !== 0 ) return; + } - if ( this.dragging && ( this.axis !== null ) ) { + setSpace( space ) { - mouseUpEvent.mode = this.mode; - this.dispatchEvent( mouseUpEvent ); + this.space = space; } - this.dragging = false; - this.axis = null; + update() { - }; + console.warn( 'THREE.TransformControls: update function has no more functionality and therefore has been deprecated.' ); + + } + + } - // normalize mouse / touch pointer and remap {x,y} to view space. + TransformControls.prototype.isTransformControls = true; // mouse / touch event handlers function getPointer( event ) { - if ( scope.domElement.ownerDocument.pointerLockElement ) { + if ( this.domElement.ownerDocument.pointerLockElement ) { return { x: 0, @@ -591,10 +617,8 @@ THREE.TransformControls = function ( camera, domElement ) { } else { - var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event; - - var rect = domElement.getBoundingClientRect(); - + const pointer = event.changedTouches ? event.changedTouches[ 0 ] : event; + const rect = this.domElement.getBoundingClientRect(); return { x: ( pointer.clientX - rect.left ) / rect.width * 2 - 1, y: - ( pointer.clientY - rect.top ) / rect.height * 2 + 1, @@ -605,17 +629,15 @@ THREE.TransformControls = function ( camera, domElement ) { } - // mouse / touch event handlers - function onPointerHover( event ) { - if ( ! scope.enabled ) return; + if ( ! this.enabled ) return; switch ( event.pointerType ) { case 'mouse': case 'pen': - scope.pointerHover( getPointer( event ) ); + this.pointerHover( this._getPointer( event ) ); break; } @@ -624,1040 +646,826 @@ THREE.TransformControls = function ( camera, domElement ) { function onPointerDown( event ) { - if ( ! scope.enabled ) return; - - scope.domElement.style.touchAction = 'none'; // disable touch scroll - scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove ); + if ( ! this.enabled ) return; + this.domElement.style.touchAction = 'none'; // disable touch scroll - scope.pointerHover( getPointer( event ) ); - scope.pointerDown( getPointer( event ) ); + this.domElement.ownerDocument.addEventListener( 'pointermove', this._onPointerMove ); + this.pointerHover( this._getPointer( event ) ); + this.pointerDown( this._getPointer( event ) ); } function onPointerMove( event ) { - if ( ! scope.enabled ) return; - - scope.pointerMove( getPointer( event ) ); + if ( ! this.enabled ) return; + this.pointerMove( this._getPointer( event ) ); } function onPointerUp( event ) { - if ( ! scope.enabled ) return; - - scope.domElement.style.touchAction = ''; - scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove ); - - scope.pointerUp( getPointer( event ) ); + if ( ! this.enabled ) return; + this.domElement.style.touchAction = ''; + this.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove ); + this.pointerUp( this._getPointer( event ) ); } - // TODO: deprecate - - this.getMode = function () { - - return scope.mode; - - }; - - this.setMode = function ( mode ) { + function intersectObjectWithRay( object, raycaster, includeInvisible ) { - scope.mode = mode; + const allIntersections = raycaster.intersectObject( object, true ); - }; + for ( let i = 0; i < allIntersections.length; i ++ ) { - this.setTranslationSnap = function ( translationSnap ) { + if ( allIntersections[ i ].object.visible || includeInvisible ) { - scope.translationSnap = translationSnap; + return allIntersections[ i ]; - }; + } - this.setRotationSnap = function ( rotationSnap ) { + } - scope.rotationSnap = rotationSnap; + return false; - }; + } // + // Reusable utility variables - this.setScaleSnap = function ( scaleSnap ) { - scope.scaleSnap = scaleSnap; + const _tempEuler = new THREE.Euler(); + + const _alignVector = new THREE.Vector3( 0, 1, 0 ); - }; + const _zeroVector = new THREE.Vector3( 0, 0, 0 ); - this.setSize = function ( size ) { + const _lookAtMatrix = new THREE.Matrix4(); - scope.size = size; + const _tempQuaternion2 = new THREE.Quaternion(); - }; + const _identityQuaternion = new THREE.Quaternion(); - this.setSpace = function ( space ) { + const _dirVector = new THREE.Vector3(); - scope.space = space; + const _tempMatrix = new THREE.Matrix4(); - }; + const _unitX = new THREE.Vector3( 1, 0, 0 ); - this.update = function () { + const _unitY = new THREE.Vector3( 0, 1, 0 ); - console.warn( 'THREE.TransformControls: update function has no more functionality and therefore has been deprecated.' ); + const _unitZ = new THREE.Vector3( 0, 0, 1 ); - }; + const _v1 = new THREE.Vector3(); -}; + const _v2 = new THREE.Vector3(); -THREE.TransformControls.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { + const _v3 = new THREE.Vector3(); - constructor: THREE.TransformControls, + class TransformControlsGizmo extends THREE.Object3D { - isTransformControls: true + constructor() { -} ); + super(); + this.type = 'TransformControlsGizmo'; // shared materials + const gizmoMaterial = new THREE.MeshBasicMaterial( { + depthTest: false, + depthWrite: false, + transparent: true, + side: THREE.DoubleSide, + fog: false, + toneMapped: false + } ); + const gizmoLineMaterial = new THREE.LineBasicMaterial( { + depthTest: false, + depthWrite: false, + transparent: true, + linewidth: 1, + fog: false, + toneMapped: false + } ); // Make unique material for each axis/color -THREE.TransformControlsGizmo = function () { + const matInvisible = gizmoMaterial.clone(); + matInvisible.opacity = 0.15; + const matHelper = gizmoMaterial.clone(); + matHelper.opacity = 0.33; + const matRed = gizmoMaterial.clone(); + matRed.color.set( 0xff0000 ); + const matGreen = gizmoMaterial.clone(); + matGreen.color.set( 0x00ff00 ); + const matBlue = gizmoMaterial.clone(); + matBlue.color.set( 0x0000ff ); + const matWhiteTransparent = gizmoMaterial.clone(); + matWhiteTransparent.opacity = 0.25; + const matYellowTransparent = matWhiteTransparent.clone(); + matYellowTransparent.color.set( 0xffff00 ); + const matCyanTransparent = matWhiteTransparent.clone(); + matCyanTransparent.color.set( 0x00ffff ); + const matMagentaTransparent = matWhiteTransparent.clone(); + matMagentaTransparent.color.set( 0xff00ff ); + const matYellow = gizmoMaterial.clone(); + matYellow.color.set( 0xffff00 ); + const matLineRed = gizmoLineMaterial.clone(); + matLineRed.color.set( 0xff0000 ); + const matLineGreen = gizmoLineMaterial.clone(); + matLineGreen.color.set( 0x00ff00 ); + const matLineBlue = gizmoLineMaterial.clone(); + matLineBlue.color.set( 0x0000ff ); + const matLineCyan = gizmoLineMaterial.clone(); + matLineCyan.color.set( 0x00ffff ); + const matLineMagenta = gizmoLineMaterial.clone(); + matLineMagenta.color.set( 0xff00ff ); + const matLineYellow = gizmoLineMaterial.clone(); + matLineYellow.color.set( 0xffff00 ); + const matLineGray = gizmoLineMaterial.clone(); + matLineGray.color.set( 0x787878 ); + const matLineYellowTransparent = matLineYellow.clone(); + matLineYellowTransparent.opacity = 0.25; // reusable geometry - 'use strict'; + const arrowGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.2, 12, 1, false ); + const scaleHandleGeometry = new THREE.BoxGeometry( 0.125, 0.125, 0.125 ); + const lineGeometry = new THREE.BufferGeometry(); + lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) ); - THREE.Object3D.call( this ); + function CircleGeometry( radius, arc ) { - this.type = 'TransformControlsGizmo'; + const geometry = new THREE.BufferGeometry(); + const vertices = []; - // shared materials + for ( let i = 0; i <= 64 * arc; ++ i ) { + + vertices.push( 0, Math.cos( i / 32 * Math.PI ) * radius, Math.sin( i / 32 * Math.PI ) * radius ); - var gizmoMaterial = new THREE.MeshBasicMaterial( { - depthTest: false, - depthWrite: false, - transparent: true, - side: THREE.DoubleSide, - fog: false, - toneMapped: false - } ); + } - var gizmoLineMaterial = new THREE.LineBasicMaterial( { - depthTest: false, - depthWrite: false, - transparent: true, - linewidth: 1, - fog: false, - toneMapped: false - } ); + geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); + return geometry; - // Make unique material for each axis/color + } // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position - var matInvisible = gizmoMaterial.clone(); - matInvisible.opacity = 0.15; - var matHelper = gizmoMaterial.clone(); - matHelper.opacity = 0.33; + function TranslateHelperGeometry() { - var matRed = gizmoMaterial.clone(); - matRed.color.set( 0xff0000 ); + const geometry = new THREE.BufferGeometry(); + geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) ); + return geometry; - var matGreen = gizmoMaterial.clone(); - matGreen.color.set( 0x00ff00 ); + } // Gizmo definitions - custom hierarchy definitions for setupGizmo() function - var matBlue = gizmoMaterial.clone(); - matBlue.color.set( 0x0000ff ); - var matWhiteTransparent = gizmoMaterial.clone(); - matWhiteTransparent.opacity = 0.25; + const gizmoTranslate = { + X: [[ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, - Math.PI / 2 ], null, 'fwd' ], [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, Math.PI / 2 ], null, 'bwd' ], [ new THREE.Line( lineGeometry, matLineRed ) ]], + Y: [[ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], null, null, 'fwd' ], [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], [ Math.PI, 0, 0 ], null, 'bwd' ], [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ]]], + Z: [[ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ Math.PI / 2, 0, 0 ], null, 'fwd' ], [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ - Math.PI / 2, 0, 0 ], null, 'bwd' ], [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, - Math.PI / 2, 0 ]]], + XYZ: [[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), matWhiteTransparent.clone() ), [ 0, 0, 0 ], [ 0, 0, 0 ]]], + XY: [[ new THREE.Mesh( new THREE.PlaneGeometry( 0.295, 0.295 ), matYellowTransparent.clone() ), [ 0.15, 0.15, 0 ]], [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.18, 0.3, 0 ], null, [ 0.125, 1, 1 ]], [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.3, 0.18, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]]], + YZ: [[ new THREE.Mesh( new THREE.PlaneGeometry( 0.295, 0.295 ), matCyanTransparent.clone() ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]], [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.18, 0.3 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]], [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.3, 0.18 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]], + XZ: [[ new THREE.Mesh( new THREE.PlaneGeometry( 0.295, 0.295 ), matMagentaTransparent.clone() ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]], [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.18, 0, 0.3 ], null, [ 0.125, 1, 1 ]], [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.3, 0, 0.18 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]] + }; + const pickerTranslate = { + X: [[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]], + Y: [[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0.6, 0 ]]], + Z: [[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ]]], + XYZ: [[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.2, 0 ), matInvisible ) ]], + XY: [[ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0.2, 0 ]]], + YZ: [[ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), matInvisible ), [ 0, 0.2, 0.2 ], [ 0, Math.PI / 2, 0 ]]], + XZ: [[ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0, 0.2 ], [ - Math.PI / 2, 0, 0 ]]] + }; + const helperTranslate = { + START: [[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]], + END: [[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ]], + DELTA: [[ new THREE.Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ]], + X: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]], + Y: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]], + Z: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]] + }; + const gizmoRotate = { + X: [[ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineRed ) ], [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.04, 0 ), matRed ), [ 0, 0, 0.99 ], null, [ 1, 3, 1 ]]], + Y: [[ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineGreen ), null, [ 0, 0, - Math.PI / 2 ]], [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.04, 0 ), matGreen ), [ 0, 0, 0.99 ], null, [ 3, 1, 1 ]]], + Z: [[ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineBlue ), null, [ 0, Math.PI / 2, 0 ]], [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.04, 0 ), matBlue ), [ 0.99, 0, 0 ], null, [ 1, 3, 1 ]]], + E: [[ new THREE.Line( CircleGeometry( 1.25, 1 ), matLineYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]], [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 1.17, 0, 0 ], [ 0, 0, - Math.PI / 2 ], [ 1, 1, 0.001 ]], [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ - 1.17, 0, 0 ], [ 0, 0, Math.PI / 2 ], [ 1, 1, 0.001 ]], [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, - 1.17, 0 ], [ Math.PI, 0, 0 ], [ 1, 1, 0.001 ]], [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, 1.17, 0 ], [ 0, 0, 0 ], [ 1, 1, 0.001 ]]], + XYZE: [[ new THREE.Line( CircleGeometry( 1, 1 ), matLineGray ), null, [ 0, Math.PI / 2, 0 ]]] + }; + const helperRotate = { + AXIS: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]] + }; + const pickerRotate = { + X: [[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]]], + Y: [[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]]], + Z: [[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]], + E: [[ new THREE.Mesh( new THREE.TorusGeometry( 1.25, 0.1, 2, 24 ), matInvisible ) ]], + XYZE: [[ new THREE.Mesh( new THREE.SphereGeometry( 0.7, 10, 8 ), matInvisible ) ]] + }; + const gizmoScale = { + X: [[ new THREE.Mesh( scaleHandleGeometry, matRed ), [ 0.8, 0, 0 ], [ 0, 0, - Math.PI / 2 ]], [ new THREE.Line( lineGeometry, matLineRed ), null, null, [ 0.8, 1, 1 ]]], + Y: [[ new THREE.Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.8, 0 ]], [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ], [ 0.8, 1, 1 ]]], + Z: [[ new THREE.Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.8 ], [ Math.PI / 2, 0, 0 ]], [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, - Math.PI / 2, 0 ], [ 0.8, 1, 1 ]]], + XY: [[ new THREE.Mesh( scaleHandleGeometry, matYellowTransparent ), [ 0.85, 0.85, 0 ], null, [ 2, 2, 0.2 ]], [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.855, 0.98, 0 ], null, [ 0.125, 1, 1 ]], [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.98, 0.855, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]]], + YZ: [[ new THREE.Mesh( scaleHandleGeometry, matCyanTransparent ), [ 0, 0.85, 0.85 ], null, [ 0.2, 2, 2 ]], [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.855, 0.98 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]], [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.98, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]], + XZ: [[ new THREE.Mesh( scaleHandleGeometry, matMagentaTransparent ), [ 0.85, 0, 0.85 ], null, [ 2, 0.2, 2 ]], [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.855, 0, 0.98 ], null, [ 0.125, 1, 1 ]], [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.98, 0, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]]], + XYZX: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 1.1, 0, 0 ]]], + XYZY: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 1.1, 0 ]]], + XYZZ: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 0, 1.1 ]]] + }; + const pickerScale = { + X: [[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]]], + Y: [[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0.5, 0 ]]], + Z: [[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]]], + XY: [[ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0.85, 0 ], null, [ 3, 3, 0.2 ]]], + YZ: [[ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0, 0.85, 0.85 ], null, [ 0.2, 3, 3 ]]], + XZ: [[ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0, 0.85 ], null, [ 3, 0.2, 3 ]]], + XYZX: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 1.1, 0, 0 ]]], + XYZY: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 1.1, 0 ]]], + XYZZ: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 1.1 ]]] + }; + const helperScale = { + X: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ]], + Y: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ]], + Z: [[ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ]] + }; // Creates an THREE.Object3D with gizmos described in custom hierarchy definition. - var matYellowTransparent = matWhiteTransparent.clone(); - matYellowTransparent.color.set( 0xffff00 ); + function setupGizmo( gizmoMap ) { - var matCyanTransparent = matWhiteTransparent.clone(); - matCyanTransparent.color.set( 0x00ffff ); + const gizmo = new THREE.Object3D(); - var matMagentaTransparent = matWhiteTransparent.clone(); - matMagentaTransparent.color.set( 0xff00ff ); + for ( const name in gizmoMap ) { - var matYellow = gizmoMaterial.clone(); - matYellow.color.set( 0xffff00 ); + for ( let i = gizmoMap[ name ].length; i --; ) { - var matLineRed = gizmoLineMaterial.clone(); - matLineRed.color.set( 0xff0000 ); + const object = gizmoMap[ name ][ i ][ 0 ].clone(); + const position = gizmoMap[ name ][ i ][ 1 ]; + const rotation = gizmoMap[ name ][ i ][ 2 ]; + const scale = gizmoMap[ name ][ i ][ 3 ]; + const tag = gizmoMap[ name ][ i ][ 4 ]; // name and tag properties are essential for picking and updating logic. - var matLineGreen = gizmoLineMaterial.clone(); - matLineGreen.color.set( 0x00ff00 ); + object.name = name; + object.tag = tag; - var matLineBlue = gizmoLineMaterial.clone(); - matLineBlue.color.set( 0x0000ff ); + if ( position ) { - var matLineCyan = gizmoLineMaterial.clone(); - matLineCyan.color.set( 0x00ffff ); + object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] ); - var matLineMagenta = gizmoLineMaterial.clone(); - matLineMagenta.color.set( 0xff00ff ); + } - var matLineYellow = gizmoLineMaterial.clone(); - matLineYellow.color.set( 0xffff00 ); + if ( rotation ) { - var matLineGray = gizmoLineMaterial.clone(); - matLineGray.color.set( 0x787878 ); + object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] ); - var matLineYellowTransparent = matLineYellow.clone(); - matLineYellowTransparent.opacity = 0.25; + } - // reusable geometry + if ( scale ) { - var arrowGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.2, 12, 1, false ); + object.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] ); - var scaleHandleGeometry = new THREE.BoxGeometry( 0.125, 0.125, 0.125 ); + } - var lineGeometry = new THREE.BufferGeometry(); - lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) ); + object.updateMatrix(); + const tempGeometry = object.geometry.clone(); + tempGeometry.applyMatrix4( object.matrix ); + object.geometry = tempGeometry; + object.renderOrder = Infinity; + object.position.set( 0, 0, 0 ); + object.rotation.set( 0, 0, 0 ); + object.scale.set( 1, 1, 1 ); + gizmo.add( object ); - var CircleGeometry = function ( radius, arc ) { + } - var geometry = new THREE.BufferGeometry( ); - var vertices = []; + } - for ( var i = 0; i <= 64 * arc; ++ i ) { + return gizmo; - vertices.push( 0, Math.cos( i / 32 * Math.PI ) * radius, Math.sin( i / 32 * Math.PI ) * radius ); + } // Gizmo creation - } - geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); + this.gizmo = {}; + this.picker = {}; + this.helper = {}; + this.add( this.gizmo[ 'translate' ] = setupGizmo( gizmoTranslate ) ); + this.add( this.gizmo[ 'rotate' ] = setupGizmo( gizmoRotate ) ); + this.add( this.gizmo[ 'scale' ] = setupGizmo( gizmoScale ) ); + this.add( this.picker[ 'translate' ] = setupGizmo( pickerTranslate ) ); + this.add( this.picker[ 'rotate' ] = setupGizmo( pickerRotate ) ); + this.add( this.picker[ 'scale' ] = setupGizmo( pickerScale ) ); + this.add( this.helper[ 'translate' ] = setupGizmo( helperTranslate ) ); + this.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) ); + this.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) ); // Pickers should be hidden always - return geometry; + this.picker[ 'translate' ].visible = false; + this.picker[ 'rotate' ].visible = false; + this.picker[ 'scale' ].visible = false; - }; + } // updateMatrixWorld will update transformations and appearance of individual handles - // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position - var TranslateHelperGeometry = function () { + updateMatrixWorld( force ) { - var geometry = new THREE.BufferGeometry(); + const space = this.mode === 'scale' ? this.space : 'local'; // scale always oriented to local rotation - geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) ); + const quaternion = space === 'local' ? this.worldQuaternion : _identityQuaternion; // Show only gizmos for current transform mode - return geometry; + this.gizmo[ 'translate' ].visible = this.mode === 'translate'; + this.gizmo[ 'rotate' ].visible = this.mode === 'rotate'; + this.gizmo[ 'scale' ].visible = this.mode === 'scale'; + this.helper[ 'translate' ].visible = this.mode === 'translate'; + this.helper[ 'rotate' ].visible = this.mode === 'rotate'; + this.helper[ 'scale' ].visible = this.mode === 'scale'; + let handles = []; + handles = handles.concat( this.picker[ this.mode ].children ); + handles = handles.concat( this.gizmo[ this.mode ].children ); + handles = handles.concat( this.helper[ this.mode ].children ); - }; + for ( let i = 0; i < handles.length; i ++ ) { - // Gizmo definitions - custom hierarchy definitions for setupGizmo() function - - var gizmoTranslate = { - X: [ - [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, - Math.PI / 2 ], null, 'fwd' ], - [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, Math.PI / 2 ], null, 'bwd' ], - [ new THREE.Line( lineGeometry, matLineRed ) ] - ], - Y: [ - [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], null, null, 'fwd' ], - [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], [ Math.PI, 0, 0 ], null, 'bwd' ], - [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ]] - ], - Z: [ - [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ Math.PI / 2, 0, 0 ], null, 'fwd' ], - [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ - Math.PI / 2, 0, 0 ], null, 'bwd' ], - [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, - Math.PI / 2, 0 ]] - ], - XYZ: [ - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), matWhiteTransparent.clone() ), [ 0, 0, 0 ], [ 0, 0, 0 ]] - ], - XY: [ - [ new THREE.Mesh( new THREE.PlaneGeometry( 0.295, 0.295 ), matYellowTransparent.clone() ), [ 0.15, 0.15, 0 ]], - [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.18, 0.3, 0 ], null, [ 0.125, 1, 1 ]], - [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.3, 0.18, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]] - ], - YZ: [ - [ new THREE.Mesh( new THREE.PlaneGeometry( 0.295, 0.295 ), matCyanTransparent.clone() ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ]], - [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.18, 0.3 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]], - [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.3, 0.18 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]] - ], - XZ: [ - [ new THREE.Mesh( new THREE.PlaneGeometry( 0.295, 0.295 ), matMagentaTransparent.clone() ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ]], - [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.18, 0, 0.3 ], null, [ 0.125, 1, 1 ]], - [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.3, 0, 0.18 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]] - ] - }; + const handle = handles[ i ]; // hide aligned to camera - var pickerTranslate = { - X: [ - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ]] - ], - Y: [ - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0.6, 0 ]] - ], - Z: [ - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ]] - ], - XYZ: [ - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.2, 0 ), matInvisible ) ] - ], - XY: [ - [ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0.2, 0 ]] - ], - YZ: [ - [ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), matInvisible ), [ 0, 0.2, 0.2 ], [ 0, Math.PI / 2, 0 ]] - ], - XZ: [ - [ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0, 0.2 ], [ - Math.PI / 2, 0, 0 ]] - ] - }; + handle.visible = true; + handle.rotation.set( 0, 0, 0 ); + handle.position.copy( this.worldPosition ); + let factor; - var helperTranslate = { - START: [ - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ] - ], - END: [ - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ] - ], - DELTA: [ - [ new THREE.Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ] - ], - X: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ] - ], - Y: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ] - ], - Z: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ] - ] - }; + if ( this.camera.isOrthographicCamera ) { - var gizmoRotate = { - X: [ - [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineRed ) ], - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.04, 0 ), matRed ), [ 0, 0, 0.99 ], null, [ 1, 3, 1 ]], - ], - Y: [ - [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineGreen ), null, [ 0, 0, - Math.PI / 2 ]], - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.04, 0 ), matGreen ), [ 0, 0, 0.99 ], null, [ 3, 1, 1 ]], - ], - Z: [ - [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineBlue ), null, [ 0, Math.PI / 2, 0 ]], - [ new THREE.Mesh( new THREE.OctahedronGeometry( 0.04, 0 ), matBlue ), [ 0.99, 0, 0 ], null, [ 1, 3, 1 ]], - ], - E: [ - [ new THREE.Line( CircleGeometry( 1.25, 1 ), matLineYellowTransparent ), null, [ 0, Math.PI / 2, 0 ]], - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 1.17, 0, 0 ], [ 0, 0, - Math.PI / 2 ], [ 1, 1, 0.001 ]], - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ - 1.17, 0, 0 ], [ 0, 0, Math.PI / 2 ], [ 1, 1, 0.001 ]], - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, - 1.17, 0 ], [ Math.PI, 0, 0 ], [ 1, 1, 0.001 ]], - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, 1.17, 0 ], [ 0, 0, 0 ], [ 1, 1, 0.001 ]], - ], - XYZE: [ - [ new THREE.Line( CircleGeometry( 1, 1 ), matLineGray ), null, [ 0, Math.PI / 2, 0 ]] - ] - }; + factor = ( this.camera.top - this.camera.bottom ) / this.camera.zoom; - var helperRotate = { - AXIS: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ] - ] - }; + } else { - var pickerRotate = { - X: [ - [ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ]], - ], - Y: [ - [ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ]], - ], - Z: [ - [ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ]], - ], - E: [ - [ new THREE.Mesh( new THREE.TorusGeometry( 1.25, 0.1, 2, 24 ), matInvisible ) ] - ], - XYZE: [ - [ new THREE.Mesh( new THREE.SphereGeometry( 0.7, 10, 8 ), matInvisible ) ] - ] - }; + factor = this.worldPosition.distanceTo( this.cameraPosition ) * Math.min( 1.9 * Math.tan( Math.PI * this.camera.fov / 360 ) / this.camera.zoom, 7 ); - var gizmoScale = { - X: [ - [ new THREE.Mesh( scaleHandleGeometry, matRed ), [ 0.8, 0, 0 ], [ 0, 0, - Math.PI / 2 ]], - [ new THREE.Line( lineGeometry, matLineRed ), null, null, [ 0.8, 1, 1 ]] - ], - Y: [ - [ new THREE.Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.8, 0 ]], - [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ], [ 0.8, 1, 1 ]] - ], - Z: [ - [ new THREE.Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.8 ], [ Math.PI / 2, 0, 0 ]], - [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, - Math.PI / 2, 0 ], [ 0.8, 1, 1 ]] - ], - XY: [ - [ new THREE.Mesh( scaleHandleGeometry, matYellowTransparent ), [ 0.85, 0.85, 0 ], null, [ 2, 2, 0.2 ]], - [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.855, 0.98, 0 ], null, [ 0.125, 1, 1 ]], - [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.98, 0.855, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]] - ], - YZ: [ - [ new THREE.Mesh( scaleHandleGeometry, matCyanTransparent ), [ 0, 0.85, 0.85 ], null, [ 0.2, 2, 2 ]], - [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.855, 0.98 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ]], - [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.98, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]] - ], - XZ: [ - [ new THREE.Mesh( scaleHandleGeometry, matMagentaTransparent ), [ 0.85, 0, 0.85 ], null, [ 2, 0.2, 2 ]], - [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.855, 0, 0.98 ], null, [ 0.125, 1, 1 ]], - [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.98, 0, 0.855 ], [ 0, - Math.PI / 2, 0 ], [ 0.125, 1, 1 ]] - ], - XYZX: [ - [ new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 1.1, 0, 0 ]], - ], - XYZY: [ - [ new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 1.1, 0 ]], - ], - XYZZ: [ - [ new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ), matWhiteTransparent.clone() ), [ 0, 0, 1.1 ]], - ] - }; + } - var pickerScale = { - X: [ - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ]] - ], - Y: [ - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0.5, 0 ]] - ], - Z: [ - [ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ]] - ], - XY: [ - [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0.85, 0 ], null, [ 3, 3, 0.2 ]], - ], - YZ: [ - [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0, 0.85, 0.85 ], null, [ 0.2, 3, 3 ]], - ], - XZ: [ - [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0, 0.85 ], null, [ 3, 0.2, 3 ]], - ], - XYZX: [ - [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 1.1, 0, 0 ]], - ], - XYZY: [ - [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 1.1, 0 ]], - ], - XYZZ: [ - [ new THREE.Mesh( new THREE.BoxGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 1.1 ]], - ] - }; + handle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 7 ); // TODO: simplify helpers and consider decoupling from gizmo - var helperScale = { - X: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ - 1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ] - ], - Y: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, - 1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ] - ], - Z: [ - [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, - 1e3 ], [ 0, - Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ] - ] - }; + if ( handle.tag === 'helper' ) { - // Creates an Object3D with gizmos described in custom hierarchy definition. + handle.visible = false; - var setupGizmo = function ( gizmoMap ) { + if ( handle.name === 'AXIS' ) { - var gizmo = new THREE.Object3D(); + handle.position.copy( this.worldPositionStart ); + handle.visible = !! this.axis; - for ( var name in gizmoMap ) { + if ( this.axis === 'X' ) { - for ( var i = gizmoMap[ name ].length; i --; ) { + _tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, 0 ) ); - var object = gizmoMap[ name ][ i ][ 0 ].clone(); - var position = gizmoMap[ name ][ i ][ 1 ]; - var rotation = gizmoMap[ name ][ i ][ 2 ]; - var scale = gizmoMap[ name ][ i ][ 3 ]; - var tag = gizmoMap[ name ][ i ][ 4 ]; + handle.quaternion.copy( quaternion ).multiply( _tempQuaternion ); - // name and tag properties are essential for picking and updating logic. - object.name = name; - object.tag = tag; + if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { - if ( position ) { + handle.visible = false; - object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] ); + } - } + } - if ( rotation ) { + if ( this.axis === 'Y' ) { - object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] ); + _tempQuaternion.setFromEuler( _tempEuler.set( 0, 0, Math.PI / 2 ) ); - } + handle.quaternion.copy( quaternion ).multiply( _tempQuaternion ); - if ( scale ) { + if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { - object.scale.set( scale[ 0 ], scale[ 1 ], scale[ 2 ] ); + handle.visible = false; - } + } - object.updateMatrix(); + } - var tempGeometry = object.geometry.clone(); - tempGeometry.applyMatrix4( object.matrix ); - object.geometry = tempGeometry; - object.renderOrder = Infinity; + if ( this.axis === 'Z' ) { - object.position.set( 0, 0, 0 ); - object.rotation.set( 0, 0, 0 ); - object.scale.set( 1, 1, 1 ); + _tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) ); - gizmo.add( object ); + handle.quaternion.copy( quaternion ).multiply( _tempQuaternion ); - } + if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { - } + handle.visible = false; - return gizmo; + } - }; + } - // Reusable utility variables + if ( this.axis === 'XYZE' ) { - var tempVector = new THREE.Vector3( 0, 0, 0 ); - var tempEuler = new THREE.Euler(); - var alignVector = new THREE.Vector3( 0, 1, 0 ); - var zeroVector = new THREE.Vector3( 0, 0, 0 ); - var lookAtMatrix = new THREE.Matrix4(); - var tempQuaternion = new THREE.Quaternion(); - var tempQuaternion2 = new THREE.Quaternion(); - var identityQuaternion = new THREE.Quaternion(); + _tempQuaternion.setFromEuler( _tempEuler.set( 0, Math.PI / 2, 0 ) ); - var unitX = new THREE.Vector3( 1, 0, 0 ); - var unitY = new THREE.Vector3( 0, 1, 0 ); - var unitZ = new THREE.Vector3( 0, 0, 1 ); + _alignVector.copy( this.rotationAxis ); - // Gizmo creation + handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( _zeroVector, _alignVector, _unitY ) ); + handle.quaternion.multiply( _tempQuaternion ); + handle.visible = this.dragging; - this.gizmo = {}; - this.picker = {}; - this.helper = {}; + } - this.add( this.gizmo[ 'translate' ] = setupGizmo( gizmoTranslate ) ); - this.add( this.gizmo[ 'rotate' ] = setupGizmo( gizmoRotate ) ); - this.add( this.gizmo[ 'scale' ] = setupGizmo( gizmoScale ) ); - this.add( this.picker[ 'translate' ] = setupGizmo( pickerTranslate ) ); - this.add( this.picker[ 'rotate' ] = setupGizmo( pickerRotate ) ); - this.add( this.picker[ 'scale' ] = setupGizmo( pickerScale ) ); - this.add( this.helper[ 'translate' ] = setupGizmo( helperTranslate ) ); - this.add( this.helper[ 'rotate' ] = setupGizmo( helperRotate ) ); - this.add( this.helper[ 'scale' ] = setupGizmo( helperScale ) ); + if ( this.axis === 'E' ) { - // Pickers should be hidden always + handle.visible = false; - this.picker[ 'translate' ].visible = false; - this.picker[ 'rotate' ].visible = false; - this.picker[ 'scale' ].visible = false; + } - // updateMatrixWorld will update transformations and appearance of individual handles + } else if ( handle.name === 'START' ) { - this.updateMatrixWorld = function () { + handle.position.copy( this.worldPositionStart ); + handle.visible = this.dragging; - var space = this.space; + } else if ( handle.name === 'END' ) { - if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation + handle.position.copy( this.worldPosition ); + handle.visible = this.dragging; - var quaternion = space === 'local' ? this.worldQuaternion : identityQuaternion; + } else if ( handle.name === 'DELTA' ) { - // Show only gizmos for current transform mode + handle.position.copy( this.worldPositionStart ); + handle.quaternion.copy( this.worldQuaternionStart ); - this.gizmo[ 'translate' ].visible = this.mode === 'translate'; - this.gizmo[ 'rotate' ].visible = this.mode === 'rotate'; - this.gizmo[ 'scale' ].visible = this.mode === 'scale'; + _tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 ); - this.helper[ 'translate' ].visible = this.mode === 'translate'; - this.helper[ 'rotate' ].visible = this.mode === 'rotate'; - this.helper[ 'scale' ].visible = this.mode === 'scale'; + _tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() ); + handle.scale.copy( _tempVector ); + handle.visible = this.dragging; - var handles = []; - handles = handles.concat( this.picker[ this.mode ].children ); - handles = handles.concat( this.gizmo[ this.mode ].children ); - handles = handles.concat( this.helper[ this.mode ].children ); + } else { - for ( var i = 0; i < handles.length; i ++ ) { + handle.quaternion.copy( quaternion ); - var handle = handles[ i ]; + if ( this.dragging ) { - // hide aligned to camera + handle.position.copy( this.worldPositionStart ); - handle.visible = true; - handle.rotation.set( 0, 0, 0 ); - handle.position.copy( this.worldPosition ); + } else { - var factor; + handle.position.copy( this.worldPosition ); - if ( this.camera.isOrthographicCamera ) { + } - factor = ( this.camera.top - this.camera.bottom ) / this.camera.zoom; + if ( this.axis ) { - } else { + handle.visible = this.axis.search( handle.name ) !== - 1; - factor = this.worldPosition.distanceTo( this.cameraPosition ) * Math.min( 1.9 * Math.tan( Math.PI * this.camera.fov / 360 ) / this.camera.zoom, 7 ); + } - } + } // If updating helper, skip rest of the loop - handle.scale.set( 1, 1, 1 ).multiplyScalar( factor * this.size / 7 ); - // TODO: simplify helpers and consider decoupling from gizmo + continue; - if ( handle.tag === 'helper' ) { + } // Align handles to current local or world rotation - handle.visible = false; - if ( handle.name === 'AXIS' ) { + handle.quaternion.copy( quaternion ); - handle.position.copy( this.worldPositionStart ); - handle.visible = !! this.axis; + if ( this.mode === 'translate' || this.mode === 'scale' ) { - if ( this.axis === 'X' ) { + // Hide translate and scale axis facing the camera + const AXIS_HIDE_TRESHOLD = 0.99; + const PLANE_HIDE_TRESHOLD = 0.2; + const AXIS_FLIP_TRESHOLD = 0.0; - tempQuaternion.setFromEuler( tempEuler.set( 0, 0, 0 ) ); - handle.quaternion.copy( quaternion ).multiply( tempQuaternion ); + if ( handle.name === 'X' || handle.name === 'XYZX' ) { - if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { + if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); handle.visible = false; } } - if ( this.axis === 'Y' ) { - - tempQuaternion.setFromEuler( tempEuler.set( 0, 0, Math.PI / 2 ) ); - handle.quaternion.copy( quaternion ).multiply( tempQuaternion ); + if ( handle.name === 'Y' || handle.name === 'XYZY' ) { - if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { + if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); handle.visible = false; } } - if ( this.axis === 'Z' ) { - - tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) ); - handle.quaternion.copy( quaternion ).multiply( tempQuaternion ); + if ( handle.name === 'Z' || handle.name === 'XYZZ' ) { - if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { + if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); handle.visible = false; } } - if ( this.axis === 'XYZE' ) { + if ( handle.name === 'XY' ) { - tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) ); - alignVector.copy( this.rotationAxis ); - handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( zeroVector, alignVector, unitY ) ); - handle.quaternion.multiply( tempQuaternion ); - handle.visible = this.dragging; + if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { - } - - if ( this.axis === 'E' ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; - handle.visible = false; + } } + if ( handle.name === 'YZ' ) { - } else if ( handle.name === 'START' ) { - - handle.position.copy( this.worldPositionStart ); - handle.visible = this.dragging; + if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { - } else if ( handle.name === 'END' ) { - - handle.position.copy( this.worldPosition ); - handle.visible = this.dragging; - - } else if ( handle.name === 'DELTA' ) { - - handle.position.copy( this.worldPositionStart ); - handle.quaternion.copy( this.worldQuaternionStart ); - tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( - 1 ); - tempVector.applyQuaternion( this.worldQuaternionStart.clone().invert() ); - handle.scale.copy( tempVector ); - handle.visible = this.dragging; - - } else { - - handle.quaternion.copy( quaternion ); - - if ( this.dragging ) { - - handle.position.copy( this.worldPositionStart ); - - } else { - - handle.position.copy( this.worldPosition ); - - } - - if ( this.axis ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; - handle.visible = this.axis.search( handle.name ) !== - 1; + } } - } + if ( handle.name === 'XZ' ) { - // If updating helper, skip rest of the loop - continue; + if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { - } - - // Align handles to current local or world rotation + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; - handle.quaternion.copy( quaternion ); + } - if ( this.mode === 'translate' || this.mode === 'scale' ) { + } // Flip translate and scale axis ocluded behind another axis - // Hide translate and scale axis facing the camera - var AXIS_HIDE_TRESHOLD = 0.99; - var PLANE_HIDE_TRESHOLD = 0.2; - var AXIS_FLIP_TRESHOLD = 0.0; + if ( handle.name.search( 'X' ) !== - 1 ) { + if ( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { - if ( handle.name === 'X' || handle.name === 'XYZX' ) { + if ( handle.tag === 'fwd' ) { - if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.visible = false; - handle.scale.set( 1e-10, 1e-10, 1e-10 ); - handle.visible = false; + } else { - } + handle.scale.x *= - 1; - } + } - if ( handle.name === 'Y' || handle.name === 'XYZY' ) { + } else if ( handle.tag === 'bwd' ) { - if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.visible = false; - handle.scale.set( 1e-10, 1e-10, 1e-10 ); - handle.visible = false; + } } - } + if ( handle.name.search( 'Y' ) !== - 1 ) { - if ( handle.name === 'Z' || handle.name === 'XYZZ' ) { + if ( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { - if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + if ( handle.tag === 'fwd' ) { - handle.scale.set( 1e-10, 1e-10, 1e-10 ); - handle.visible = false; + handle.visible = false; - } + } else { - } - - if ( handle.name === 'XY' ) { + handle.scale.y *= - 1; - if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { + } - handle.scale.set( 1e-10, 1e-10, 1e-10 ); - handle.visible = false; + } else if ( handle.tag === 'bwd' ) { - } - - } - - if ( handle.name === 'YZ' ) { - - if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { + handle.visible = false; - handle.scale.set( 1e-10, 1e-10, 1e-10 ); - handle.visible = false; + } } - } - - if ( handle.name === 'XZ' ) { + if ( handle.name.search( 'Z' ) !== - 1 ) { - if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { + if ( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { - handle.scale.set( 1e-10, 1e-10, 1e-10 ); - handle.visible = false; + if ( handle.tag === 'fwd' ) { - } - - } + handle.visible = false; - // Flip translate and scale axis ocluded behind another axis + } else { - if ( handle.name.search( 'X' ) !== - 1 ) { + handle.scale.z *= - 1; - if ( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { + } - if ( handle.tag === 'fwd' ) { + } else if ( handle.tag === 'bwd' ) { handle.visible = false; - } else { - - handle.scale.x *= - 1; - } - } else if ( handle.tag === 'bwd' ) { - - handle.visible = false; - } - } + } else if ( this.mode === 'rotate' ) { - if ( handle.name.search( 'Y' ) !== - 1 ) { + // Align handles to current local or world rotation + _tempQuaternion2.copy( quaternion ); - if ( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { + _alignVector.copy( this.eye ).applyQuaternion( _tempQuaternion.copy( quaternion ).invert() ); - if ( handle.tag === 'fwd' ) { + if ( handle.name.search( 'E' ) !== - 1 ) { - handle.visible = false; + handle.quaternion.setFromRotationMatrix( _lookAtMatrix.lookAt( this.eye, _zeroVector, _unitY ) ); - } else { + } - handle.scale.y *= - 1; + if ( handle.name === 'X' ) { - } + _tempQuaternion.setFromAxisAngle( _unitX, Math.atan2( - _alignVector.y, _alignVector.z ) ); - } else if ( handle.tag === 'bwd' ) { + _tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion ); - handle.visible = false; + handle.quaternion.copy( _tempQuaternion ); } - } - - if ( handle.name.search( 'Z' ) !== - 1 ) { + if ( handle.name === 'Y' ) { - if ( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { + _tempQuaternion.setFromAxisAngle( _unitY, Math.atan2( _alignVector.x, _alignVector.z ) ); - if ( handle.tag === 'fwd' ) { + _tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion ); - handle.visible = false; + handle.quaternion.copy( _tempQuaternion ); - } else { + } - handle.scale.z *= - 1; + if ( handle.name === 'Z' ) { - } + _tempQuaternion.setFromAxisAngle( _unitZ, Math.atan2( _alignVector.y, _alignVector.x ) ); - } else if ( handle.tag === 'bwd' ) { + _tempQuaternion.multiplyQuaternions( _tempQuaternion2, _tempQuaternion ); - handle.visible = false; + handle.quaternion.copy( _tempQuaternion ); } - } + } // Hide disabled axes - } else if ( this.mode === 'rotate' ) { - // Align handles to current local or world rotation + handle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX ); + handle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY ); + handle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ ); + handle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || this.showX && this.showY && this.showZ ); // highlight selected axis - tempQuaternion2.copy( quaternion ); - alignVector.copy( this.eye ).applyQuaternion( tempQuaternion.copy( quaternion ).invert() ); + handle.material._opacity = handle.material._opacity || handle.material.opacity; + handle.material._color = handle.material._color || handle.material.color.clone(); + handle.material.color.copy( handle.material._color ); + handle.material.opacity = handle.material._opacity; - if ( handle.name.search( 'E' ) !== - 1 ) { + if ( ! this.enabled ) { - handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( this.eye, zeroVector, unitY ) ); + handle.material.opacity *= 0.5; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); - } + } else if ( this.axis ) { - if ( handle.name === 'X' ) { + if ( handle.name === this.axis ) { - tempQuaternion.setFromAxisAngle( unitX, Math.atan2( - alignVector.y, alignVector.z ) ); - tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion ); - handle.quaternion.copy( tempQuaternion ); + handle.material.opacity = 1.0; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); - } + } else if ( this.axis.split( '' ).some( function ( a ) { - if ( handle.name === 'Y' ) { + return handle.name === a; - tempQuaternion.setFromAxisAngle( unitY, Math.atan2( alignVector.x, alignVector.z ) ); - tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion ); - handle.quaternion.copy( tempQuaternion ); + } ) ) { - } + handle.material.opacity = 1.0; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); - if ( handle.name === 'Z' ) { + } else { - tempQuaternion.setFromAxisAngle( unitZ, Math.atan2( alignVector.y, alignVector.x ) ); - tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion ); - handle.quaternion.copy( tempQuaternion ); + handle.material.opacity *= 0.25; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + + } } } - // Hide disabled axes - handle.visible = handle.visible && ( handle.name.indexOf( 'X' ) === - 1 || this.showX ); - handle.visible = handle.visible && ( handle.name.indexOf( 'Y' ) === - 1 || this.showY ); - handle.visible = handle.visible && ( handle.name.indexOf( 'Z' ) === - 1 || this.showZ ); - handle.visible = handle.visible && ( handle.name.indexOf( 'E' ) === - 1 || ( this.showX && this.showY && this.showZ ) ); + super.updateMatrixWorld( force ); - // highlight selected axis - - handle.material._opacity = handle.material._opacity || handle.material.opacity; - handle.material._color = handle.material._color || handle.material.color.clone(); - - handle.material.color.copy( handle.material._color ); - handle.material.opacity = handle.material._opacity; - - if ( ! this.enabled ) { - - handle.material.opacity *= 0.5; - handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + } - } else if ( this.axis ) { + } - if ( handle.name === this.axis ) { + TransformControlsGizmo.prototype.isTransformControlsGizmo = true; // - handle.material.opacity = 1.0; - handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + class TransformControlsPlane extends THREE.Mesh { - } else if ( this.axis.split( '' ).some( function ( a ) { + constructor() { - return handle.name === a; + super( new THREE.PlaneGeometry( 100000, 100000, 2, 2 ), new THREE.MeshBasicMaterial( { + visible: false, + wireframe: true, + side: THREE.DoubleSide, + transparent: true, + opacity: 0.1, + toneMapped: false + } ) ); + this.type = 'TransformControlsPlane'; - } ) ) { + } - handle.material.opacity = 1.0; - handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + updateMatrixWorld( force ) { - } else { + let space = this.space; + this.position.copy( this.worldPosition ); + if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation - handle.material.opacity *= 0.25; - handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + _v1.copy( _unitX ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); - } + _v2.copy( _unitY ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); - } + _v3.copy( _unitZ ).applyQuaternion( space === 'local' ? this.worldQuaternion : _identityQuaternion ); // Align the plane for current transform mode, axis and space. - } - THREE.Object3D.prototype.updateMatrixWorld.call( this ); + _alignVector.copy( _v2 ); - }; + switch ( this.mode ) { -}; + case 'translate': + case 'scale': + switch ( this.axis ) { -THREE.TransformControlsGizmo.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { + case 'X': + _alignVector.copy( this.eye ).cross( _v1 ); - constructor: THREE.TransformControlsGizmo, + _dirVector.copy( _v1 ).cross( _alignVector ); - isTransformControlsGizmo: true + break; -} ); + case 'Y': + _alignVector.copy( this.eye ).cross( _v2 ); + _dirVector.copy( _v2 ).cross( _alignVector ); -THREE.TransformControlsPlane = function () { + break; - 'use strict'; + case 'Z': + _alignVector.copy( this.eye ).cross( _v3 ); - THREE.Mesh.call( this, - new THREE.PlaneGeometry( 100000, 100000, 2, 2 ), - new THREE.MeshBasicMaterial( { visible: false, wireframe: true, side: THREE.DoubleSide, transparent: true, opacity: 0.1, toneMapped: false } ) - ); + _dirVector.copy( _v3 ).cross( _alignVector ); - this.type = 'TransformControlsPlane'; + break; - var unitX = new THREE.Vector3( 1, 0, 0 ); - var unitY = new THREE.Vector3( 0, 1, 0 ); - var unitZ = new THREE.Vector3( 0, 0, 1 ); + case 'XY': + _dirVector.copy( _v3 ); - var tempVector = new THREE.Vector3(); - var dirVector = new THREE.Vector3(); - var alignVector = new THREE.Vector3(); - var tempMatrix = new THREE.Matrix4(); - var identityQuaternion = new THREE.Quaternion(); + break; - this.updateMatrixWorld = function () { + case 'YZ': + _dirVector.copy( _v1 ); - var space = this.space; + break; - this.position.copy( this.worldPosition ); + case 'XZ': + _alignVector.copy( _v3 ); - if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation + _dirVector.copy( _v2 ); - unitX.set( 1, 0, 0 ).applyQuaternion( space === 'local' ? this.worldQuaternion : identityQuaternion ); - unitY.set( 0, 1, 0 ).applyQuaternion( space === 'local' ? this.worldQuaternion : identityQuaternion ); - unitZ.set( 0, 0, 1 ).applyQuaternion( space === 'local' ? this.worldQuaternion : identityQuaternion ); + break; - // Align the plane for current transform mode, axis and space. + case 'XYZ': + case 'E': + _dirVector.set( 0, 0, 0 ); - alignVector.copy( unitY ); + break; - switch ( this.mode ) { + } - case 'translate': - case 'scale': - switch ( this.axis ) { + break; - case 'X': - alignVector.copy( this.eye ).cross( unitX ); - dirVector.copy( unitX ).cross( alignVector ); - break; - case 'Y': - alignVector.copy( this.eye ).cross( unitY ); - dirVector.copy( unitY ).cross( alignVector ); - break; - case 'Z': - alignVector.copy( this.eye ).cross( unitZ ); - dirVector.copy( unitZ ).cross( alignVector ); - break; - case 'XY': - dirVector.copy( unitZ ); - break; - case 'YZ': - dirVector.copy( unitX ); - break; - case 'XZ': - alignVector.copy( unitZ ); - dirVector.copy( unitY ); - break; - case 'XYZ': - case 'E': - dirVector.set( 0, 0, 0 ); - break; + case 'rotate': + default: + // special case for rotate + _dirVector.set( 0, 0, 0 ); - } + } - break; - case 'rotate': - default: - // special case for rotate - dirVector.set( 0, 0, 0 ); + if ( _dirVector.length() === 0 ) { - } + // If in rotate mode, make the plane parallel to camera + this.quaternion.copy( this.cameraQuaternion ); - if ( dirVector.length() === 0 ) { + } else { - // If in rotate mode, make the plane parallel to camera - this.quaternion.copy( this.cameraQuaternion ); + _tempMatrix.lookAt( _tempVector.set( 0, 0, 0 ), _dirVector, _alignVector ); - } else { + this.quaternion.setFromRotationMatrix( _tempMatrix ); - tempMatrix.lookAt( tempVector.set( 0, 0, 0 ), dirVector, alignVector ); + } - this.quaternion.setFromRotationMatrix( tempMatrix ); + super.updateMatrixWorld( force ); } - THREE.Object3D.prototype.updateMatrixWorld.call( this ); - - }; - -}; - -THREE.TransformControlsPlane.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { + } - constructor: THREE.TransformControlsPlane, + TransformControlsPlane.prototype.isTransformControlsPlane = true; - isTransformControlsPlane: true + THREE.TransformControls = TransformControls; + THREE.TransformControlsGizmo = TransformControlsGizmo; + THREE.TransformControlsPlane = TransformControlsPlane; -} ); +} )(); diff --git a/examples/js/controls/experimental/CameraControls.js b/examples/js/controls/experimental/CameraControls.js new file mode 100644 index 00000000000000..41709e26aceabf --- /dev/null +++ b/examples/js/controls/experimental/CameraControls.js @@ -0,0 +1,1044 @@ +( function () { + + var CameraControls = function ( object, domElement ) { + + if ( domElement === undefined ) console.warn( 'THREE.CameraControls: The second parameter "domElement" is now mandatory.' ); + if ( domElement === document ) console.error( 'THREE.CameraControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' ); + this.object = object; + this.domElement = domElement; // Set to false to disable this control + + this.enabled = true; // "target" sets the location of focus, where the object orbits around + + this.target = new THREE.Vector3(); // Set to true to enable trackball behavior + + this.trackball = false; // How far you can dolly in and out ( PerspectiveCamera only ) + + this.minDistance = 0; + this.maxDistance = Infinity; // How far you can zoom in and out ( OrthographicCamera only ) + + this.minZoom = 0; + this.maxZoom = Infinity; // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + + this.minPolarAngle = 0; // radians + + this.maxPolarAngle = Math.PI; // radians + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + + this.minAzimuthAngle = - Infinity; // radians + + this.maxAzimuthAngle = Infinity; // radians + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + + this.enableDamping = false; + this.dampingFactor = 0.05; // This option enables dollying in and out; property named as "zoom" for backwards compatibility + // Set to false to disable zooming + + this.enableZoom = true; + this.zoomSpeed = 1.0; // Set to false to disable rotating + + this.enableRotate = true; + this.rotateSpeed = 1.0; // Set to false to disable panning + + this.enablePan = true; + this.panSpeed = 1.0; + this.screenSpacePanning = false; // if true, pan in screen-space + + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + // auto-rotate is not supported for trackball behavior + + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // Set to false to disable use of the keys + + this.enableKeys = true; // The four arrow keys + + this.keys = { + LEFT: 37, + UP: 38, + RIGHT: 39, + BOTTOM: 40 + }; // Mouse buttons + + this.mouseButtons = { + LEFT: THREE.MOUSE.ROTATE, + MIDDLE: THREE.MOUSE.DOLLY, + RIGHT: THREE.MOUSE.PAN + }; // Touch fingers + + this.touches = { + ONE: THREE.TOUCH.ROTATE, + TWO: THREE.TOUCH.DOLLY_PAN + }; // for reset + + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.quaternion0 = this.object.quaternion.clone(); + this.zoom0 = this.object.zoom; // + // public methods + // + + this.getPolarAngle = function () { + + return spherical.phi; + + }; + + this.getAzimuthalAngle = function () { + + return spherical.theta; + + }; + + this.saveState = function () { + + scope.target0.copy( scope.target ); + scope.position0.copy( scope.object.position ); + scope.quaternion0.copy( scope.object.quaternion ); + scope.zoom0 = scope.object.zoom; + + }; + + this.reset = function () { + + scope.target.copy( scope.target0 ); + scope.object.position.copy( scope.position0 ); + scope.object.quaternion.copy( scope.quaternion0 ); + scope.object.zoom = scope.zoom0; + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + scope.update(); + state = STATE.NONE; + + }; // this method is exposed, but perhaps it would be better if we can make it private... + + + this.update = function () { + + var offset = new THREE.Vector3(); // so camera.up is the orbit axis + + var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); + var quatInverse = quat.clone().invert(); + var lastPosition = new THREE.Vector3(); + var lastQuaternion = new THREE.Quaternion(); + var q = new THREE.Quaternion(); + var vec = new THREE.Vector3(); + return function update() { + + var position = scope.object.position; + offset.copy( position ).sub( scope.target ); + + if ( scope.trackball ) { + + // rotate around screen-space y-axis + if ( sphericalDelta.theta ) { + + vec.set( 0, 1, 0 ).applyQuaternion( scope.object.quaternion ); + var factor = scope.enableDamping ? scope.dampingFactor : 1; + q.setFromAxisAngle( vec, sphericalDelta.theta * factor ); + scope.object.quaternion.premultiply( q ); + offset.applyQuaternion( q ); + + } // rotate around screen-space x-axis + + + if ( sphericalDelta.phi ) { + + vec.set( 1, 0, 0 ).applyQuaternion( scope.object.quaternion ); + var factor = scope.enableDamping ? scope.dampingFactor : 1; + q.setFromAxisAngle( vec, sphericalDelta.phi * factor ); + scope.object.quaternion.premultiply( q ); + offset.applyQuaternion( q ); + + } + + offset.multiplyScalar( scale ); + offset.clampLength( scope.minDistance, scope.maxDistance ); + + } else { + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion( quat ); + + if ( scope.autoRotate && state === STATE.NONE ) { + + rotateLeft( getAutoRotationAngle() ); + + } + + spherical.setFromVector3( offset ); + + if ( scope.enableDamping ) { + + spherical.theta += sphericalDelta.theta * scope.dampingFactor; + spherical.phi += sphericalDelta.phi * scope.dampingFactor; + + } else { + + spherical.theta += sphericalDelta.theta; + spherical.phi += sphericalDelta.phi; + + } // restrict theta to be between desired limits + + + spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) ); // restrict phi to be between desired limits + + spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); + spherical.makeSafe(); + spherical.radius *= scale; // restrict radius to be between desired limits + + spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); + offset.setFromSpherical( spherical ); // rotate offset back to "camera-up-vector-is-up" space + + offset.applyQuaternion( quatInverse ); + + } // move target to panned location + + + if ( scope.enableDamping === true ) { + + scope.target.addScaledVector( panOffset, scope.dampingFactor ); + + } else { + + scope.target.add( panOffset ); + + } + + position.copy( scope.target ).add( offset ); + + if ( scope.trackball === false ) { + + scope.object.lookAt( scope.target ); + + } + + if ( scope.enableDamping === true ) { + + sphericalDelta.theta *= 1 - scope.dampingFactor; + sphericalDelta.phi *= 1 - scope.dampingFactor; + panOffset.multiplyScalar( 1 - scope.dampingFactor ); + + } else { + + sphericalDelta.set( 0, 0, 0 ); + panOffset.set( 0, 0, 0 ); + + } + + scale = 1; // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + + if ( zoomChanged || lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { + + scope.dispatchEvent( changeEvent ); + lastPosition.copy( scope.object.position ); + lastQuaternion.copy( scope.object.quaternion ); + zoomChanged = false; + return true; + + } + + return false; + + }; + + }(); + + this.dispose = function () { + + scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); + scope.domElement.removeEventListener( 'mousedown', onMouseDown, false ); + scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); + scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + scope.domElement.removeEventListener( 'keydown', onKeyDown, false ); //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? + + }; // + // internals + // + + + var scope = this; + var changeEvent = { + type: 'change' + }; + var startEvent = { + type: 'start' + }; + var endEvent = { + type: 'end' + }; + var STATE = { + NONE: - 1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_PAN: 4, + TOUCH_DOLLY_PAN: 5, + TOUCH_DOLLY_ROTATE: 6 + }; + var state = STATE.NONE; + var EPS = 0.000001; // current position in spherical coordinates + + var spherical = new THREE.Spherical(); + var sphericalDelta = new THREE.Spherical(); + var scale = 1; + var panOffset = new THREE.Vector3(); + var zoomChanged = false; + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + var panStart = new THREE.Vector2(); + var panEnd = new THREE.Vector2(); + var panDelta = new THREE.Vector2(); + var dollyStart = new THREE.Vector2(); + var dollyEnd = new THREE.Vector2(); + var dollyDelta = new THREE.Vector2(); + + function getAutoRotationAngle() { + + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + + } + + function getZoomScale() { + + return Math.pow( 0.95, scope.zoomSpeed ); + + } + + function rotateLeft( angle ) { + + sphericalDelta.theta -= angle; + + } + + function rotateUp( angle ) { + + sphericalDelta.phi -= angle; + + } + + var panLeft = function () { + + var v = new THREE.Vector3(); + return function panLeft( distance, objectMatrix ) { + + v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix + + v.multiplyScalar( - distance ); + panOffset.add( v ); + + }; + + }(); + + var panUp = function () { + + var v = new THREE.Vector3(); + return function panUp( distance, objectMatrix ) { + + if ( scope.screenSpacePanning === true ) { + + v.setFromMatrixColumn( objectMatrix, 1 ); + + } else { + + v.setFromMatrixColumn( objectMatrix, 0 ); + v.crossVectors( scope.object.up, v ); + + } + + v.multiplyScalar( distance ); + panOffset.add( v ); + + }; + + }(); // deltaX and deltaY are in pixels; right and down are positive + + + var pan = function () { + + var offset = new THREE.Vector3(); + return function pan( deltaX, deltaY ) { + + var element = scope.domElement; + + if ( scope.object.isPerspectiveCamera ) { + + // perspective + var position = scope.object.position; + offset.copy( position ).sub( scope.target ); + var targetDistance = offset.length(); // half of the fov is center to top of screen + + targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 ); // we use only clientHeight here so aspect ratio does not distort speed + + panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); + panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); + + } else if ( scope.object.isOrthographicCamera ) { + + // orthographic + panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); + panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); + + } else { + + // camera neither orthographic nor perspective + console.warn( 'WARNING: CameraControls.js encountered an unknown camera type - pan disabled.' ); + scope.enablePan = false; + + } + + }; + + }(); + + function dollyIn( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: CameraControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } + + function dollyOut( dollyScale ) { + + if ( scope.object.isPerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object.isOrthographicCamera ) { + + scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: CameraControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + scope.enableZoom = false; + + } + + } // + // event callbacks - update the object state + // + + + function handleMouseDownRotate( event ) { + + rotateStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownDolly( event ) { + + dollyStart.set( event.clientX, event.clientY ); + + } + + function handleMouseDownPan( event ) { + + panStart.set( event.clientX, event.clientY ); + + } + + function handleMouseMoveRotate( event ) { + + rotateEnd.set( event.clientX, event.clientY ); + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + var element = scope.domElement; + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + rotateStart.copy( rotateEnd ); + scope.update(); + + } + + function handleMouseMoveDolly( event ) { + + dollyEnd.set( event.clientX, event.clientY ); + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + dollyIn( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + dollyOut( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + scope.update(); + + } + + function handleMouseMovePan( event ) { + + panEnd.set( event.clientX, event.clientY ); + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + pan( panDelta.x, panDelta.y ); + panStart.copy( panEnd ); + scope.update(); + + } + + function handleMouseUp( ) { // no-op + } + + function handleMouseWheel( event ) { + + if ( event.deltaY < 0 ) { + + dollyOut( getZoomScale() ); + + } else if ( event.deltaY > 0 ) { + + dollyIn( getZoomScale() ); + + } + + scope.update(); + + } + + function handleKeyDown( event ) { + + var needsUpdate = false; + + switch ( event.keyCode ) { + + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + needsUpdate = true; + break; + + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + needsUpdate = true; + break; + + } + + if ( needsUpdate ) { + + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + scope.update(); + + } + + } + + function handleTouchStartRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + rotateStart.set( x, y ); + + } + + } + + function handleTouchStartPan( event ) { + + if ( event.touches.length == 1 ) { + + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + panStart.set( x, y ); + + } + + } + + function handleTouchStartDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + var distance = Math.sqrt( dx * dx + dy * dy ); + dollyStart.set( 0, distance ); + + } + + function handleTouchStartDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + if ( scope.enablePan ) handleTouchStartPan( event ); + + } + + function handleTouchStartDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchStartDolly( event ); + if ( scope.enableRotate ) handleTouchStartRotate( event ); + + } + + function handleTouchMoveRotate( event ) { + + if ( event.touches.length == 1 ) { + + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + rotateEnd.set( x, y ); + + } + + rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); + var element = scope.domElement; + rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height + + rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); + rotateStart.copy( rotateEnd ); + + } + + function handleTouchMovePan( event ) { + + if ( event.touches.length == 1 ) { + + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + + } else { + + var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); + var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); + panEnd.set( x, y ); + + } + + panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); + pan( panDelta.x, panDelta.y ); + panStart.copy( panEnd ); + + } + + function handleTouchMoveDolly( event ) { + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + var distance = Math.sqrt( dx * dx + dy * dy ); + dollyEnd.set( 0, distance ); + dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); + dollyIn( dollyDelta.y ); + dollyStart.copy( dollyEnd ); + + } + + function handleTouchMoveDollyPan( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + if ( scope.enablePan ) handleTouchMovePan( event ); + + } + + function handleTouchMoveDollyRotate( event ) { + + if ( scope.enableZoom ) handleTouchMoveDolly( event ); + if ( scope.enableRotate ) handleTouchMoveRotate( event ); + + } + + function handleTouchEnd( ) { // no-op + } // + // event handlers - FSM: listen for events and reset state + // + + + function onMouseDown( event ) { + + if ( scope.enabled === false ) return; // Prevent the browser from scrolling. + + event.preventDefault(); // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. + + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + var mouseAction; + + switch ( event.button ) { + + case 0: + mouseAction = scope.mouseButtons.LEFT; + break; + + case 1: + mouseAction = scope.mouseButtons.MIDDLE; + break; + + case 2: + mouseAction = scope.mouseButtons.RIGHT; + break; + + default: + mouseAction = - 1; + + } + + switch ( mouseAction ) { + + case THREE.MOUSE.DOLLY: + if ( scope.enableZoom === false ) return; + handleMouseDownDolly( event ); + state = STATE.DOLLY; + break; + + case THREE.MOUSE.ROTATE: + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enablePan === false ) return; + handleMouseDownPan( event ); + state = STATE.PAN; + + } else { + + if ( scope.enableRotate === false ) return; + handleMouseDownRotate( event ); + state = STATE.ROTATE; + + } + + break; + + case THREE.MOUSE.PAN: + if ( event.ctrlKey || event.metaKey || event.shiftKey ) { + + if ( scope.enableRotate === false ) return; + handleMouseDownRotate( event ); + state = STATE.ROTATE; + + } else { + + if ( scope.enablePan === false ) return; + handleMouseDownPan( event ); + state = STATE.PAN; + + } + + break; + + default: + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + document.addEventListener( 'mousemove', onMouseMove, false ); + document.addEventListener( 'mouseup', onMouseUp, false ); + scope.dispatchEvent( startEvent ); + + } + + } + + function onMouseMove( event ) { + + if ( scope.enabled === false ) return; + event.preventDefault(); + + switch ( state ) { + + case STATE.ROTATE: + if ( scope.enableRotate === false ) return; + handleMouseMoveRotate( event ); + break; + + case STATE.DOLLY: + if ( scope.enableZoom === false ) return; + handleMouseMoveDolly( event ); + break; + + case STATE.PAN: + if ( scope.enablePan === false ) return; + handleMouseMovePan( event ); + break; + + } + + } + + function onMouseUp( event ) { + + if ( scope.enabled === false ) return; + handleMouseUp( event ); + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + scope.dispatchEvent( endEvent ); + state = STATE.NONE; + + } + + function onMouseWheel( event ) { + + if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE ) return; + event.preventDefault(); + event.stopPropagation(); + scope.dispatchEvent( startEvent ); + handleMouseWheel( event ); + scope.dispatchEvent( endEvent ); + + } + + function onKeyDown( event ) { + + if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + handleKeyDown( event ); + + } + + function onTouchStart( event ) { + + if ( scope.enabled === false ) return; + event.preventDefault(); + + switch ( event.touches.length ) { + + case 1: + switch ( scope.touches.ONE ) { + + case THREE.TOUCH.ROTATE: + if ( scope.enableRotate === false ) return; + handleTouchStartRotate( event ); + state = STATE.TOUCH_ROTATE; + break; + + case THREE.TOUCH.PAN: + if ( scope.enablePan === false ) return; + handleTouchStartPan( event ); + state = STATE.TOUCH_PAN; + break; + + default: + state = STATE.NONE; + + } + + break; + + case 2: + switch ( scope.touches.TWO ) { + + case THREE.TOUCH.DOLLY_PAN: + if ( scope.enableZoom === false && scope.enablePan === false ) return; + handleTouchStartDollyPan( event ); + state = STATE.TOUCH_DOLLY_PAN; + break; + + case THREE.TOUCH.DOLLY_ROTATE: + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + handleTouchStartDollyRotate( event ); + state = STATE.TOUCH_DOLLY_ROTATE; + break; + + default: + state = STATE.NONE; + + } + + break; + + default: + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) { + + scope.dispatchEvent( startEvent ); + + } + + } + + function onTouchMove( event ) { + + if ( scope.enabled === false ) return; + event.preventDefault(); + event.stopPropagation(); + + switch ( state ) { + + case STATE.TOUCH_ROTATE: + if ( scope.enableRotate === false ) return; + handleTouchMoveRotate( event ); + scope.update(); + break; + + case STATE.TOUCH_PAN: + if ( scope.enablePan === false ) return; + handleTouchMovePan( event ); + scope.update(); + break; + + case STATE.TOUCH_DOLLY_PAN: + if ( scope.enableZoom === false && scope.enablePan === false ) return; + handleTouchMoveDollyPan( event ); + scope.update(); + break; + + case STATE.TOUCH_DOLLY_ROTATE: + if ( scope.enableZoom === false && scope.enableRotate === false ) return; + handleTouchMoveDollyRotate( event ); + scope.update(); + break; + + default: + state = STATE.NONE; + + } + + } + + function onTouchEnd( event ) { + + if ( scope.enabled === false ) return; + handleTouchEnd( event ); + scope.dispatchEvent( endEvent ); + state = STATE.NONE; + + } + + function onContextMenu( event ) { + + if ( scope.enabled === false ) return; + event.preventDefault(); + + } // + + + scope.domElement.addEventListener( 'contextmenu', onContextMenu, false ); + scope.domElement.addEventListener( 'mousedown', onMouseDown, false ); + scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); + scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); + scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); + scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); + scope.domElement.addEventListener( 'keydown', onKeyDown, false ); // make sure element can receive keys. + + if ( scope.domElement.tabIndex === - 1 ) { + + scope.domElement.tabIndex = 0; + + } // force an update at start + + + this.object.lookAt( scope.target ); + this.update(); + this.saveState(); + + }; + + CameraControls.prototype = Object.create( THREE.EventDispatcher.prototype ); + CameraControls.prototype.constructor = CameraControls; // OrbitControls maintains the "up" direction, camera.up (+Y by default). + // + // Orbit - left mouse / touch: one-finger move + // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish + // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + + var OrbitControls = function ( object, domElement ) { + + CameraControls.call( this, object, domElement ); + this.mouseButtons.LEFT = THREE.MOUSE.ROTATE; + this.mouseButtons.RIGHT = THREE.MOUSE.PAN; + this.touches.ONE = THREE.TOUCH.ROTATE; + this.touches.TWO = THREE.TOUCH.DOLLY_PAN; + + }; + + OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); + OrbitControls.prototype.constructor = OrbitControls; // MapControls maintains the "up" direction, camera.up (+Y by default) + // + // Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate + // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish + // Pan - left mouse, or left right + ctrl/meta/shiftKey, or arrow keys / touch: one-finger move + + var MapControls = function ( object, domElement ) { + + CameraControls.call( this, object, domElement ); + this.mouseButtons.LEFT = THREE.MOUSE.PAN; + this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; + this.touches.ONE = THREE.TOUCH.PAN; + this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; + + }; + + MapControls.prototype = Object.create( THREE.EventDispatcher.prototype ); + MapControls.prototype.constructor = MapControls; // TrackballControls allows the camera to rotate over the polls and does not maintain camera.up + // + // Orbit - left mouse / touch: one-finger move + // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish + // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move + + var TrackballControls = function ( object, domElement ) { + + CameraControls.call( this, object, domElement ); + this.trackball = true; + this.screenSpacePanning = true; + this.autoRotate = false; + this.mouseButtons.LEFT = THREE.MOUSE.ROTATE; + this.mouseButtons.RIGHT = THREE.MOUSE.PAN; + this.touches.ONE = THREE.TOUCH.ROTATE; + this.touches.TWO = THREE.TOUCH.DOLLY_PAN; + + }; + + TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); + TrackballControls.prototype.constructor = TrackballControls; + + THREE.CameraControls = CameraControls; + THREE.MapControls = MapControls; + THREE.OrbitControls = OrbitControls; + THREE.TrackballControls = TrackballControls; + +} )(); diff --git a/examples/js/csm/CSM.js b/examples/js/csm/CSM.js new file mode 100644 index 00000000000000..13771bc82b43d4 --- /dev/null +++ b/examples/js/csm/CSM.js @@ -0,0 +1,382 @@ +( function () { + + const _cameraToLightMatrix = new THREE.Matrix4(); + + const _lightSpaceFrustum = new THREE.Frustum(); + + const _center = new THREE.Vector3(); + + const _bbox = new THREE.Box3(); + + const _uniformArray = []; + const _logArray = []; + class CSM { + + constructor( data ) { + + data = data || {}; + this.camera = data.camera; + this.parent = data.parent; + this.cascades = data.cascades || 3; + this.maxFar = data.maxFar || 100000; + this.mode = data.mode || 'practical'; + this.shadowMapSize = data.shadowMapSize || 2048; + this.shadowBias = data.shadowBias || 0.000001; + this.lightDirection = data.lightDirection || new THREE.Vector3( 1, - 1, 1 ).normalize(); + this.lightIntensity = data.lightIntensity || 1; + this.lightNear = data.lightNear || 1; + this.lightFar = data.lightFar || 2000; + this.lightMargin = data.lightMargin || 200; + this.customSplitsCallback = data.customSplitsCallback; + this.fade = false; + this.mainFrustum = new THREE.Frustum(); + this.frustums = []; + this.breaks = []; + this.lights = []; + this.shaders = new Map(); + this.createLights(); + this.updateFrustums(); + this.injectInclude(); + + } + + createLights() { + + for ( let i = 0; i < this.cascades; i ++ ) { + + const light = new THREE.DirectionalLight( 0xffffff, this.lightIntensity ); + light.castShadow = true; + light.shadow.mapSize.width = this.shadowMapSize; + light.shadow.mapSize.height = this.shadowMapSize; + light.shadow.camera.near = this.lightNear; + light.shadow.camera.far = this.lightFar; + light.shadow.bias = this.shadowBias; + this.parent.add( light ); + this.parent.add( light.target ); + this.lights.push( light ); + + } + + } + + initCascades() { + + const camera = this.camera; + camera.updateProjectionMatrix(); + this.mainFrustum.setFromProjectionMatrix( camera.projectionMatrix, this.maxFar ); + this.mainFrustum.split( this.breaks, this.frustums ); + + } + + updateShadowBounds() { + + const frustums = this.frustums; + + for ( let i = 0; i < frustums.length; i ++ ) { + + const light = this.lights[ i ]; + const shadowCam = light.shadow.camera; + const frustum = this.frustums[ i ]; // Get the two points that represent that furthest points on the frustum assuming + // that's either the diagonal across the far plane or the diagonal across the whole + // frustum itself. + + const nearVerts = frustum.vertices.near; + const farVerts = frustum.vertices.far; + const point1 = farVerts[ 0 ]; + let point2; + + if ( point1.distanceTo( farVerts[ 2 ] ) > point1.distanceTo( nearVerts[ 2 ] ) ) { + + point2 = farVerts[ 2 ]; + + } else { + + point2 = nearVerts[ 2 ]; + + } + + let squaredBBWidth = point1.distanceTo( point2 ); + + if ( this.fade ) { + + // expand the shadow extents by the fade margin if fade is enabled. + const camera = this.camera; + const far = Math.max( camera.far, this.maxFar ); + const linearDepth = frustum.vertices.far[ 0 ].z / ( far - camera.near ); + const margin = 0.25 * Math.pow( linearDepth, 2.0 ) * ( far - camera.near ); + squaredBBWidth += margin; + + } + + shadowCam.left = - squaredBBWidth / 2; + shadowCam.right = squaredBBWidth / 2; + shadowCam.top = squaredBBWidth / 2; + shadowCam.bottom = - squaredBBWidth / 2; + shadowCam.updateProjectionMatrix(); + + } + + } + + getBreaks() { + + const camera = this.camera; + const far = Math.min( camera.far, this.maxFar ); + this.breaks.length = 0; + + switch ( this.mode ) { + + case 'uniform': + uniformSplit( this.cascades, camera.near, far, this.breaks ); + break; + + case 'logarithmic': + logarithmicSplit( this.cascades, camera.near, far, this.breaks ); + break; + + case 'practical': + practicalSplit( this.cascades, camera.near, far, 0.5, this.breaks ); + break; + + case 'custom': + if ( this.customSplitsCallback === undefined ) console.error( 'CSM: Custom split scheme callback not defined.' ); + this.customSplitsCallback( this.cascades, camera.near, far, this.breaks ); + break; + + } + + function uniformSplit( amount, near, far, target ) { + + for ( let i = 1; i < amount; i ++ ) { + + target.push( ( near + ( far - near ) * i / amount ) / far ); + + } + + target.push( 1 ); + + } + + function logarithmicSplit( amount, near, far, target ) { + + for ( let i = 1; i < amount; i ++ ) { + + target.push( near * ( far / near ) ** ( i / amount ) / far ); + + } + + target.push( 1 ); + + } + + function practicalSplit( amount, near, far, lambda, target ) { + + _uniformArray.length = 0; + _logArray.length = 0; + logarithmicSplit( amount, near, far, _logArray ); + uniformSplit( amount, near, far, _uniformArray ); + + for ( let i = 1; i < amount; i ++ ) { + + target.push( THREE.MathUtils.lerp( _uniformArray[ i - 1 ], _logArray[ i - 1 ], lambda ) ); + + } + + target.push( 1 ); + + } + + } + + update() { + + const camera = this.camera; + const frustums = this.frustums; + + for ( let i = 0; i < frustums.length; i ++ ) { + + const light = this.lights[ i ]; + const shadowCam = light.shadow.camera; + const texelWidth = ( shadowCam.right - shadowCam.left ) / this.shadowMapSize; + const texelHeight = ( shadowCam.top - shadowCam.bottom ) / this.shadowMapSize; + light.shadow.camera.updateMatrixWorld( true ); + + _cameraToLightMatrix.multiplyMatrices( light.shadow.camera.matrixWorldInverse, camera.matrixWorld ); + + frustums[ i ].toSpace( _cameraToLightMatrix, _lightSpaceFrustum ); + const nearVerts = _lightSpaceFrustum.vertices.near; + const farVerts = _lightSpaceFrustum.vertices.far; + + _bbox.makeEmpty(); + + for ( let j = 0; j < 4; j ++ ) { + + _bbox.expandByPoint( nearVerts[ j ] ); + + _bbox.expandByPoint( farVerts[ j ] ); + + } + + _bbox.getCenter( _center ); + + _center.z = _bbox.max.z + this.lightMargin; + _center.x = Math.floor( _center.x / texelWidth ) * texelWidth; + _center.y = Math.floor( _center.y / texelHeight ) * texelHeight; + + _center.applyMatrix4( light.shadow.camera.matrixWorld ); + + light.position.copy( _center ); + light.target.position.copy( _center ); + light.target.position.x += this.lightDirection.x; + light.target.position.y += this.lightDirection.y; + light.target.position.z += this.lightDirection.z; + + } + + } + + injectInclude() { + + THREE.ShaderChunk.lights_fragment_begin = THREE.CSMShader.lights_fragment_begin; + THREE.ShaderChunk.lights_pars_begin = THREE.CSMShader.lights_pars_begin; + + } + + setupMaterial( material ) { + + material.defines = material.defines || {}; + material.defines.USE_CSM = 1; + material.defines.CSM_CASCADES = this.cascades; + + if ( this.fade ) { + + material.defines.CSM_FADE = ''; + + } + + const breaksVec2 = []; + const scope = this; + const shaders = this.shaders; + + material.onBeforeCompile = function ( shader ) { + + const far = Math.min( scope.camera.far, scope.maxFar ); + scope.getExtendedBreaks( breaksVec2 ); + shader.uniforms.CSM_cascades = { + value: breaksVec2 + }; + shader.uniforms.cameraNear = { + value: scope.camera.near + }; + shader.uniforms.shadowFar = { + value: far + }; + shaders.set( material, shader ); + + }; + + shaders.set( material, null ); + + } + + updateUniforms() { + + const far = Math.min( this.camera.far, this.maxFar ); + const shaders = this.shaders; + shaders.forEach( function ( shader, material ) { + + if ( shader !== null ) { + + const uniforms = shader.uniforms; + this.getExtendedBreaks( uniforms.CSM_cascades.value ); + uniforms.cameraNear.value = this.camera.near; + uniforms.shadowFar.value = far; + + } + + if ( ! this.fade && 'CSM_FADE' in material.defines ) { + + delete material.defines.CSM_FADE; + material.needsUpdate = true; + + } else if ( this.fade && ! ( 'CSM_FADE' in material.defines ) ) { + + material.defines.CSM_FADE = ''; + material.needsUpdate = true; + + } + + }, this ); + + } + + getExtendedBreaks( target ) { + + while ( target.length < this.breaks.length ) { + + target.push( new THREE.Vector2() ); + + } + + target.length = this.breaks.length; + + for ( let i = 0; i < this.cascades; i ++ ) { + + const amount = this.breaks[ i ]; + const prev = this.breaks[ i - 1 ] || 0; + target[ i ].x = prev; + target[ i ].y = amount; + + } + + } + + updateFrustums() { + + this.getBreaks(); + this.initCascades(); + this.updateShadowBounds(); + this.updateUniforms(); + + } + + remove() { + + for ( let i = 0; i < this.lights.length; i ++ ) { + + this.parent.remove( this.lights[ i ] ); + + } + + } + + dispose() { + + const shaders = this.shaders; + shaders.forEach( function ( shader, material ) { + + delete material.onBeforeCompile; + delete material.defines.USE_CSM; + delete material.defines.CSM_CASCADES; + delete material.defines.CSM_FADE; + + if ( shader !== null ) { + + delete shader.uniforms.CSM_cascades; + delete shader.uniforms.cameraNear; + delete shader.uniforms.shadowFar; + + } + + material.needsUpdate = true; + + } ); + shaders.clear(); + + } + + } + + THREE.CSM = CSM; + +} )(); diff --git a/examples/js/csm/CSMHelper.js b/examples/js/csm/CSMHelper.js new file mode 100644 index 00000000000000..df372b8058accf --- /dev/null +++ b/examples/js/csm/CSMHelper.js @@ -0,0 +1,145 @@ +( function () { + + class CSMHelper extends THREE.Group { + + constructor( csm ) { + + super(); + this.csm = csm; + this.displayFrustum = true; + this.displayPlanes = true; + this.displayShadowBounds = true; + const indices = 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 ] ); + const positions = new Float32Array( 24 ); + const frustumGeometry = new THREE.BufferGeometry(); + frustumGeometry.setIndex( new THREE.BufferAttribute( indices, 1 ) ); + frustumGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3, false ) ); + const frustumLines = new THREE.LineSegments( frustumGeometry, new THREE.LineBasicMaterial() ); + this.add( frustumLines ); + this.frustumLines = frustumLines; + this.cascadeLines = []; + this.cascadePlanes = []; + this.shadowLines = []; + + } + + updateVisibility() { + + const displayFrustum = this.displayFrustum; + const displayPlanes = this.displayPlanes; + const displayShadowBounds = this.displayShadowBounds; + const frustumLines = this.frustumLines; + const cascadeLines = this.cascadeLines; + const cascadePlanes = this.cascadePlanes; + const shadowLines = this.shadowLines; + + for ( let i = 0, l = cascadeLines.length; i < l; i ++ ) { + + const cascadeLine = cascadeLines[ i ]; + const cascadePlane = cascadePlanes[ i ]; + const shadowLineGroup = shadowLines[ i ]; + cascadeLine.visible = displayFrustum; + cascadePlane.visible = displayFrustum && displayPlanes; + shadowLineGroup.visible = displayShadowBounds; + + } + + frustumLines.visible = displayFrustum; + + } + + update() { + + const csm = this.csm; + const camera = csm.camera; + const cascades = csm.cascades; + const mainFrustum = csm.mainFrustum; + const frustums = csm.frustums; + const lights = csm.lights; + const frustumLines = this.frustumLines; + const frustumLinePositions = frustumLines.geometry.getAttribute( 'position' ); + const cascadeLines = this.cascadeLines; + const cascadePlanes = this.cascadePlanes; + const shadowLines = this.shadowLines; + this.position.copy( camera.position ); + this.quaternion.copy( camera.quaternion ); + this.scale.copy( camera.scale ); + this.updateMatrixWorld( true ); + + while ( cascadeLines.length > cascades ) { + + this.remove( cascadeLines.pop() ); + this.remove( cascadePlanes.pop() ); + this.remove( shadowLines.pop() ); + + } + + while ( cascadeLines.length < cascades ) { + + const cascadeLine = new THREE.Box3Helper( new THREE.Box3(), 0xffffff ); + const planeMat = new THREE.MeshBasicMaterial( { + transparent: true, + opacity: 0.1, + depthWrite: false, + side: THREE.DoubleSide + } ); + const cascadePlane = new THREE.Mesh( new THREE.PlaneGeometry(), planeMat ); + const shadowLineGroup = new THREE.Group(); + const shadowLine = new THREE.Box3Helper( new THREE.Box3(), 0xffff00 ); + shadowLineGroup.add( shadowLine ); + this.add( cascadeLine ); + this.add( cascadePlane ); + this.add( shadowLineGroup ); + cascadeLines.push( cascadeLine ); + cascadePlanes.push( cascadePlane ); + shadowLines.push( shadowLineGroup ); + + } + + for ( let i = 0; i < cascades; i ++ ) { + + const frustum = frustums[ i ]; + const light = lights[ i ]; + const shadowCam = light.shadow.camera; + const farVerts = frustum.vertices.far; + const cascadeLine = cascadeLines[ i ]; + const cascadePlane = cascadePlanes[ i ]; + const shadowLineGroup = shadowLines[ i ]; + const shadowLine = shadowLineGroup.children[ 0 ]; + cascadeLine.box.min.copy( farVerts[ 2 ] ); + cascadeLine.box.max.copy( farVerts[ 0 ] ); + cascadeLine.box.max.z += 1e-4; + cascadePlane.position.addVectors( farVerts[ 0 ], farVerts[ 2 ] ); + cascadePlane.position.multiplyScalar( 0.5 ); + cascadePlane.scale.subVectors( farVerts[ 0 ], farVerts[ 2 ] ); + cascadePlane.scale.z = 1e-4; + this.remove( shadowLineGroup ); + shadowLineGroup.position.copy( shadowCam.position ); + shadowLineGroup.quaternion.copy( shadowCam.quaternion ); + shadowLineGroup.scale.copy( shadowCam.scale ); + shadowLineGroup.updateMatrixWorld( true ); + this.attach( shadowLineGroup ); + shadowLine.box.min.set( shadowCam.bottom, shadowCam.left, - shadowCam.far ); + shadowLine.box.max.set( shadowCam.top, shadowCam.right, - shadowCam.near ); + + } + + const nearVerts = mainFrustum.vertices.near; + const farVerts = mainFrustum.vertices.far; + frustumLinePositions.setXYZ( 0, farVerts[ 0 ].x, farVerts[ 0 ].y, farVerts[ 0 ].z ); + frustumLinePositions.setXYZ( 1, farVerts[ 3 ].x, farVerts[ 3 ].y, farVerts[ 3 ].z ); + frustumLinePositions.setXYZ( 2, farVerts[ 2 ].x, farVerts[ 2 ].y, farVerts[ 2 ].z ); + frustumLinePositions.setXYZ( 3, farVerts[ 1 ].x, farVerts[ 1 ].y, farVerts[ 1 ].z ); + frustumLinePositions.setXYZ( 4, nearVerts[ 0 ].x, nearVerts[ 0 ].y, nearVerts[ 0 ].z ); + frustumLinePositions.setXYZ( 5, nearVerts[ 3 ].x, nearVerts[ 3 ].y, nearVerts[ 3 ].z ); + frustumLinePositions.setXYZ( 6, nearVerts[ 2 ].x, nearVerts[ 2 ].y, nearVerts[ 2 ].z ); + frustumLinePositions.setXYZ( 7, nearVerts[ 1 ].x, nearVerts[ 1 ].y, nearVerts[ 1 ].z ); + frustumLinePositions.needsUpdate = true; + + } + + } + + THREE.CSMHelper = CSMHelper; + +} )(); diff --git a/examples/js/csm/CSMShader.js b/examples/js/csm/CSMShader.js new file mode 100644 index 00000000000000..9993a92814b492 --- /dev/null +++ b/examples/js/csm/CSMShader.js @@ -0,0 +1,241 @@ +( function () { + + const CSMShader = { + lights_fragment_begin: + /* glsl */ + ` +GeometricContext geometry; + +geometry.position = - vViewPosition; +geometry.normal = normal; +geometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition ); + +#ifdef CLEARCOAT + + geometry.clearcoatNormal = clearcoatNormal; + +#endif + +IncidentLight directLight; + +#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct ) + + PointLight pointLight; + #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0 + PointLightShadow pointLightShadow; + #endif + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) { + + pointLight = pointLights[ i ]; + + getPointDirectLightIrradiance( pointLight, geometry, directLight ); + + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) + pointLightShadow = pointLightShadows[ i ]; + directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0; + #endif + + RE_Direct( directLight, geometry, material, reflectedLight ); + + } + #pragma unroll_loop_end + +#endif + +#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct ) + + SpotLight spotLight; + #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLightShadow; + #endif + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) { + + spotLight = spotLights[ i ]; + + getSpotDirectLightIrradiance( spotLight, geometry, directLight ); + + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + spotLightShadow = spotLightShadows[ i ]; + directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0; + #endif + + RE_Direct( directLight, geometry, material, reflectedLight ); + + } + #pragma unroll_loop_end + +#endif + +#if ( NUM_DIR_LIGHTS > 0) && defined( RE_Direct ) && defined( USE_CSM ) && defined( CSM_CASCADES ) + + DirectionalLight directionalLight; + float linearDepth = (vViewPosition.z) / (shadowFar - cameraNear); + #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLightShadow; + #endif + + #if defined( USE_SHADOWMAP ) && defined( CSM_FADE ) + vec2 cascade; + float cascadeCenter; + float closestEdge; + float margin; + float csmx; + float csmy; + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { + + directionalLight = directionalLights[ i ]; + getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight ); + + // NOTE: Depth gets larger away from the camera. + // cascade.x is closer, cascade.y is further + cascade = CSM_cascades[ i ]; + cascadeCenter = ( cascade.x + cascade.y ) / 2.0; + closestEdge = linearDepth < cascadeCenter ? cascade.x : cascade.y; + margin = 0.25 * pow( closestEdge, 2.0 ); + csmx = cascade.x - margin / 2.0; + csmy = cascade.y + margin / 2.0; + if( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS && linearDepth >= csmx && ( linearDepth < csmy || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 ) ) { + + float dist = min( linearDepth - csmx, csmy - linearDepth ); + float ratio = clamp( dist / margin, 0.0, 1.0 ); + if( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) { + + vec3 prevColor = directLight.color; + directionalLightShadow = directionalLightShadows[ i ]; + directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + + bool shouldFadeLastCascade = UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth > cascadeCenter; + directLight.color = mix( prevColor, directLight.color, shouldFadeLastCascade ? ratio : 1.0 ); + + } + + ReflectedLight prevLight = reflectedLight; + RE_Direct( directLight, geometry, material, reflectedLight ); + + bool shouldBlend = UNROLLED_LOOP_INDEX != CSM_CASCADES - 1 || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth < cascadeCenter; + float blendRatio = shouldBlend ? ratio : 1.0; + + reflectedLight.directDiffuse = mix( prevLight.directDiffuse, reflectedLight.directDiffuse, blendRatio ); + reflectedLight.directSpecular = mix( prevLight.directSpecular, reflectedLight.directSpecular, blendRatio ); + reflectedLight.indirectDiffuse = mix( prevLight.indirectDiffuse, reflectedLight.indirectDiffuse, blendRatio ); + reflectedLight.indirectSpecular = mix( prevLight.indirectSpecular, reflectedLight.indirectSpecular, blendRatio ); + + } + + } + #pragma unroll_loop_end + #else + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { + + directionalLight = directionalLights[ i ]; + getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight ); + + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) + + directionalLightShadow = directionalLightShadows[ i ]; + if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y) directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + + #endif + + if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && (linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1)) RE_Direct( directLight, geometry, material, reflectedLight ); + + } + #pragma unroll_loop_end + + #endif + +#endif + + +#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct ) && !defined( USE_CSM ) && !defined( CSM_CASCADES ) + + DirectionalLight directionalLight; + #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLightShadow; + #endif + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { + + directionalLight = directionalLights[ i ]; + + getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight ); + + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) + directionalLightShadow = directionalLightShadows[ i ]; + directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + #endif + + RE_Direct( directLight, geometry, material, reflectedLight ); + + } + #pragma unroll_loop_end + +#endif + +#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea ) + + RectAreaLight rectAreaLight; + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) { + + rectAreaLight = rectAreaLights[ i ]; + RE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight ); + + } + #pragma unroll_loop_end + +#endif + +#if defined( RE_IndirectDiffuse ) + + vec3 iblIrradiance = vec3( 0.0 ); + + vec3 irradiance = getAmbientLightIrradiance( ambientLightColor ); + + irradiance += getLightProbeIrradiance( lightProbe, geometry ); + + #if ( NUM_HEMI_LIGHTS > 0 ) + + #pragma unroll_loop_start + for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) { + + irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry ); + + } + #pragma unroll_loop_end + + #endif + +#endif + +#if defined( RE_IndirectSpecular ) + + vec3 radiance = vec3( 0.0 ); + vec3 clearcoatRadiance = vec3( 0.0 ); + +#endif +`, + lights_pars_begin: + /* glsl */ + ` +#if defined( USE_CSM ) && defined( CSM_CASCADES ) +uniform vec2 CSM_cascades[CSM_CASCADES]; +uniform float cameraNear; +uniform float shadowFar; +#endif + ` + THREE.ShaderChunk.lights_pars_begin + }; + + THREE.CSMShader = CSMShader; + +} )(); diff --git a/examples/js/csm/Frustum.js b/examples/js/csm/Frustum.js new file mode 100644 index 00000000000000..7f324aab4b3b2d --- /dev/null +++ b/examples/js/csm/Frustum.js @@ -0,0 +1,133 @@ +( function () { + + const inverseProjectionMatrix = new THREE.Matrix4(); + + class Frustum { + + constructor( data ) { + + data = data || {}; + this.vertices = { + near: [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ], + far: [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ] + }; + + if ( data.projectionMatrix !== undefined ) { + + this.setFromProjectionMatrix( data.projectionMatrix, data.maxFar || 10000 ); + + } + + } + + setFromProjectionMatrix( projectionMatrix, maxFar ) { + + const isOrthographic = projectionMatrix.elements[ 2 * 4 + 3 ] === 0; + inverseProjectionMatrix.copy( projectionMatrix ).invert(); // 3 --- 0 vertices.near/far order + // | | + // 2 --- 1 + // clip space spans from [-1, 1] + + this.vertices.near[ 0 ].set( 1, 1, - 1 ); + this.vertices.near[ 1 ].set( 1, - 1, - 1 ); + this.vertices.near[ 2 ].set( - 1, - 1, - 1 ); + this.vertices.near[ 3 ].set( - 1, 1, - 1 ); + this.vertices.near.forEach( function ( v ) { + + v.applyMatrix4( inverseProjectionMatrix ); + + } ); + this.vertices.far[ 0 ].set( 1, 1, 1 ); + this.vertices.far[ 1 ].set( 1, - 1, 1 ); + this.vertices.far[ 2 ].set( - 1, - 1, 1 ); + this.vertices.far[ 3 ].set( - 1, 1, 1 ); + this.vertices.far.forEach( function ( v ) { + + v.applyMatrix4( inverseProjectionMatrix ); + const absZ = Math.abs( v.z ); + + if ( isOrthographic ) { + + v.z *= Math.min( maxFar / absZ, 1.0 ); + + } else { + + v.multiplyScalar( Math.min( maxFar / absZ, 1.0 ) ); + + } + + } ); + return this.vertices; + + } + + split( breaks, target ) { + + while ( breaks.length > target.length ) { + + target.push( new Frustum() ); + + } + + target.length = breaks.length; + + for ( let i = 0; i < breaks.length; i ++ ) { + + const cascade = target[ i ]; + + if ( i === 0 ) { + + for ( let j = 0; j < 4; j ++ ) { + + cascade.vertices.near[ j ].copy( this.vertices.near[ j ] ); + + } + + } else { + + for ( let j = 0; j < 4; j ++ ) { + + cascade.vertices.near[ j ].lerpVectors( this.vertices.near[ j ], this.vertices.far[ j ], breaks[ i - 1 ] ); + + } + + } + + if ( i === breaks - 1 ) { + + for ( let j = 0; j < 4; j ++ ) { + + cascade.vertices.far[ j ].copy( this.vertices.far[ j ] ); + + } + + } else { + + for ( let j = 0; j < 4; j ++ ) { + + cascade.vertices.far[ j ].lerpVectors( this.vertices.near[ j ], this.vertices.far[ j ], breaks[ i ] ); + + } + + } + + } + + } + + toSpace( cameraMatrix, target ) { + + for ( var i = 0; i < 4; i ++ ) { + + target.vertices.near[ i ].copy( this.vertices.near[ i ] ).applyMatrix4( cameraMatrix ); + target.vertices.far[ i ].copy( this.vertices.far[ i ] ).applyMatrix4( cameraMatrix ); + + } + + } + + } + + THREE.Frustum = Frustum; + +} )(); diff --git a/examples/js/curves/CurveExtras.js b/examples/js/curves/CurveExtras.js index fa697c1bbd536c..793fba841f9f2a 100644 --- a/examples/js/curves/CurveExtras.js +++ b/examples/js/curves/CurveExtras.js @@ -1,4 +1,6 @@ -/** +( function () { + + /** * A bunch of parametric curves * * Formulas collected from various sources @@ -9,402 +11,328 @@ * http://www.mi.sanu.ac.rs/vismath/taylorapril2011/Taylor.pdf * https://prideout.net/blog/old/blog/index.html@p=44.html */ - -THREE.Curves = ( function () { - // GrannyKnot - function GrannyKnot() { - - THREE.Curve.call( this ); - - } - - GrannyKnot.prototype = Object.create( THREE.Curve.prototype ); - GrannyKnot.prototype.constructor = GrannyKnot; - - GrannyKnot.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new THREE.Vector3(); - - t = 2 * Math.PI * t; - - var x = - 0.22 * Math.cos( t ) - 1.28 * Math.sin( t ) - 0.44 * Math.cos( 3 * t ) - 0.78 * Math.sin( 3 * t ); - var y = - 0.1 * Math.cos( 2 * t ) - 0.27 * Math.sin( 2 * t ) + 0.38 * Math.cos( 4 * t ) + 0.46 * Math.sin( 4 * t ); - var z = 0.7 * Math.cos( 3 * t ) - 0.4 * Math.sin( 3 * t ); - - return point.set( x, y, z ).multiplyScalar( 20 ); - - }; - - // HeartCurve - - function HeartCurve( scale ) { - - THREE.Curve.call( this ); - - this.scale = ( scale === undefined ) ? 5 : scale; - - } - - HeartCurve.prototype = Object.create( THREE.Curve.prototype ); - HeartCurve.prototype.constructor = HeartCurve; - - HeartCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new THREE.Vector3(); - - t *= 2 * Math.PI; - - var x = 16 * Math.pow( Math.sin( t ), 3 ); - var y = 13 * Math.cos( t ) - 5 * Math.cos( 2 * t ) - 2 * Math.cos( 3 * t ) - Math.cos( 4 * t ); - var z = 0; - - return point.set( x, y, z ).multiplyScalar( this.scale ); - - }; - - // Viviani's Curve - - function VivianiCurve( scale ) { + class GrannyKnot extends THREE.Curve { - THREE.Curve.call( this ); + getPoint( t, optionalTarget = new THREE.Vector3() ) { - this.scale = ( scale === undefined ) ? 70 : scale; + const point = optionalTarget; + t = 2 * Math.PI * t; + const x = - 0.22 * Math.cos( t ) - 1.28 * Math.sin( t ) - 0.44 * Math.cos( 3 * t ) - 0.78 * Math.sin( 3 * t ); + const y = - 0.1 * Math.cos( 2 * t ) - 0.27 * Math.sin( 2 * t ) + 0.38 * Math.cos( 4 * t ) + 0.46 * Math.sin( 4 * t ); + const z = 0.7 * Math.cos( 3 * t ) - 0.4 * Math.sin( 3 * t ); + return point.set( x, y, z ).multiplyScalar( 20 ); - } - - VivianiCurve.prototype = Object.create( THREE.Curve.prototype ); - VivianiCurve.prototype.constructor = VivianiCurve; - - VivianiCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new THREE.Vector3(); - - t = t * 4 * Math.PI; // normalized to 0..1 - var a = this.scale / 2; + } - var x = a * ( 1 + Math.cos( t ) ); - var y = a * Math.sin( t ); - var z = 2 * a * Math.sin( t / 2 ); + } // HeartCurve - return point.set( x, y, z ); - }; + class HeartCurve extends THREE.Curve { - // KnotCurve + constructor( scale = 5 ) { - function KnotCurve() { + super(); + this.scale = scale; - THREE.Curve.call( this ); + } - } + getPoint( t, optionalTarget = new THREE.Vector3() ) { - KnotCurve.prototype = Object.create( THREE.Curve.prototype ); - KnotCurve.prototype.constructor = KnotCurve; + const point = optionalTarget; + t *= 2 * Math.PI; + const x = 16 * Math.pow( Math.sin( t ), 3 ); + const y = 13 * Math.cos( t ) - 5 * Math.cos( 2 * t ) - 2 * Math.cos( 3 * t ) - Math.cos( 4 * t ); + const z = 0; + return point.set( x, y, z ).multiplyScalar( this.scale ); - KnotCurve.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new THREE.Vector3(); + } // Viviani's THREE.Curve - t *= 2 * Math.PI; - var R = 10; - var s = 50; + class VivianiCurve extends THREE.Curve { - var x = s * Math.sin( t ); - var y = Math.cos( t ) * ( R + s * Math.cos( t ) ); - var z = Math.sin( t ) * ( R + s * Math.cos( t ) ); + constructor( scale = 70 ) { - return point.set( x, y, z ); + super(); + this.scale = scale; - }; + } - // HelixCurve + getPoint( t, optionalTarget = new THREE.Vector3() ) { - function HelixCurve() { + const point = optionalTarget; + t = t * 4 * Math.PI; // normalized to 0..1 - THREE.Curve.call( this ); + const a = this.scale / 2; + const x = a * ( 1 + Math.cos( t ) ); + const y = a * Math.sin( t ); + const z = 2 * a * Math.sin( t / 2 ); + return point.set( x, y, z ); - } + } - HelixCurve.prototype = Object.create( THREE.Curve.prototype ); - HelixCurve.prototype.constructor = HelixCurve; + } // KnotCurve - HelixCurve.prototype.getPoint = function ( t, optionalTarget ) { - var point = optionalTarget || new THREE.Vector3(); + class KnotCurve extends THREE.Curve { - var a = 30; // radius - var b = 150; // height + getPoint( t, optionalTarget = new THREE.Vector3() ) { - var t2 = 2 * Math.PI * t * b / 30; + const point = optionalTarget; + t *= 2 * Math.PI; + const R = 10; + const s = 50; + const x = s * Math.sin( t ); + const y = Math.cos( t ) * ( R + s * Math.cos( t ) ); + const z = Math.sin( t ) * ( R + s * Math.cos( t ) ); + return point.set( x, y, z ); - var x = Math.cos( t2 ) * a; - var y = Math.sin( t2 ) * a; - var z = b * t; + } - return point.set( x, y, z ); + } // HelixCurve - }; - // TrefoilKnot + class HelixCurve extends THREE.Curve { - function TrefoilKnot( scale ) { + getPoint( t, optionalTarget = new THREE.Vector3() ) { - THREE.Curve.call( this ); + const point = optionalTarget; + const a = 30; // radius - this.scale = ( scale === undefined ) ? 10 : scale; + const b = 150; // height - } + const t2 = 2 * Math.PI * t * b / 30; + const x = Math.cos( t2 ) * a; + const y = Math.sin( t2 ) * a; + const z = b * t; + return point.set( x, y, z ); - TrefoilKnot.prototype = Object.create( THREE.Curve.prototype ); - TrefoilKnot.prototype.constructor = TrefoilKnot; + } - TrefoilKnot.prototype.getPoint = function ( t, optionalTarget ) { + } // TrefoilKnot - var point = optionalTarget || new THREE.Vector3(); - t *= Math.PI * 2; + class TrefoilKnot extends THREE.Curve { - var x = ( 2 + Math.cos( 3 * t ) ) * Math.cos( 2 * t ); - var y = ( 2 + Math.cos( 3 * t ) ) * Math.sin( 2 * t ); - var z = Math.sin( 3 * t ); + constructor( scale = 10 ) { - return point.set( x, y, z ).multiplyScalar( this.scale ); + super(); + this.scale = scale; - }; + } - // TorusKnot + getPoint( t, optionalTarget = new THREE.Vector3() ) { - function TorusKnot( scale ) { + const point = optionalTarget; + t *= Math.PI * 2; + const x = ( 2 + Math.cos( 3 * t ) ) * Math.cos( 2 * t ); + const y = ( 2 + Math.cos( 3 * t ) ) * Math.sin( 2 * t ); + const z = Math.sin( 3 * t ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - THREE.Curve.call( this ); + } - this.scale = ( scale === undefined ) ? 10 : scale; + } // TorusKnot - } - TorusKnot.prototype = Object.create( THREE.Curve.prototype ); - TorusKnot.prototype.constructor = TorusKnot; + class TorusKnot extends THREE.Curve { - TorusKnot.prototype.getPoint = function ( t, optionalTarget ) { + constructor( scale = 10 ) { - var point = optionalTarget || new THREE.Vector3(); + super(); + this.scale = scale; - var p = 3; - var q = 4; + } - t *= Math.PI * 2; + getPoint( t, optionalTarget = new THREE.Vector3() ) { - var x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ); - var y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ); - var z = Math.sin( q * t ); + const point = optionalTarget; + const p = 3; + const q = 4; + t *= Math.PI * 2; + const x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ); + const y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ); + const z = Math.sin( q * t ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - return point.set( x, y, z ).multiplyScalar( this.scale ); + } - }; + } // CinquefoilKnot - // CinquefoilKnot - function CinquefoilKnot( scale ) { + class CinquefoilKnot extends THREE.Curve { - THREE.Curve.call( this ); + constructor( scale = 10 ) { - this.scale = ( scale === undefined ) ? 10 : scale; + super(); + this.scale = scale; - } + } - CinquefoilKnot.prototype = Object.create( THREE.Curve.prototype ); - CinquefoilKnot.prototype.constructor = CinquefoilKnot; + getPoint( t, optionalTarget = new THREE.Vector3() ) { - CinquefoilKnot.prototype.getPoint = function ( t, optionalTarget ) { + const point = optionalTarget; + const p = 2; + const q = 5; + t *= Math.PI * 2; + const x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ); + const y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ); + const z = Math.sin( q * t ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - var point = optionalTarget || new THREE.Vector3(); + } - var p = 2; - var q = 5; + } // TrefoilPolynomialKnot - t *= Math.PI * 2; - var x = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ); - var y = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ); - var z = Math.sin( q * t ); + class TrefoilPolynomialKnot extends THREE.Curve { - return point.set( x, y, z ).multiplyScalar( this.scale ); + constructor( scale = 10 ) { - }; + super(); + this.scale = scale; - // TrefoilPolynomialKnot + } - function TrefoilPolynomialKnot( scale ) { + getPoint( t, optionalTarget = new THREE.Vector3() ) { - THREE.Curve.call( this ); + const point = optionalTarget; + t = t * 4 - 2; + const x = Math.pow( t, 3 ) - 3 * t; + const y = Math.pow( t, 4 ) - 4 * t * t; + const z = 1 / 5 * Math.pow( t, 5 ) - 2 * t; + return point.set( x, y, z ).multiplyScalar( this.scale ); - this.scale = ( scale === undefined ) ? 10 : scale; + } } - TrefoilPolynomialKnot.prototype = Object.create( THREE.Curve.prototype ); - TrefoilPolynomialKnot.prototype.constructor = TrefoilPolynomialKnot; - - TrefoilPolynomialKnot.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new THREE.Vector3(); - - t = t * 4 - 2; - - var x = Math.pow( t, 3 ) - 3 * t; - var y = Math.pow( t, 4 ) - 4 * t * t; - var z = 1 / 5 * Math.pow( t, 5 ) - 2 * t; + function scaleTo( x, y, t ) { - return point.set( x, y, z ).multiplyScalar( this.scale ); - - }; - - var scaleTo = function ( x, y, t ) { - - var r = y - x; + const r = y - x; return t * r + x; - }; - - // FigureEightPolynomialKnot - - function FigureEightPolynomialKnot( scale ) { - - THREE.Curve.call( this ); - - this.scale = ( scale === undefined ) ? 1 : scale; - - } - - FigureEightPolynomialKnot.prototype = Object.create( THREE.Curve.prototype ); - FigureEightPolynomialKnot.prototype.constructor = FigureEightPolynomialKnot; - - FigureEightPolynomialKnot.prototype.getPoint = function ( t, optionalTarget ) { + } // FigureEightPolynomialKnot - var point = optionalTarget || new THREE.Vector3(); - t = scaleTo( - 4, 4, t ); + class FigureEightPolynomialKnot extends THREE.Curve { - var x = 2 / 5 * t * ( t * t - 7 ) * ( t * t - 10 ); - var y = Math.pow( t, 4 ) - 13 * t * t; - var z = 1 / 10 * t * ( t * t - 4 ) * ( t * t - 9 ) * ( t * t - 12 ); + constructor( scale = 1 ) { - return point.set( x, y, z ).multiplyScalar( this.scale ); - - }; + super(); + this.scale = scale; - // DecoratedTorusKnot4a + } - function DecoratedTorusKnot4a( scale ) { + getPoint( t, optionalTarget = new THREE.Vector3() ) { - THREE.Curve.call( this ); + const point = optionalTarget; + t = scaleTo( - 4, 4, t ); + const x = 2 / 5 * t * ( t * t - 7 ) * ( t * t - 10 ); + const y = Math.pow( t, 4 ) - 13 * t * t; + const z = 1 / 10 * t * ( t * t - 4 ) * ( t * t - 9 ) * ( t * t - 12 ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - this.scale = ( scale === undefined ) ? 40 : scale; + } - } + } // DecoratedTorusKnot4a - DecoratedTorusKnot4a.prototype = Object.create( THREE.Curve.prototype ); - DecoratedTorusKnot4a.prototype.constructor = DecoratedTorusKnot4a; - DecoratedTorusKnot4a.prototype.getPoint = function ( t, optionalTarget ) { + class DecoratedTorusKnot4a extends THREE.Curve { - var point = optionalTarget || new THREE.Vector3(); + constructor( scale = 40 ) { - t *= Math.PI * 2; + super(); + this.scale = scale; - var x = Math.cos( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ); - var y = Math.sin( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ); - var z = 0.35 * Math.sin( 5 * t ); + } - return point.set( x, y, z ).multiplyScalar( this.scale ); + getPoint( t, optionalTarget = new THREE.Vector3() ) { - }; + const point = optionalTarget; + t *= Math.PI * 2; + const x = Math.cos( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ); + const y = Math.sin( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ); + const z = 0.35 * Math.sin( 5 * t ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - // DecoratedTorusKnot4b + } - function DecoratedTorusKnot4b( scale ) { + } // DecoratedTorusKnot4b - THREE.Curve.call( this ); - this.scale = ( scale === undefined ) ? 40 : scale; + class DecoratedTorusKnot4b extends THREE.Curve { - } + constructor( scale = 40 ) { - DecoratedTorusKnot4b.prototype = Object.create( THREE.Curve.prototype ); - DecoratedTorusKnot4b.prototype.constructor = DecoratedTorusKnot4b; + super(); + this.scale = scale; - DecoratedTorusKnot4b.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new THREE.Vector3(); + getPoint( t, optionalTarget = new THREE.Vector3() ) { - var fi = t * Math.PI * 2; + const point = optionalTarget; + const fi = t * Math.PI * 2; + const x = Math.cos( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ); + const y = Math.sin( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ); + const z = 0.2 * Math.sin( 9 * fi ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - var x = Math.cos( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ); - var y = Math.sin( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ); - var z = 0.2 * Math.sin( 9 * fi ); + } - return point.set( x, y, z ).multiplyScalar( this.scale ); + } // DecoratedTorusKnot5a - }; - // DecoratedTorusKnot5a + class DecoratedTorusKnot5a extends THREE.Curve { - function DecoratedTorusKnot5a( scale ) { + constructor( scale = 40 ) { - THREE.Curve.call( this ); + super(); + this.scale = scale; - this.scale = ( scale === undefined ) ? 40 : scale; + } - } + getPoint( t, optionalTarget = new THREE.Vector3() ) { - DecoratedTorusKnot5a.prototype = Object.create( THREE.Curve.prototype ); - DecoratedTorusKnot5a.prototype.constructor = DecoratedTorusKnot5a; + const point = optionalTarget; + const fi = t * Math.PI * 2; + const x = Math.cos( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ); + const y = Math.sin( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ); + const z = 0.2 * Math.sin( 20 * fi ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - DecoratedTorusKnot5a.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new THREE.Vector3(); + } // DecoratedTorusKnot5c - var fi = t * Math.PI * 2; - var x = Math.cos( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ); - var y = Math.sin( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ); - var z = 0.2 * Math.sin( 20 * fi ); + class DecoratedTorusKnot5c extends THREE.Curve { - return point.set( x, y, z ).multiplyScalar( this.scale ); + constructor( scale = 40 ) { - }; + super(); + this.scale = scale; - // DecoratedTorusKnot5c + } - function DecoratedTorusKnot5c( scale ) { + getPoint( t, optionalTarget = new THREE.Vector3() ) { - THREE.Curve.call( this ); + const point = optionalTarget; + const fi = t * Math.PI * 2; + const x = Math.cos( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ); + const y = Math.sin( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ); + const z = 0.35 * Math.sin( 15 * fi ); + return point.set( x, y, z ).multiplyScalar( this.scale ); - this.scale = ( scale === undefined ) ? 40 : scale; + } } - DecoratedTorusKnot5c.prototype = Object.create( THREE.Curve.prototype ); - DecoratedTorusKnot5c.prototype.constructor = DecoratedTorusKnot5c; - - DecoratedTorusKnot5c.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new THREE.Vector3(); - - var fi = t * Math.PI * 2; - - var x = Math.cos( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ); - var y = Math.sin( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ); - var z = 0.35 * Math.sin( 15 * fi ); - - return point.set( x, y, z ).multiplyScalar( this.scale ); - - }; - - return { + const Curves = { GrannyKnot: GrannyKnot, HeartCurve: HeartCurve, VivianiCurve: VivianiCurve, @@ -421,4 +349,6 @@ THREE.Curves = ( function () { DecoratedTorusKnot5c: DecoratedTorusKnot5c }; + THREE.Curves = Curves; + } )(); diff --git a/examples/js/curves/NURBSCurve.js b/examples/js/curves/NURBSCurve.js index 20f79dbe47ad20..21d0ceecaa31a7 100644 --- a/examples/js/curves/NURBSCurve.js +++ b/examples/js/curves/NURBSCurve.js @@ -1,66 +1,75 @@ -/** +( function () { + + /** * NURBS curve object * - * Derives from Curve, overriding getPoint and getTangent. + * Derives from THREE.Curve, overriding getPoint and getTangent. * * Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight. * **/ -THREE.NURBSCurve = function ( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */, startKnot /* index in knots */, endKnot /* index in knots */ ) { - - THREE.Curve.call( this ); - - this.degree = degree; - this.knots = knots; - this.controlPoints = []; - // Used by periodic NURBS to remove hidden spans - this.startKnot = startKnot || 0; - this.endKnot = endKnot || ( this.knots.length - 1 ); - for ( var i = 0; i < controlPoints.length; ++ i ) { + class NURBSCurve extends THREE.Curve { - // ensure Vector4 for control points - var point = controlPoints[ i ]; - this.controlPoints[ i ] = new THREE.Vector4( point.x, point.y, point.z, point.w ); + constructor( degree, knots + /* array of reals */ + , controlPoints + /* array of Vector(2|3|4) */ + , startKnot + /* index in knots */ + , endKnot + /* index in knots */ + ) { - } + super(); + this.degree = degree; + this.knots = knots; + this.controlPoints = []; // Used by periodic NURBS to remove hidden spans -}; + this.startKnot = startKnot || 0; + this.endKnot = endKnot || this.knots.length - 1; + for ( let i = 0; i < controlPoints.length; ++ i ) { -THREE.NURBSCurve.prototype = Object.create( THREE.Curve.prototype ); -THREE.NURBSCurve.prototype.constructor = THREE.NURBSCurve; + // ensure THREE.Vector4 for control points + const point = controlPoints[ i ]; + this.controlPoints[ i ] = new THREE.Vector4( point.x, point.y, point.z, point.w ); + } -THREE.NURBSCurve.prototype.getPoint = function ( t, optionalTarget ) { + } - var point = optionalTarget || new THREE.Vector3(); + getPoint( t, optionalTarget = new THREE.Vector3() ) { - var u = this.knots[ this.startKnot ] + t * ( this.knots[ this.endKnot ] - this.knots[ this.startKnot ] ); // linear mapping t->u + const point = optionalTarget; + const u = this.knots[ this.startKnot ] + t * ( this.knots[ this.endKnot ] - this.knots[ this.startKnot ] ); // linear mapping t->u + // following results in (wx, wy, wz, w) homogeneous point - // following results in (wx, wy, wz, w) homogeneous point - var hpoint = THREE.NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u ); + const hpoint = THREE.NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u ); - if ( hpoint.w != 1.0 ) { + if ( hpoint.w !== 1.0 ) { - // project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1) - hpoint.divideScalar( hpoint.w ); + // project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1) + hpoint.divideScalar( hpoint.w ); - } + } - return point.set( hpoint.x, hpoint.y, hpoint.z ); + return point.set( hpoint.x, hpoint.y, hpoint.z ); -}; + } + getTangent( t, optionalTarget = new THREE.Vector3() ) { -THREE.NURBSCurve.prototype.getTangent = function ( t, optionalTarget ) { + const tangent = optionalTarget; + const u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] ); + const ders = THREE.NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 ); + tangent.copy( ders[ 1 ] ).normalize(); + return tangent; - var tangent = optionalTarget || new THREE.Vector3(); + } - var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] ); - var ders = THREE.NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 ); - tangent.copy( ders[ 1 ] ).normalize(); + } - return tangent; + THREE.NURBSCurve = NURBSCurve; -}; +} )(); diff --git a/examples/js/curves/NURBSSurface.js b/examples/js/curves/NURBSSurface.js index f081e3c6602e5a..7c67c0fd06e536 100644 --- a/examples/js/curves/NURBSSurface.js +++ b/examples/js/curves/NURBSSurface.js @@ -1,46 +1,54 @@ -/** +( function () { + + /** * NURBS surface object * * Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight. **/ -THREE.NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) { + class NURBSSurface { - this.degree1 = degree1; - this.degree2 = degree2; - this.knots1 = knots1; - this.knots2 = knots2; - this.controlPoints = []; + constructor( degree1, degree2, knots1, knots2 + /* arrays of reals */ + , controlPoints + /* array^2 of Vector(2|3|4) */ + ) { - var len1 = knots1.length - degree1 - 1; - var len2 = knots2.length - degree2 - 1; + this.degree1 = degree1; + this.degree2 = degree2; + this.knots1 = knots1; + this.knots2 = knots2; + this.controlPoints = []; + const len1 = knots1.length - degree1 - 1; + const len2 = knots2.length - degree2 - 1; // ensure THREE.Vector4 for control points - // ensure Vector4 for control points - for ( var i = 0; i < len1; ++ i ) { + for ( let i = 0; i < len1; ++ i ) { - this.controlPoints[ i ] = []; - for ( var j = 0; j < len2; ++ j ) { + this.controlPoints[ i ] = []; - var point = controlPoints[ i ][ j ]; - this.controlPoints[ i ][ j ] = new THREE.Vector4( point.x, point.y, point.z, point.w ); + for ( let j = 0; j < len2; ++ j ) { - } + const point = controlPoints[ i ][ j ]; + this.controlPoints[ i ][ j ] = new THREE.Vector4( point.x, point.y, point.z, point.w ); - } + } -}; + } + } -THREE.NURBSSurface.prototype = { + getPoint( t1, t2, target ) { - constructor: THREE.NURBSSurface, + const u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u - getPoint: function ( t1, t2, target ) { + const v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u - var u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u - var v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u + THREE.NURBSUtils.calcSurfacePoint( this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v, target ); - THREE.NURBSUtils.calcSurfacePoint( this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v, target ); + } } -}; + + THREE.NURBSSurface = NURBSSurface; + +} )(); diff --git a/examples/js/curves/NURBSUtils.js b/examples/js/curves/NURBSUtils.js index aeedf5e29da487..e0f5ef58947619 100644 --- a/examples/js/curves/NURBSUtils.js +++ b/examples/js/curves/NURBSUtils.js @@ -1,470 +1,453 @@ -/** +( function () { + + /** * NURBS utils * * See NURBSCurve and NURBSSurface. **/ - -/************************************************************** + /************************************************************** * NURBS Utils **************************************************************/ -THREE.NURBSUtils = { + class NURBSUtils { - /* - Finds knot vector span. + /* + Finds knot vector span. + p : degree + u : parametric value + U : knot vector + returns the span + */ + static findSpan( p, u, U ) { - p : degree - u : parametric value - U : knot vector + const n = U.length - p - 1; - returns the span - */ - findSpan: function ( p, u, U ) { + if ( u >= U[ n ] ) { - var n = U.length - p - 1; + return n - 1; - if ( u >= U[ n ] ) { + } - return n - 1; + if ( u <= U[ p ] ) { - } + return p; - if ( u <= U[ p ] ) { + } - return p; + let low = p; + let high = n; + let mid = Math.floor( ( low + high ) / 2 ); - } + while ( u < U[ mid ] || u >= U[ mid + 1 ] ) { - var low = p; - var high = n; - var mid = Math.floor( ( low + high ) / 2 ); + if ( u < U[ mid ] ) { - while ( u < U[ mid ] || u >= U[ mid + 1 ] ) { + high = mid; - if ( u < U[ mid ] ) { + } else { - high = mid; + low = mid; - } else { + } - low = mid; + mid = Math.floor( ( low + high ) / 2 ); } - mid = Math.floor( ( low + high ) / 2 ); + return mid; } - - return mid; - - }, + /* + Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2 + span : span in which u lies + u : parametric point + p : degree + U : knot vector + returns array[p+1] with basis functions values. + */ - /* - Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2 + static calcBasisFunctions( span, u, p, U ) { - span : span in which u lies - u : parametric point - p : degree - U : knot vector + const N = []; + const left = []; + const right = []; + N[ 0 ] = 1.0; - returns array[p+1] with basis functions values. - */ - calcBasisFunctions: function ( span, u, p, U ) { + for ( let j = 1; j <= p; ++ j ) { - var N = []; - var left = []; - var right = []; - N[ 0 ] = 1.0; + left[ j ] = u - U[ span + 1 - j ]; + right[ j ] = U[ span + j ] - u; + let saved = 0.0; - for ( var j = 1; j <= p; ++ j ) { + for ( let r = 0; r < j; ++ r ) { - left[ j ] = u - U[ span + 1 - j ]; - right[ j ] = U[ span + j ] - u; + const rv = right[ r + 1 ]; + const lv = left[ j - r ]; + const temp = N[ r ] / ( rv + lv ); + N[ r ] = saved + rv * temp; + saved = lv * temp; - var saved = 0.0; - - for ( var r = 0; r < j; ++ r ) { - - var rv = right[ r + 1 ]; - var lv = left[ j - r ]; - var temp = N[ r ] / ( rv + lv ); - N[ r ] = saved + rv * temp; - saved = lv * temp; - - } + } - N[ j ] = saved; + N[ j ] = saved; - } + } - return N; + return N; - }, + } + /* + Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1. + p : degree of B-Spline + U : knot vector + P : control points (x, y, z, w) + u : parametric point + returns point for given u + */ - /* - Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1. + static calcBSplinePoint( p, U, P, u ) { - p : degree of B-Spline - U : knot vector - P : control points (x, y, z, w) - u : parametric point + const span = this.findSpan( p, u, U ); + const N = this.calcBasisFunctions( span, u, p, U ); + const C = new THREE.Vector4( 0, 0, 0, 0 ); - returns point for given u - */ - calcBSplinePoint: function ( p, U, P, u ) { + for ( let j = 0; j <= p; ++ j ) { - var span = this.findSpan( p, u, U ); - var N = this.calcBasisFunctions( span, u, p, U ); - var C = new THREE.Vector4( 0, 0, 0, 0 ); + const point = P[ span - p + j ]; + const Nj = N[ j ]; + const wNj = point.w * Nj; + C.x += point.x * wNj; + C.y += point.y * wNj; + C.z += point.z * wNj; + C.w += point.w * Nj; - for ( var j = 0; j <= p; ++ j ) { + } - var point = P[ span - p + j ]; - var Nj = N[ j ]; - var wNj = point.w * Nj; - C.x += point.x * wNj; - C.y += point.y * wNj; - C.z += point.z * wNj; - C.w += point.w * Nj; + return C; } + /* + Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3. + span : span in which u lies + u : parametric point + p : degree + n : number of derivatives to calculate + U : knot vector + returns array[n+1][p+1] with basis functions derivatives + */ - return C; - - }, + static calcBasisFunctionDerivatives( span, u, p, n, U ) { - /* - Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3. + const zeroArr = []; - span : span in which u lies - u : parametric point - p : degree - n : number of derivatives to calculate - U : knot vector + for ( let i = 0; i <= p; ++ i ) zeroArr[ i ] = 0.0; - returns array[n+1][p+1] with basis functions derivatives - */ - calcBasisFunctionDerivatives: function ( span, u, p, n, U ) { + const ders = []; - var zeroArr = []; - for ( var i = 0; i <= p; ++ i ) - zeroArr[ i ] = 0.0; + for ( let i = 0; i <= n; ++ i ) ders[ i ] = zeroArr.slice( 0 ); - var ders = []; - for ( var i = 0; i <= n; ++ i ) - ders[ i ] = zeroArr.slice( 0 ); + const ndu = []; - var ndu = []; - for ( var i = 0; i <= p; ++ i ) - ndu[ i ] = zeroArr.slice( 0 ); + for ( let i = 0; i <= p; ++ i ) ndu[ i ] = zeroArr.slice( 0 ); - ndu[ 0 ][ 0 ] = 1.0; + ndu[ 0 ][ 0 ] = 1.0; + const left = zeroArr.slice( 0 ); + const right = zeroArr.slice( 0 ); - var left = zeroArr.slice( 0 ); - var right = zeroArr.slice( 0 ); + for ( let j = 1; j <= p; ++ j ) { - for ( var j = 1; j <= p; ++ j ) { + left[ j ] = u - U[ span + 1 - j ]; + right[ j ] = U[ span + j ] - u; + let saved = 0.0; - left[ j ] = u - U[ span + 1 - j ]; - right[ j ] = U[ span + j ] - u; + for ( let r = 0; r < j; ++ r ) { - var saved = 0.0; + const rv = right[ r + 1 ]; + const lv = left[ j - r ]; + ndu[ j ][ r ] = rv + lv; + const temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ]; + ndu[ r ][ j ] = saved + rv * temp; + saved = lv * temp; - for ( var r = 0; r < j; ++ r ) { - - var rv = right[ r + 1 ]; - var lv = left[ j - r ]; - ndu[ j ][ r ] = rv + lv; + } - var temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ]; - ndu[ r ][ j ] = saved + rv * temp; - saved = lv * temp; + ndu[ j ][ j ] = saved; } - ndu[ j ][ j ] = saved; + for ( let j = 0; j <= p; ++ j ) { - } + ders[ 0 ][ j ] = ndu[ j ][ p ]; - for ( var j = 0; j <= p; ++ j ) { + } - ders[ 0 ][ j ] = ndu[ j ][ p ]; + for ( let r = 0; r <= p; ++ r ) { - } + let s1 = 0; + let s2 = 1; + const a = []; - for ( var r = 0; r <= p; ++ r ) { + for ( let i = 0; i <= p; ++ i ) { - var s1 = 0; - var s2 = 1; + a[ i ] = zeroArr.slice( 0 ); - var a = []; - for ( var i = 0; i <= p; ++ i ) { + } - a[ i ] = zeroArr.slice( 0 ); + a[ 0 ][ 0 ] = 1.0; - } + for ( let k = 1; k <= n; ++ k ) { - a[ 0 ][ 0 ] = 1.0; + let d = 0.0; + const rk = r - k; + const pk = p - k; - for ( var k = 1; k <= n; ++ k ) { + if ( r >= k ) { - var d = 0.0; - var rk = r - k; - var pk = p - k; + a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ]; + d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ]; - if ( r >= k ) { + } - a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ]; - d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ]; + const j1 = rk >= - 1 ? 1 : - rk; + const j2 = r - 1 <= pk ? k - 1 : p - r; - } + for ( let j = j1; j <= j2; ++ j ) { - var j1 = ( rk >= - 1 ) ? 1 : - rk; - var j2 = ( r - 1 <= pk ) ? k - 1 : p - r; + a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ]; + d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ]; - for ( var j = j1; j <= j2; ++ j ) { + } - a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ]; - d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ]; + if ( r <= pk ) { - } + a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ]; + d += a[ s2 ][ k ] * ndu[ r ][ pk ]; - if ( r <= pk ) { + } - a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ]; - d += a[ s2 ][ k ] * ndu[ r ][ pk ]; + ders[ k ][ r ] = d; + const j = s1; + s1 = s2; + s2 = j; } - ders[ k ][ r ] = d; - - var j = s1; - s1 = s2; - s2 = j; - } - } + let r = p; - var r = p; + for ( let k = 1; k <= n; ++ k ) { - for ( var k = 1; k <= n; ++ k ) { + for ( let j = 0; j <= p; ++ j ) { - for ( var j = 0; j <= p; ++ j ) { + ders[ k ][ j ] *= r; - ders[ k ][ j ] *= r; + } + + r *= p - k; } - r *= p - k; + return ders; } - - return ders; - - }, + /* + Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2. + p : degree + U : knot vector + P : control points + u : Parametric points + nd : number of derivatives + returns array[d+1] with derivatives + */ - /* - Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2. + static calcBSplineDerivatives( p, U, P, u, nd ) { - p : degree - U : knot vector - P : control points - u : Parametric points - nd : number of derivatives + const du = nd < p ? nd : p; + const CK = []; + const span = this.findSpan( p, u, U ); + const nders = this.calcBasisFunctionDerivatives( span, u, p, du, U ); + const Pw = []; - returns array[d+1] with derivatives - */ - calcBSplineDerivatives: function ( p, U, P, u, nd ) { + for ( let i = 0; i < P.length; ++ i ) { - var du = nd < p ? nd : p; - var CK = []; - var span = this.findSpan( p, u, U ); - var nders = this.calcBasisFunctionDerivatives( span, u, p, du, U ); - var Pw = []; - - for ( var i = 0; i < P.length; ++ i ) { - - var point = P[ i ].clone(); - var w = point.w; + const point = P[ i ].clone(); + const w = point.w; + point.x *= w; + point.y *= w; + point.z *= w; + Pw[ i ] = point; - point.x *= w; - point.y *= w; - point.z *= w; + } - Pw[ i ] = point; + for ( let k = 0; k <= du; ++ k ) { - } + const point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] ); - for ( var k = 0; k <= du; ++ k ) { + for ( let j = 1; j <= p; ++ j ) { - var point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] ); + point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) ); - for ( var j = 1; j <= p; ++ j ) { + } - point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) ); + CK[ k ] = point; } - CK[ k ] = point; + for ( let k = du + 1; k <= nd + 1; ++ k ) { - } + CK[ k ] = new THREE.Vector4( 0, 0, 0 ); - for ( var k = du + 1; k <= nd + 1; ++ k ) { + } - CK[ k ] = new THREE.Vector4( 0, 0, 0 ); + return CK; } + /* + Calculate "K over I" + returns k!/(i!(k-i)!) + */ - return CK; - }, + static calcKoverI( k, i ) { + let nom = 1; - /* - Calculate "K over I" + for ( let j = 2; j <= k; ++ j ) { - returns k!/(i!(k-i)!) - */ - calcKoverI: function ( k, i ) { + nom *= j; - var nom = 1; - - for ( var j = 2; j <= k; ++ j ) { + } - nom *= j; + let denom = 1; - } + for ( let j = 2; j <= i; ++ j ) { - var denom = 1; + denom *= j; - for ( var j = 2; j <= i; ++ j ) { + } - denom *= j; + for ( let j = 2; j <= k - i; ++ j ) { - } + denom *= j; - for ( var j = 2; j <= k - i; ++ j ) { + } - denom *= j; + return nom / denom; } + /* + Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2. + Pders : result of function calcBSplineDerivatives + returns array with derivatives for rational curve. + */ - return nom / denom; - }, + static calcRationalCurveDerivatives( Pders ) { + const nd = Pders.length; + const Aders = []; + const wders = []; - /* - Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2. + for ( let i = 0; i < nd; ++ i ) { - Pders : result of function calcBSplineDerivatives + const point = Pders[ i ]; + Aders[ i ] = new THREE.Vector3( point.x, point.y, point.z ); + wders[ i ] = point.w; - returns array with derivatives for rational curve. - */ - calcRationalCurveDerivatives: function ( Pders ) { - - var nd = Pders.length; - var Aders = []; - var wders = []; - - for ( var i = 0; i < nd; ++ i ) { + } - var point = Pders[ i ]; - Aders[ i ] = new THREE.Vector3( point.x, point.y, point.z ); - wders[ i ] = point.w; + const CK = []; - } + for ( let k = 0; k < nd; ++ k ) { - var CK = []; + const v = Aders[ k ].clone(); - for ( var k = 0; k < nd; ++ k ) { + for ( let i = 1; i <= k; ++ i ) { - var v = Aders[ k ].clone(); + v.sub( CK[ k - i ].clone().multiplyScalar( this.calcKoverI( k, i ) * wders[ i ] ) ); - for ( var i = 1; i <= k; ++ i ) { + } - v.sub( CK[ k - i ].clone().multiplyScalar( this.calcKoverI( k, i ) * wders[ i ] ) ); + CK[ k ] = v.divideScalar( wders[ 0 ] ); } - CK[ k ] = v.divideScalar( wders[ 0 ] ); + return CK; } + /* + Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2. + p : degree + U : knot vector + P : control points in homogeneous space + u : parametric points + nd : number of derivatives + returns array with derivatives. + */ - return CK; - }, + static calcNURBSDerivatives( p, U, P, u, nd ) { + const Pders = this.calcBSplineDerivatives( p, U, P, u, nd ); + return this.calcRationalCurveDerivatives( Pders ); - /* - Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2. + } + /* + Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3. + p1, p2 : degrees of B-Spline surface + U1, U2 : knot vectors + P : control points (x, y, z, w) + u, v : parametric values + returns point for given (u, v) + */ - p : degree - U : knot vector - P : control points in homogeneous space - u : parametric points - nd : number of derivatives - returns array with derivatives. - */ - calcNURBSDerivatives: function ( p, U, P, u, nd ) { + static calcSurfacePoint( p, q, U, V, P, u, v, target ) { - var Pders = this.calcBSplineDerivatives( p, U, P, u, nd ); - return this.calcRationalCurveDerivatives( Pders ); + const uspan = this.findSpan( p, u, U ); + const vspan = this.findSpan( q, v, V ); + const Nu = this.calcBasisFunctions( uspan, u, p, U ); + const Nv = this.calcBasisFunctions( vspan, v, q, V ); + const temp = []; - }, + for ( let l = 0; l <= q; ++ l ) { + temp[ l ] = new THREE.Vector4( 0, 0, 0, 0 ); - /* - Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3. + for ( let k = 0; k <= p; ++ k ) { - p1, p2 : degrees of B-Spline surface - U1, U2 : knot vectors - P : control points (x, y, z, w) - u, v : parametric values + const point = P[ uspan - p + k ][ vspan - q + l ].clone(); + const w = point.w; + point.x *= w; + point.y *= w; + point.z *= w; + temp[ l ].add( point.multiplyScalar( Nu[ k ] ) ); - returns point for given (u, v) - */ - calcSurfacePoint: function ( p, q, U, V, P, u, v, target ) { + } - var uspan = this.findSpan( p, u, U ); - var vspan = this.findSpan( q, v, V ); - var Nu = this.calcBasisFunctions( uspan, u, p, U ); - var Nv = this.calcBasisFunctions( vspan, v, q, V ); - var temp = []; + } - for ( var l = 0; l <= q; ++ l ) { + const Sw = new THREE.Vector4( 0, 0, 0, 0 ); - temp[ l ] = new THREE.Vector4( 0, 0, 0, 0 ); - for ( var k = 0; k <= p; ++ k ) { + for ( let l = 0; l <= q; ++ l ) { - var point = P[ uspan - p + k ][ vspan - q + l ].clone(); - var w = point.w; - point.x *= w; - point.y *= w; - point.z *= w; - temp[ l ].add( point.multiplyScalar( Nu[ k ] ) ); + Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) ); } - } - - var Sw = new THREE.Vector4( 0, 0, 0, 0 ); - for ( var l = 0; l <= q; ++ l ) { - - Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) ); + Sw.divideScalar( Sw.w ); + target.set( Sw.x, Sw.y, Sw.z ); } - Sw.divideScalar( Sw.w ); - target.set( Sw.x, Sw.y, Sw.z ); - } -}; + THREE.NURBSUtils = NURBSUtils; + +} )(); diff --git a/examples/js/deprecated/Geometry.js b/examples/js/deprecated/Geometry.js new file mode 100644 index 00000000000000..e22aa55c83f9ab --- /dev/null +++ b/examples/js/deprecated/Geometry.js @@ -0,0 +1,1656 @@ +( function () { + + const _m1 = new THREE.Matrix4(); + + const _obj = new THREE.Object3D(); + + const _offset = new THREE.Vector3(); + + class Geometry extends THREE.EventDispatcher { + + constructor() { + + super(); + this.uuid = THREE.MathUtils.generateUUID(); + this.name = ''; + this.type = 'Geometry'; + this.vertices = []; + this.colors = []; + this.faces = []; + this.faceVertexUvs = [[]]; + this.morphTargets = []; + this.morphNormals = []; + this.skinWeights = []; + this.skinIndices = []; + this.lineDistances = []; + this.boundingBox = null; + this.boundingSphere = null; // update flags + + this.elementsNeedUpdate = false; + this.verticesNeedUpdate = false; + this.uvsNeedUpdate = false; + this.normalsNeedUpdate = false; + this.colorsNeedUpdate = false; + this.lineDistancesNeedUpdate = false; + this.groupsNeedUpdate = false; + + } + + applyMatrix4( matrix ) { + + const normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix ); + + for ( let i = 0, il = this.vertices.length; i < il; i ++ ) { + + const vertex = this.vertices[ i ]; + vertex.applyMatrix4( matrix ); + + } + + for ( let i = 0, il = this.faces.length; i < il; i ++ ) { + + const face = this.faces[ i ]; + face.normal.applyMatrix3( normalMatrix ).normalize(); + + for ( let j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { + + face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); + + } + + } + + if ( this.boundingBox !== null ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere !== null ) { + + this.computeBoundingSphere(); + + } + + this.verticesNeedUpdate = true; + this.normalsNeedUpdate = true; + return this; + + } + + rotateX( angle ) { + + // rotate geometry around world x-axis + _m1.makeRotationX( angle ); + + this.applyMatrix4( _m1 ); + return this; + + } + + rotateY( angle ) { + + // rotate geometry around world y-axis + _m1.makeRotationY( angle ); + + this.applyMatrix4( _m1 ); + return this; + + } + + rotateZ( angle ) { + + // rotate geometry around world z-axis + _m1.makeRotationZ( angle ); + + this.applyMatrix4( _m1 ); + return this; + + } + + translate( x, y, z ) { + + // translate geometry + _m1.makeTranslation( x, y, z ); + + this.applyMatrix4( _m1 ); + return this; + + } + + scale( x, y, z ) { + + // scale geometry + _m1.makeScale( x, y, z ); + + this.applyMatrix4( _m1 ); + return this; + + } + + lookAt( vector ) { + + _obj.lookAt( vector ); + + _obj.updateMatrix(); + + this.applyMatrix4( _obj.matrix ); + return this; + + } + + fromBufferGeometry( geometry ) { + + const scope = this; + const index = geometry.index !== null ? geometry.index : undefined; + const attributes = geometry.attributes; + + if ( attributes.position === undefined ) { + + console.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' ); + return this; + + } + + const position = attributes.position; + const normal = attributes.normal; + const color = attributes.color; + const uv = attributes.uv; + const uv2 = attributes.uv2; + if ( uv2 !== undefined ) this.faceVertexUvs[ 1 ] = []; + + for ( let i = 0; i < position.count; i ++ ) { + + scope.vertices.push( new THREE.Vector3().fromBufferAttribute( position, i ) ); + + if ( color !== undefined ) { + + scope.colors.push( new THREE.Color().fromBufferAttribute( color, i ) ); + + } + + } + + function addFace( a, b, c, materialIndex ) { + + const vertexColors = color === undefined ? [] : [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ]; + const vertexNormals = normal === undefined ? [] : [ new THREE.Vector3().fromBufferAttribute( normal, a ), new THREE.Vector3().fromBufferAttribute( normal, b ), new THREE.Vector3().fromBufferAttribute( normal, c ) ]; + const face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); + scope.faces.push( face ); + + if ( uv !== undefined ) { + + scope.faceVertexUvs[ 0 ].push( [ new THREE.Vector2().fromBufferAttribute( uv, a ), new THREE.Vector2().fromBufferAttribute( uv, b ), new THREE.Vector2().fromBufferAttribute( uv, c ) ] ); + + } + + if ( uv2 !== undefined ) { + + scope.faceVertexUvs[ 1 ].push( [ new THREE.Vector2().fromBufferAttribute( uv2, a ), new THREE.Vector2().fromBufferAttribute( uv2, b ), new THREE.Vector2().fromBufferAttribute( uv2, c ) ] ); + + } + + } + + const groups = geometry.groups; + + if ( groups.length > 0 ) { + + for ( let i = 0; i < groups.length; i ++ ) { + + const group = groups[ i ]; + const start = group.start; + const count = group.count; + + for ( let j = start, jl = start + count; j < jl; j += 3 ) { + + if ( index !== undefined ) { + + addFace( index.getX( j ), index.getX( j + 1 ), index.getX( j + 2 ), group.materialIndex ); + + } else { + + addFace( j, j + 1, j + 2, group.materialIndex ); + + } + + } + + } + + } else { + + if ( index !== undefined ) { + + for ( let i = 0; i < index.count; i += 3 ) { + + addFace( index.getX( i ), index.getX( i + 1 ), index.getX( i + 2 ) ); + + } + + } else { + + for ( let i = 0; i < position.count; i += 3 ) { + + addFace( i, i + 1, i + 2 ); + + } + + } + + } + + this.computeFaceNormals(); + + if ( geometry.boundingBox !== null ) { + + this.boundingBox = geometry.boundingBox.clone(); + + } + + if ( geometry.boundingSphere !== null ) { + + this.boundingSphere = geometry.boundingSphere.clone(); + + } + + return this; + + } + + center() { + + this.computeBoundingBox(); + this.boundingBox.getCenter( _offset ).negate(); + this.translate( _offset.x, _offset.y, _offset.z ); + return this; + + } + + normalize() { + + this.computeBoundingSphere(); + const center = this.boundingSphere.center; + const radius = this.boundingSphere.radius; + const s = radius === 0 ? 1 : 1.0 / radius; + const matrix = new THREE.Matrix4(); + matrix.set( s, 0, 0, - s * center.x, 0, s, 0, - s * center.y, 0, 0, s, - s * center.z, 0, 0, 0, 1 ); + this.applyMatrix4( matrix ); + return this; + + } + + computeFaceNormals() { + + const cb = new THREE.Vector3(), + ab = new THREE.Vector3(); + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + const vA = this.vertices[ face.a ]; + const vB = this.vertices[ face.b ]; + const vC = this.vertices[ face.c ]; + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); + cb.normalize(); + face.normal.copy( cb ); + + } + + } + + computeVertexNormals( areaWeighted = true ) { + + const vertices = new Array( this.vertices.length ); + + for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + vertices[ v ] = new THREE.Vector3(); + + } + + if ( areaWeighted ) { + + // vertex normals weighted by triangle areas + // http://www.iquilezles.org/www/articles/normals/normals.htm + const cb = new THREE.Vector3(), + ab = new THREE.Vector3(); + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + const vA = this.vertices[ face.a ]; + const vB = this.vertices[ face.b ]; + const vC = this.vertices[ face.c ]; + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); + vertices[ face.a ].add( cb ); + vertices[ face.b ].add( cb ); + vertices[ face.c ].add( cb ); + + } + + } else { + + this.computeFaceNormals(); + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + vertices[ face.a ].add( face.normal ); + vertices[ face.b ].add( face.normal ); + vertices[ face.c ].add( face.normal ); + + } + + } + + for ( let v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + vertices[ v ].normalize(); + + } + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + const vertexNormals = face.vertexNormals; + + if ( vertexNormals.length === 3 ) { + + vertexNormals[ 0 ].copy( vertices[ face.a ] ); + vertexNormals[ 1 ].copy( vertices[ face.b ] ); + vertexNormals[ 2 ].copy( vertices[ face.c ] ); + + } else { + + vertexNormals[ 0 ] = vertices[ face.a ].clone(); + vertexNormals[ 1 ] = vertices[ face.b ].clone(); + vertexNormals[ 2 ] = vertices[ face.c ].clone(); + + } + + } + + if ( this.faces.length > 0 ) { + + this.normalsNeedUpdate = true; + + } + + } + + computeFlatVertexNormals() { + + this.computeFaceNormals(); + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + const vertexNormals = face.vertexNormals; + + if ( vertexNormals.length === 3 ) { + + vertexNormals[ 0 ].copy( face.normal ); + vertexNormals[ 1 ].copy( face.normal ); + vertexNormals[ 2 ].copy( face.normal ); + + } else { + + vertexNormals[ 0 ] = face.normal.clone(); + vertexNormals[ 1 ] = face.normal.clone(); + vertexNormals[ 2 ] = face.normal.clone(); + + } + + } + + if ( this.faces.length > 0 ) { + + this.normalsNeedUpdate = true; + + } + + } + + computeMorphNormals() { + + // save original normals + // - create temp variables on first access + // otherwise just copy (for faster repeated calls) + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + + if ( ! face.__originalFaceNormal ) { + + face.__originalFaceNormal = face.normal.clone(); + + } else { + + face.__originalFaceNormal.copy( face.normal ); + + } + + if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; + + for ( let i = 0, il = face.vertexNormals.length; i < il; i ++ ) { + + if ( ! face.__originalVertexNormals[ i ] ) { + + face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); + + } else { + + face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); + + } + + } + + } // use temp geometry to compute face and vertex normals for each morph + + + const tmpGeo = new Geometry(); + tmpGeo.faces = this.faces; + + for ( let i = 0, il = this.morphTargets.length; i < il; i ++ ) { + + // create on first access + if ( ! this.morphNormals[ i ] ) { + + this.morphNormals[ i ] = {}; + this.morphNormals[ i ].faceNormals = []; + this.morphNormals[ i ].vertexNormals = []; + const dstNormalsFace = this.morphNormals[ i ].faceNormals; + const dstNormalsVertex = this.morphNormals[ i ].vertexNormals; + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const faceNormal = new THREE.Vector3(); + const vertexNormals = { + a: new THREE.Vector3(), + b: new THREE.Vector3(), + c: new THREE.Vector3() + }; + dstNormalsFace.push( faceNormal ); + dstNormalsVertex.push( vertexNormals ); + + } + + } + + const morphNormals = this.morphNormals[ i ]; // set vertices to morph target + + tmpGeo.vertices = this.morphTargets[ i ].vertices; // compute morph normals + + tmpGeo.computeFaceNormals(); + tmpGeo.computeVertexNormals(); // store morph normals + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + const faceNormal = morphNormals.faceNormals[ f ]; + const vertexNormals = morphNormals.vertexNormals[ f ]; + faceNormal.copy( face.normal ); + vertexNormals.a.copy( face.vertexNormals[ 0 ] ); + vertexNormals.b.copy( face.vertexNormals[ 1 ] ); + vertexNormals.c.copy( face.vertexNormals[ 2 ] ); + + } + + } // restore original normals + + + for ( let f = 0, fl = this.faces.length; f < fl; f ++ ) { + + const face = this.faces[ f ]; + face.normal = face.__originalFaceNormal; + face.vertexNormals = face.__originalVertexNormals; + + } + + } + + computeBoundingBox() { + + if ( this.boundingBox === null ) { + + this.boundingBox = new THREE.Box3(); + + } + + this.boundingBox.setFromPoints( this.vertices ); + + } + + computeBoundingSphere() { + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new THREE.Sphere(); + + } + + this.boundingSphere.setFromPoints( this.vertices ); + + } + + merge( geometry, matrix, materialIndexOffset = 0 ) { + + if ( ! ( geometry && geometry.isGeometry ) ) { + + console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); + return; + + } + + let normalMatrix; + const vertexOffset = this.vertices.length, + vertices1 = this.vertices, + vertices2 = geometry.vertices, + faces1 = this.faces, + faces2 = geometry.faces, + colors1 = this.colors, + colors2 = geometry.colors; + + if ( matrix !== undefined ) { + + normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix ); + + } // vertices + + + for ( let i = 0, il = vertices2.length; i < il; i ++ ) { + + const vertex = vertices2[ i ]; + const vertexCopy = vertex.clone(); + if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); + vertices1.push( vertexCopy ); + + } // colors + + + for ( let i = 0, il = colors2.length; i < il; i ++ ) { + + colors1.push( colors2[ i ].clone() ); + + } // faces + + + for ( let i = 0, il = faces2.length; i < il; i ++ ) { + + const face = faces2[ i ]; + let normal, color; + const faceVertexNormals = face.vertexNormals, + faceVertexColors = face.vertexColors; + const faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); + faceCopy.normal.copy( face.normal ); + + if ( normalMatrix !== undefined ) { + + faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); + + } + + for ( let j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { + + normal = faceVertexNormals[ j ].clone(); + + if ( normalMatrix !== undefined ) { + + normal.applyMatrix3( normalMatrix ).normalize(); + + } + + faceCopy.vertexNormals.push( normal ); + + } + + faceCopy.color.copy( face.color ); + + for ( let j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { + + color = faceVertexColors[ j ]; + faceCopy.vertexColors.push( color.clone() ); + + } + + faceCopy.materialIndex = face.materialIndex + materialIndexOffset; + faces1.push( faceCopy ); + + } // uvs + + + for ( let i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) { + + const faceVertexUvs2 = geometry.faceVertexUvs[ i ]; + if ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = []; + + for ( let j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) { + + const uvs2 = faceVertexUvs2[ j ], + uvsCopy = []; + + for ( let k = 0, kl = uvs2.length; k < kl; k ++ ) { + + uvsCopy.push( uvs2[ k ].clone() ); + + } + + this.faceVertexUvs[ i ].push( uvsCopy ); + + } + + } + + } + + mergeMesh( mesh ) { + + if ( ! ( mesh && mesh.isMesh ) ) { + + console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); + return; + + } + + if ( mesh.matrixAutoUpdate ) mesh.updateMatrix(); + this.merge( mesh.geometry, mesh.matrix ); + + } + /* + * Checks for duplicate vertices with hashmap. + * Duplicated vertices are removed + * and faces' vertices are updated. + */ + + + mergeVertices( precisionPoints = 4 ) { + + const verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) + + const unique = [], + changes = []; + const precision = Math.pow( 10, precisionPoints ); + + for ( let i = 0, il = this.vertices.length; i < il; i ++ ) { + + const v = this.vertices[ i ]; + const key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); + + if ( verticesMap[ key ] === undefined ) { + + verticesMap[ key ] = i; + unique.push( this.vertices[ i ] ); + changes[ i ] = unique.length - 1; + + } else { + + //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); + changes[ i ] = changes[ verticesMap[ key ] ]; + + } + + } // if faces are completely degenerate after merging vertices, we + // have to remove them from the geometry. + + + const faceIndicesToRemove = []; + + for ( let i = 0, il = this.faces.length; i < il; i ++ ) { + + const face = this.faces[ i ]; + face.a = changes[ face.a ]; + face.b = changes[ face.b ]; + face.c = changes[ face.c ]; + const indices = [ face.a, face.b, face.c ]; // if any duplicate vertices are found in a Face3 + // we have to remove the face as nothing can be saved + + for ( let n = 0; n < 3; n ++ ) { + + if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { + + faceIndicesToRemove.push( i ); + break; + + } + + } + + } + + for ( let i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { + + const idx = faceIndicesToRemove[ i ]; + this.faces.splice( idx, 1 ); + + for ( let j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { + + this.faceVertexUvs[ j ].splice( idx, 1 ); + + } + + } // Use unique set of vertices + + + const diff = this.vertices.length - unique.length; + this.vertices = unique; + return diff; + + } + + setFromPoints( points ) { + + this.vertices = []; + + for ( let i = 0, l = points.length; i < l; i ++ ) { + + const point = points[ i ]; + this.vertices.push( new THREE.Vector3( point.x, point.y, point.z || 0 ) ); + + } + + return this; + + } + + sortFacesByMaterialIndex() { + + const faces = this.faces; + const length = faces.length; // tag faces + + for ( let i = 0; i < length; i ++ ) { + + faces[ i ]._id = i; + + } // sort faces + + + function materialIndexSort( a, b ) { + + return a.materialIndex - b.materialIndex; + + } + + faces.sort( materialIndexSort ); // sort uvs + + const uvs1 = this.faceVertexUvs[ 0 ]; + const uvs2 = this.faceVertexUvs[ 1 ]; + let newUvs1, newUvs2; + if ( uvs1 && uvs1.length === length ) newUvs1 = []; + if ( uvs2 && uvs2.length === length ) newUvs2 = []; + + for ( let i = 0; i < length; i ++ ) { + + const id = faces[ i ]._id; + if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); + if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); + + } + + if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; + if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; + + } + + toJSON() { + + const data = { + metadata: { + version: 4.5, + type: 'Geometry', + generator: 'Geometry.toJSON' + } + }; // standard Geometry serialization + + data.uuid = this.uuid; + data.type = this.type; + if ( this.name !== '' ) data.name = this.name; + + if ( this.parameters !== undefined ) { + + const parameters = this.parameters; + + for ( const key in parameters ) { + + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + + } + + return data; + + } + + const vertices = []; + + for ( let i = 0; i < this.vertices.length; i ++ ) { + + const vertex = this.vertices[ i ]; + vertices.push( vertex.x, vertex.y, vertex.z ); + + } + + const faces = []; + const normals = []; + const normalsHash = {}; + const colors = []; + const colorsHash = {}; + const uvs = []; + const uvsHash = {}; + + for ( let i = 0; i < this.faces.length; i ++ ) { + + const face = this.faces[ i ]; + const hasMaterial = true; + const hasFaceUv = false; // deprecated + + const hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined; + const hasFaceNormal = face.normal.length() > 0; + const hasFaceVertexNormal = face.vertexNormals.length > 0; + const hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1; + const hasFaceVertexColor = face.vertexColors.length > 0; + let faceType = 0; + faceType = setBit( faceType, 0, 0 ); // isQuad + + faceType = setBit( faceType, 1, hasMaterial ); + faceType = setBit( faceType, 2, hasFaceUv ); + faceType = setBit( faceType, 3, hasFaceVertexUv ); + faceType = setBit( faceType, 4, hasFaceNormal ); + faceType = setBit( faceType, 5, hasFaceVertexNormal ); + faceType = setBit( faceType, 6, hasFaceColor ); + faceType = setBit( faceType, 7, hasFaceVertexColor ); + faces.push( faceType ); + faces.push( face.a, face.b, face.c ); + faces.push( face.materialIndex ); + + if ( hasFaceVertexUv ) { + + const faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; + faces.push( getUvIndex( faceVertexUvs[ 0 ] ), getUvIndex( faceVertexUvs[ 1 ] ), getUvIndex( faceVertexUvs[ 2 ] ) ); + + } + + if ( hasFaceNormal ) { + + faces.push( getNormalIndex( face.normal ) ); + + } + + if ( hasFaceVertexNormal ) { + + const vertexNormals = face.vertexNormals; + faces.push( getNormalIndex( vertexNormals[ 0 ] ), getNormalIndex( vertexNormals[ 1 ] ), getNormalIndex( vertexNormals[ 2 ] ) ); + + } + + if ( hasFaceColor ) { + + faces.push( getColorIndex( face.color ) ); + + } + + if ( hasFaceVertexColor ) { + + const vertexColors = face.vertexColors; + faces.push( getColorIndex( vertexColors[ 0 ] ), getColorIndex( vertexColors[ 1 ] ), getColorIndex( vertexColors[ 2 ] ) ); + + } + + } + + function setBit( value, position, enabled ) { + + return enabled ? value | 1 << position : value & ~ ( 1 << position ); + + } + + function getNormalIndex( normal ) { + + const hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); + + if ( normalsHash[ hash ] !== undefined ) { + + return normalsHash[ hash ]; + + } + + normalsHash[ hash ] = normals.length / 3; + normals.push( normal.x, normal.y, normal.z ); + return normalsHash[ hash ]; + + } + + function getColorIndex( color ) { + + const hash = color.r.toString() + color.g.toString() + color.b.toString(); + + if ( colorsHash[ hash ] !== undefined ) { + + return colorsHash[ hash ]; + + } + + colorsHash[ hash ] = colors.length; + colors.push( color.getHex() ); + return colorsHash[ hash ]; + + } + + function getUvIndex( uv ) { + + const hash = uv.x.toString() + uv.y.toString(); + + if ( uvsHash[ hash ] !== undefined ) { + + return uvsHash[ hash ]; + + } + + uvsHash[ hash ] = uvs.length / 2; + uvs.push( uv.x, uv.y ); + return uvsHash[ hash ]; + + } + + data.data = {}; + data.data.vertices = vertices; + data.data.normals = normals; + if ( colors.length > 0 ) data.data.colors = colors; + if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility + + data.data.faces = faces; + return data; + + } + + clone() { + + /* + // Handle primitives + const parameters = this.parameters; + if ( parameters !== undefined ) { + const values = []; + for ( const key in parameters ) { + values.push( parameters[ key ] ); + } + const geometry = Object.create( this.constructor.prototype ); + this.constructor.apply( geometry, values ); + return geometry; + } + return new this.constructor().copy( this ); + */ + return new Geometry().copy( this ); + + } + + copy( source ) { + + // reset + this.vertices = []; + this.colors = []; + this.faces = []; + this.faceVertexUvs = [[]]; + this.morphTargets = []; + this.morphNormals = []; + this.skinWeights = []; + this.skinIndices = []; + this.lineDistances = []; + this.boundingBox = null; + this.boundingSphere = null; // name + + this.name = source.name; // vertices + + const vertices = source.vertices; + + for ( let i = 0, il = vertices.length; i < il; i ++ ) { + + this.vertices.push( vertices[ i ].clone() ); + + } // colors + + + const colors = source.colors; + + for ( let i = 0, il = colors.length; i < il; i ++ ) { + + this.colors.push( colors[ i ].clone() ); + + } // faces + + + const faces = source.faces; + + for ( let i = 0, il = faces.length; i < il; i ++ ) { + + this.faces.push( faces[ i ].clone() ); + + } // face vertex uvs + + + for ( let i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { + + const faceVertexUvs = source.faceVertexUvs[ i ]; + + if ( this.faceVertexUvs[ i ] === undefined ) { + + this.faceVertexUvs[ i ] = []; + + } + + for ( let j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { + + const uvs = faceVertexUvs[ j ], + uvsCopy = []; + + for ( let k = 0, kl = uvs.length; k < kl; k ++ ) { + + const uv = uvs[ k ]; + uvsCopy.push( uv.clone() ); + + } + + this.faceVertexUvs[ i ].push( uvsCopy ); + + } + + } // morph targets + + + const morphTargets = source.morphTargets; + + for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { + + const morphTarget = {}; + morphTarget.name = morphTargets[ i ].name; // vertices + + if ( morphTargets[ i ].vertices !== undefined ) { + + morphTarget.vertices = []; + + for ( let j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { + + morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); + + } + + } // normals + + + if ( morphTargets[ i ].normals !== undefined ) { + + morphTarget.normals = []; + + for ( let j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { + + morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); + + } + + } + + this.morphTargets.push( morphTarget ); + + } // morph normals + + + const morphNormals = source.morphNormals; + + for ( let i = 0, il = morphNormals.length; i < il; i ++ ) { + + const morphNormal = {}; // vertex normals + + if ( morphNormals[ i ].vertexNormals !== undefined ) { + + morphNormal.vertexNormals = []; + + for ( let j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { + + const srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; + const destVertexNormal = {}; + destVertexNormal.a = srcVertexNormal.a.clone(); + destVertexNormal.b = srcVertexNormal.b.clone(); + destVertexNormal.c = srcVertexNormal.c.clone(); + morphNormal.vertexNormals.push( destVertexNormal ); + + } + + } // face normals + + + if ( morphNormals[ i ].faceNormals !== undefined ) { + + morphNormal.faceNormals = []; + + for ( let j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { + + morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); + + } + + } + + this.morphNormals.push( morphNormal ); + + } // skin weights + + + const skinWeights = source.skinWeights; + + for ( let i = 0, il = skinWeights.length; i < il; i ++ ) { + + this.skinWeights.push( skinWeights[ i ].clone() ); + + } // skin indices + + + const skinIndices = source.skinIndices; + + for ( let i = 0, il = skinIndices.length; i < il; i ++ ) { + + this.skinIndices.push( skinIndices[ i ].clone() ); + + } // line distances + + + const lineDistances = source.lineDistances; + + for ( let i = 0, il = lineDistances.length; i < il; i ++ ) { + + this.lineDistances.push( lineDistances[ i ] ); + + } // bounding box + + + const boundingBox = source.boundingBox; + + if ( boundingBox !== null ) { + + this.boundingBox = boundingBox.clone(); + + } // bounding sphere + + + const boundingSphere = source.boundingSphere; + + if ( boundingSphere !== null ) { + + this.boundingSphere = boundingSphere.clone(); + + } // update flags + + + this.elementsNeedUpdate = source.elementsNeedUpdate; + this.verticesNeedUpdate = source.verticesNeedUpdate; + this.uvsNeedUpdate = source.uvsNeedUpdate; + this.normalsNeedUpdate = source.normalsNeedUpdate; + this.colorsNeedUpdate = source.colorsNeedUpdate; + this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate; + this.groupsNeedUpdate = source.groupsNeedUpdate; + return this; + + } + + toBufferGeometry() { + + const geometry = new DirectGeometry().fromGeometry( this ); + const buffergeometry = new THREE.BufferGeometry(); + const positions = new Float32Array( geometry.vertices.length * 3 ); + buffergeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); + + if ( geometry.normals.length > 0 ) { + + const normals = new Float32Array( geometry.normals.length * 3 ); + buffergeometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); + + } + + if ( geometry.colors.length > 0 ) { + + const colors = new Float32Array( geometry.colors.length * 3 ); + buffergeometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); + + } + + if ( geometry.uvs.length > 0 ) { + + const uvs = new Float32Array( geometry.uvs.length * 2 ); + buffergeometry.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); + + } + + if ( geometry.uvs2.length > 0 ) { + + const uvs2 = new Float32Array( geometry.uvs2.length * 2 ); + buffergeometry.setAttribute( 'uv2', new THREE.BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); + + } // groups + + + buffergeometry.groups = geometry.groups; // morphs + + for ( const name in geometry.morphTargets ) { + + const array = []; + const morphTargets = geometry.morphTargets[ name ]; + + for ( let i = 0, l = morphTargets.length; i < l; i ++ ) { + + const morphTarget = morphTargets[ i ]; + const attribute = new THREE.Float32BufferAttribute( morphTarget.data.length * 3, 3 ); + attribute.name = morphTarget.name; + array.push( attribute.copyVector3sArray( morphTarget.data ) ); + + } + + buffergeometry.morphAttributes[ name ] = array; + + } // skinning + + + if ( geometry.skinIndices.length > 0 ) { + + const skinIndices = new THREE.Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); + buffergeometry.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); + + } + + if ( geometry.skinWeights.length > 0 ) { + + const skinWeights = new THREE.Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); + buffergeometry.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); + + } // + + + if ( geometry.boundingSphere !== null ) { + + buffergeometry.boundingSphere = geometry.boundingSphere.clone(); + + } + + if ( geometry.boundingBox !== null ) { + + buffergeometry.boundingBox = geometry.boundingBox.clone(); + + } + + return buffergeometry; + + } + + computeTangents() { + + console.error( 'THREE.Geometry: .computeTangents() has been removed.' ); + + } + + computeLineDistances() { + + console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' ); + + } + + applyMatrix( matrix ) { + + console.warn( 'THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().' ); + return this.applyMatrix4( matrix ); + + } + + dispose() { + + this.dispatchEvent( { + type: 'dispose' + } ); + + } + + static createBufferGeometryFromObject( object ) { + + let buffergeometry = new THREE.BufferGeometry(); + const geometry = object.geometry; + + if ( object.isPoints || object.isLine ) { + + const positions = new THREE.Float32BufferAttribute( geometry.vertices.length * 3, 3 ); + const colors = new THREE.Float32BufferAttribute( geometry.colors.length * 3, 3 ); + buffergeometry.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); + buffergeometry.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); + + if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { + + const lineDistances = new THREE.Float32BufferAttribute( geometry.lineDistances.length, 1 ); + buffergeometry.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); + + } + + if ( geometry.boundingSphere !== null ) { + + buffergeometry.boundingSphere = geometry.boundingSphere.clone(); + + } + + if ( geometry.boundingBox !== null ) { + + buffergeometry.boundingBox = geometry.boundingBox.clone(); + + } + + } else if ( object.isMesh ) { + + buffergeometry = geometry.toBufferGeometry(); + + } + + return buffergeometry; + + } + + } + + Geometry.prototype.isGeometry = true; + + class DirectGeometry { + + constructor() { + + this.vertices = []; + this.normals = []; + this.colors = []; + this.uvs = []; + this.uvs2 = []; + this.groups = []; + this.morphTargets = {}; + this.skinWeights = []; + this.skinIndices = []; // this.lineDistances = []; + + this.boundingBox = null; + this.boundingSphere = null; // update flags + + this.verticesNeedUpdate = false; + this.normalsNeedUpdate = false; + this.colorsNeedUpdate = false; + this.uvsNeedUpdate = false; + this.groupsNeedUpdate = false; + + } + + computeGroups( geometry ) { + + const groups = []; + let group, i; + let materialIndex = undefined; + const faces = geometry.faces; + + for ( i = 0; i < faces.length; i ++ ) { + + const face = faces[ i ]; // materials + + if ( face.materialIndex !== materialIndex ) { + + materialIndex = face.materialIndex; + + if ( group !== undefined ) { + + group.count = i * 3 - group.start; + groups.push( group ); + + } + + group = { + start: i * 3, + materialIndex: materialIndex + }; + + } + + } + + if ( group !== undefined ) { + + group.count = i * 3 - group.start; + groups.push( group ); + + } + + this.groups = groups; + + } + + fromGeometry( geometry ) { + + const faces = geometry.faces; + const vertices = geometry.vertices; + const faceVertexUvs = geometry.faceVertexUvs; + const hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; + const hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; // morphs + + const morphTargets = geometry.morphTargets; + const morphTargetsLength = morphTargets.length; + let morphTargetsPosition; + + if ( morphTargetsLength > 0 ) { + + morphTargetsPosition = []; + + for ( let i = 0; i < morphTargetsLength; i ++ ) { + + morphTargetsPosition[ i ] = { + name: morphTargets[ i ].name, + data: [] + }; + + } + + this.morphTargets.position = morphTargetsPosition; + + } + + const morphNormals = geometry.morphNormals; + const morphNormalsLength = morphNormals.length; + let morphTargetsNormal; + + if ( morphNormalsLength > 0 ) { + + morphTargetsNormal = []; + + for ( let i = 0; i < morphNormalsLength; i ++ ) { + + morphTargetsNormal[ i ] = { + name: morphNormals[ i ].name, + data: [] + }; + + } + + this.morphTargets.normal = morphTargetsNormal; + + } // skins + + + const skinIndices = geometry.skinIndices; + const skinWeights = geometry.skinWeights; + const hasSkinIndices = skinIndices.length === vertices.length; + const hasSkinWeights = skinWeights.length === vertices.length; // + + if ( vertices.length > 0 && faces.length === 0 ) { + + console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' ); + + } + + for ( let i = 0; i < faces.length; i ++ ) { + + const face = faces[ i ]; + this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); + const vertexNormals = face.vertexNormals; + + if ( vertexNormals.length === 3 ) { + + this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); + + } else { + + const normal = face.normal; + this.normals.push( normal, normal, normal ); + + } + + const vertexColors = face.vertexColors; + + if ( vertexColors.length === 3 ) { + + this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); + + } else { + + const color = face.color; + this.colors.push( color, color, color ); + + } + + if ( hasFaceVertexUv === true ) { + + const vertexUvs = faceVertexUvs[ 0 ][ i ]; + + if ( vertexUvs !== undefined ) { + + this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + + } else { + + console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); + this.uvs.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ); + + } + + } + + if ( hasFaceVertexUv2 === true ) { + + const vertexUvs = faceVertexUvs[ 1 ][ i ]; + + if ( vertexUvs !== undefined ) { + + this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); + + } else { + + console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); + this.uvs2.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ); + + } + + } // morphs + + + for ( let j = 0; j < morphTargetsLength; j ++ ) { + + const morphTarget = morphTargets[ j ].vertices; + morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); + + } + + for ( let j = 0; j < morphNormalsLength; j ++ ) { + + const morphNormal = morphNormals[ j ].vertexNormals[ i ]; + morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c ); + + } // skins + + + if ( hasSkinIndices ) { + + this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); + + } + + if ( hasSkinWeights ) { + + this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); + + } + + } + + this.computeGroups( geometry ); + this.verticesNeedUpdate = geometry.verticesNeedUpdate; + this.normalsNeedUpdate = geometry.normalsNeedUpdate; + this.colorsNeedUpdate = geometry.colorsNeedUpdate; + this.uvsNeedUpdate = geometry.uvsNeedUpdate; + this.groupsNeedUpdate = geometry.groupsNeedUpdate; + + if ( geometry.boundingSphere !== null ) { + + this.boundingSphere = geometry.boundingSphere.clone(); + + } + + if ( geometry.boundingBox !== null ) { + + this.boundingBox = geometry.boundingBox.clone(); + + } + + return this; + + } + + } + + class Face3 { + + constructor( a, b, c, normal, color, materialIndex = 0 ) { + + this.a = a; + this.b = b; + this.c = c; + this.normal = normal && normal.isVector3 ? normal : new THREE.Vector3(); + this.vertexNormals = Array.isArray( normal ) ? normal : []; + this.color = color && color.isColor ? color : new THREE.Color(); + this.vertexColors = Array.isArray( color ) ? color : []; + this.materialIndex = materialIndex; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.a = source.a; + this.b = source.b; + this.c = source.c; + this.normal.copy( source.normal ); + this.color.copy( source.color ); + this.materialIndex = source.materialIndex; + + for ( let i = 0, il = source.vertexNormals.length; i < il; i ++ ) { + + this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); + + } + + for ( let i = 0, il = source.vertexColors.length; i < il; i ++ ) { + + this.vertexColors[ i ] = source.vertexColors[ i ].clone(); + + } + + return this; + + } + + } + + THREE.Face3 = Face3; + THREE.Geometry = Geometry; + +} )(); diff --git a/examples/js/effects/AnaglyphEffect.js b/examples/js/effects/AnaglyphEffect.js index 69e398e24194cc..ce63897546af81 100644 --- a/examples/js/effects/AnaglyphEffect.js +++ b/examples/js/effects/AnaglyphEffect.js @@ -1,151 +1,97 @@ -THREE.AnaglyphEffect = function ( renderer, width, height ) { +( function () { - // Dubois matrices from https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.6968&rep=rep1&type=pdf#page=4 + class AnaglyphEffect { - this.colorMatrixLeft = new THREE.Matrix3().fromArray( [ - 0.456100, - 0.0400822, - 0.0152161, - 0.500484, - 0.0378246, - 0.0205971, - 0.176381, - 0.0157589, - 0.00546856 - ] ); + constructor( renderer, width = 512, height = 512 ) { - this.colorMatrixRight = new THREE.Matrix3().fromArray( [ - - 0.0434706, 0.378476, - 0.0721527, - - 0.0879388, 0.73364, - 0.112961, - - 0.00155529, - 0.0184503, 1.2264 - ] ); + // Dubois matrices from https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.6968&rep=rep1&type=pdf#page=4 + this.colorMatrixLeft = new THREE.Matrix3().fromArray( [ 0.456100, - 0.0400822, - 0.0152161, 0.500484, - 0.0378246, - 0.0205971, 0.176381, - 0.0157589, - 0.00546856 ] ); + this.colorMatrixRight = new THREE.Matrix3().fromArray( [ - 0.0434706, 0.378476, - 0.0721527, - 0.0879388, 0.73364, - 0.112961, - 0.00155529, - 0.0184503, 1.2264 ] ); - var _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); + const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - var _scene = new THREE.Scene(); + const _scene = new THREE.Scene(); - var _stereo = new THREE.StereoCamera(); + const _stereo = new THREE.StereoCamera(); - var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat }; + const _params = { + minFilter: THREE.LinearFilter, + magFilter: THREE.NearestFilter, + format: THREE.RGBAFormat + }; - if ( width === undefined ) width = 512; - if ( height === undefined ) height = 512; + const _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params ); - var _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params ); - var _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params ); + const _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params ); - var _material = new THREE.ShaderMaterial( { + const _material = new THREE.ShaderMaterial( { + uniforms: { + 'mapLeft': { + value: _renderTargetL.texture + }, + 'mapRight': { + value: _renderTargetR.texture + }, + 'colorMatrixLeft': { + value: this.colorMatrixLeft + }, + 'colorMatrixRight': { + value: this.colorMatrixRight + } + }, + vertexShader: [ 'varying vec2 vUv;', 'void main() {', ' vUv = vec2( uv.x, uv.y );', ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}' ].join( '\n' ), + fragmentShader: [ 'uniform sampler2D mapLeft;', 'uniform sampler2D mapRight;', 'varying vec2 vUv;', 'uniform mat3 colorMatrixLeft;', 'uniform mat3 colorMatrixRight;', // These functions implement sRGB linearization and gamma correction + 'float lin( float c ) {', ' return c <= 0.04045 ? c * 0.0773993808 :', ' pow( c * 0.9478672986 + 0.0521327014, 2.4 );', '}', 'vec4 lin( vec4 c ) {', ' return vec4( lin( c.r ), lin( c.g ), lin( c.b ), c.a );', '}', 'float dev( float c ) {', ' return c <= 0.0031308 ? c * 12.92', ' : pow( c, 0.41666 ) * 1.055 - 0.055;', '}', 'void main() {', ' vec2 uv = vUv;', ' vec4 colorL = lin( texture2D( mapLeft, uv ) );', ' vec4 colorR = lin( texture2D( mapRight, uv ) );', ' vec3 color = clamp(', ' colorMatrixLeft * colorL.rgb +', ' colorMatrixRight * colorR.rgb, 0., 1. );', ' gl_FragColor = vec4(', ' dev( color.r ), dev( color.g ), dev( color.b ),', ' max( colorL.a, colorR.a ) );', '}' ].join( '\n' ) + } ); - uniforms: { + const _mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ); - 'mapLeft': { value: _renderTargetL.texture }, - 'mapRight': { value: _renderTargetR.texture }, + _scene.add( _mesh ); - 'colorMatrixLeft': { value: this.colorMatrixLeft }, - 'colorMatrixRight': { value: this.colorMatrixRight } + this.setSize = function ( width, height ) { - }, + renderer.setSize( width, height ); + const pixelRatio = renderer.getPixelRatio(); - vertexShader: [ + _renderTargetL.setSize( width * pixelRatio, height * pixelRatio ); - 'varying vec2 vUv;', + _renderTargetR.setSize( width * pixelRatio, height * pixelRatio ); - 'void main() {', + }; - ' vUv = vec2( uv.x, uv.y );', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + this.render = function ( scene, camera ) { - '}' + const currentRenderTarget = renderer.getRenderTarget(); + scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); - ].join( '\n' ), + _stereo.update( camera ); - fragmentShader: [ + renderer.setRenderTarget( _renderTargetL ); + renderer.clear(); + renderer.render( scene, _stereo.cameraL ); + renderer.setRenderTarget( _renderTargetR ); + renderer.clear(); + renderer.render( scene, _stereo.cameraR ); + renderer.setRenderTarget( null ); + renderer.render( _scene, _camera ); + renderer.setRenderTarget( currentRenderTarget ); - 'uniform sampler2D mapLeft;', - 'uniform sampler2D mapRight;', - 'varying vec2 vUv;', + }; - 'uniform mat3 colorMatrixLeft;', - 'uniform mat3 colorMatrixRight;', + this.dispose = function () { - // These functions implement sRGB linearization and gamma correction + if ( _renderTargetL ) _renderTargetL.dispose(); + if ( _renderTargetR ) _renderTargetR.dispose(); + if ( _mesh ) _mesh.geometry.dispose(); + if ( _material ) _material.dispose(); - 'float lin( float c ) {', - ' return c <= 0.04045 ? c * 0.0773993808 :', - ' pow( c * 0.9478672986 + 0.0521327014, 2.4 );', - '}', + }; - 'vec4 lin( vec4 c ) {', - ' return vec4( lin( c.r ), lin( c.g ), lin( c.b ), c.a );', - '}', + } - 'float dev( float c ) {', - ' return c <= 0.0031308 ? c * 12.92', - ' : pow( c, 0.41666 ) * 1.055 - 0.055;', - '}', + } + THREE.AnaglyphEffect = AnaglyphEffect; - 'void main() {', - - ' vec2 uv = vUv;', - - ' vec4 colorL = lin( texture2D( mapLeft, uv ) );', - ' vec4 colorR = lin( texture2D( mapRight, uv ) );', - - ' vec3 color = clamp(', - ' colorMatrixLeft * colorL.rgb +', - ' colorMatrixRight * colorR.rgb, 0., 1. );', - - ' gl_FragColor = vec4(', - ' dev( color.r ), dev( color.g ), dev( color.b ),', - ' max( colorL.a, colorR.a ) );', - - '}' - - ].join( '\n' ) - - } ); - - var _mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ); - _scene.add( _mesh ); - - this.setSize = function ( width, height ) { - - renderer.setSize( width, height ); - - var pixelRatio = renderer.getPixelRatio(); - - _renderTargetL.setSize( width * pixelRatio, height * pixelRatio ); - _renderTargetR.setSize( width * pixelRatio, height * pixelRatio ); - - }; - - this.render = function ( scene, camera ) { - - var currentRenderTarget = renderer.getRenderTarget(); - - scene.updateMatrixWorld(); - - if ( camera.parent === null ) camera.updateMatrixWorld(); - - _stereo.update( camera ); - - renderer.setRenderTarget( _renderTargetL ); - renderer.clear(); - renderer.render( scene, _stereo.cameraL ); - - renderer.setRenderTarget( _renderTargetR ); - renderer.clear(); - renderer.render( scene, _stereo.cameraR ); - - renderer.setRenderTarget( null ); - renderer.render( _scene, _camera ); - - renderer.setRenderTarget( currentRenderTarget ); - - }; - - this.dispose = function () { - - if ( _renderTargetL ) _renderTargetL.dispose(); - if ( _renderTargetR ) _renderTargetR.dispose(); - if ( _mesh ) _mesh.geometry.dispose(); - if ( _material ) _material.dispose(); - - }; - -}; +} )(); diff --git a/examples/js/effects/AsciiEffect.js b/examples/js/effects/AsciiEffect.js index 0f899e4e1ba908..29e384c10e9800 100644 --- a/examples/js/effects/AsciiEffect.js +++ b/examples/js/effects/AsciiEffect.js @@ -1,288 +1,285 @@ -/** +( function () { + + /** * Ascii generation is based on http://www.nihilogic.dk/labs/jsascii/ * Maybe more about this later with a blog post at http://lab4games.net/zz85/blog * * 16 April 2012 - @blurspline */ + class AsciiEffect { -THREE.AsciiEffect = function ( renderer, charSet, options ) { - - // its fun to create one your own! - - charSet = ( charSet === undefined ) ? ' .:-=+*#%@' : charSet; - - // ' .,:;=|iI+hHOE#`$'; - // darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/ - // ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split(''); - - if ( ! options ) options = {}; + constructor( renderer, charSet = ' .:-=+*#%@', options = {} ) { - // Some ASCII settings + // ' .,:;=|iI+hHOE#`$'; + // darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/ + // ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split(''); + // Some ASCII settings + const bResolution = ! options[ 'resolution' ] ? 0.15 : options[ 'resolution' ]; // Higher for more details - var bResolution = ! options[ 'resolution' ] ? 0.15 : options[ 'resolution' ]; // Higher for more details - var iScale = ! options[ 'scale' ] ? 1 : options[ 'scale' ]; - var bColor = ! options[ 'color' ] ? false : options[ 'color' ]; // nice but slows down rendering! - var bAlpha = ! options[ 'alpha' ] ? false : options[ 'alpha' ]; // Transparency - var bBlock = ! options[ 'block' ] ? false : options[ 'block' ]; // blocked characters. like good O dos - var bInvert = ! options[ 'invert' ] ? false : options[ 'invert' ]; // black is white, white is black + const iScale = ! options[ 'scale' ] ? 1 : options[ 'scale' ]; + const bColor = ! options[ 'color' ] ? false : options[ 'color' ]; // nice but slows down rendering! - var strResolution = 'low'; + const bAlpha = ! options[ 'alpha' ] ? false : options[ 'alpha' ]; // Transparency - var width, height; + const bBlock = ! options[ 'block' ] ? false : options[ 'block' ]; // blocked characters. like good O dos - var domElement = document.createElement( 'div' ); - domElement.style.cursor = 'default'; + const bInvert = ! options[ 'invert' ] ? false : options[ 'invert' ]; // black is white, white is black - var oAscii = document.createElement( 'table' ); - domElement.appendChild( oAscii ); + const strResolution = 'low'; + let width, height; + const domElement = document.createElement( 'div' ); + domElement.style.cursor = 'default'; + const oAscii = document.createElement( 'table' ); + domElement.appendChild( oAscii ); + let iWidth, iHeight; + let oImg; - var iWidth, iHeight; - var oImg; + this.setSize = function ( w, h ) { - this.setSize = function ( w, h ) { + width = w; + height = h; + renderer.setSize( w, h ); + initAsciiSize(); - width = w; - height = h; + }; - renderer.setSize( w, h ); + this.render = function ( scene, camera ) { - initAsciiSize(); + renderer.render( scene, camera ); + asciifyImage( renderer, oAscii ); - }; + }; + this.domElement = domElement; // Throw in ascii library from http://www.nihilogic.dk/labs/jsascii/jsascii.js - this.render = function ( scene, camera ) { + /* + * 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] + */ - renderer.render( scene, camera ); - asciifyImage( renderer, oAscii ); + function initAsciiSize() { - }; + iWidth = Math.round( width * fResolution ); + iHeight = Math.round( height * fResolution ); + oCanvas.width = iWidth; + oCanvas.height = iHeight; // oCanvas.style.display = "none"; + // oCanvas.style.width = iWidth; + // oCanvas.style.height = iHeight; - this.domElement = domElement; + oImg = renderer.domElement; + if ( oImg.style.backgroundColor ) { - // Throw in ascii library from http://www.nihilogic.dk/labs/jsascii/jsascii.js + oAscii.rows[ 0 ].cells[ 0 ].style.backgroundColor = oImg.style.backgroundColor; + oAscii.rows[ 0 ].cells[ 0 ].style.color = oImg.style.color; - /* - * 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] - */ + } - function initAsciiSize() { + oAscii.cellSpacing = 0; + oAscii.cellPadding = 0; + const oStyle = oAscii.style; + oStyle.display = 'inline'; + oStyle.width = Math.round( iWidth / fResolution * iScale ) + 'px'; + oStyle.height = Math.round( iHeight / fResolution * iScale ) + 'px'; + oStyle.whiteSpace = 'pre'; + oStyle.margin = '0px'; + oStyle.padding = '0px'; + oStyle.letterSpacing = fLetterSpacing + 'px'; + oStyle.fontFamily = strFont; + oStyle.fontSize = fFontSize + 'px'; + oStyle.lineHeight = fLineHeight + 'px'; + oStyle.textAlign = 'left'; + oStyle.textDecoration = 'none'; - iWidth = Math.round( width * fResolution ); - iHeight = Math.round( height * fResolution ); + } - oCanvas.width = iWidth; - oCanvas.height = iHeight; - // oCanvas.style.display = "none"; - // oCanvas.style.width = iWidth; - // oCanvas.style.height = iHeight; + const aDefaultCharList = ' .,:;i1tfLCG08@'.split( '' ); + const aDefaultColorCharList = ' CGO08@'.split( '' ); + const strFont = 'courier new, monospace'; + const oCanvasImg = renderer.domElement; + const oCanvas = document.createElement( 'canvas' ); - oImg = renderer.domElement; + if ( ! oCanvas.getContext ) { - if ( oImg.style.backgroundColor ) { + return; - oAscii.rows[ 0 ].cells[ 0 ].style.backgroundColor = oImg.style.backgroundColor; - oAscii.rows[ 0 ].cells[ 0 ].style.color = oImg.style.color; + } - } + const oCtx = oCanvas.getContext( '2d' ); - oAscii.cellSpacing = 0; - oAscii.cellPadding = 0; - - var oStyle = oAscii.style; - oStyle.display = 'inline'; - oStyle.width = Math.round( iWidth / fResolution * iScale ) + 'px'; - oStyle.height = Math.round( iHeight / fResolution * iScale ) + 'px'; - oStyle.whiteSpace = 'pre'; - oStyle.margin = '0px'; - oStyle.padding = '0px'; - oStyle.letterSpacing = fLetterSpacing + 'px'; - oStyle.fontFamily = strFont; - oStyle.fontSize = fFontSize + 'px'; - oStyle.lineHeight = fLineHeight + 'px'; - oStyle.textAlign = 'left'; - oStyle.textDecoration = 'none'; + if ( ! oCtx.getImageData ) { - } + return; + } - var aDefaultCharList = ( ' .,:;i1tfLCG08@' ).split( '' ); - var aDefaultColorCharList = ( ' CGO08@' ).split( '' ); - var strFont = 'courier new, monospace'; + let aCharList = bColor ? aDefaultColorCharList : aDefaultCharList; + if ( charSet ) aCharList = charSet; + let fResolution = 0.5; - var oCanvasImg = renderer.domElement; + switch ( strResolution ) { - var oCanvas = document.createElement( 'canvas' ); - if ( ! oCanvas.getContext ) { + case 'low': + fResolution = 0.25; + break; - return; + case 'medium': + fResolution = 0.5; + break; - } + case 'high': + fResolution = 1; + break; - var oCtx = oCanvas.getContext( '2d' ); - if ( ! oCtx.getImageData ) { + } - return; + if ( bResolution ) fResolution = bResolution; // Setup dom - } + const fFontSize = 2 / fResolution * iScale; + const fLineHeight = 2 / fResolution * iScale; // adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width. - var aCharList = ( bColor ? aDefaultColorCharList : aDefaultCharList ); + let fLetterSpacing = 0; - if ( charSet ) aCharList = charSet; + if ( strResolution == 'low' ) { - var fResolution = 0.5; + switch ( iScale ) { - switch ( strResolution ) { + case 1: + fLetterSpacing = - 1; + break; - case 'low' : fResolution = 0.25; break; - case 'medium' : fResolution = 0.5; break; - case 'high' : fResolution = 1; break; + case 2: + case 3: + fLetterSpacing = - 2.1; + break; - } + case 4: + fLetterSpacing = - 3.1; + break; - if ( bResolution ) fResolution = bResolution; + case 5: + fLetterSpacing = - 4.15; + break; - // Setup dom + } - var fFontSize = ( 2 / fResolution ) * iScale; - var fLineHeight = ( 2 / fResolution ) * iScale; + } - // adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width. + if ( strResolution == 'medium' ) { - var fLetterSpacing = 0; + switch ( iScale ) { - if ( strResolution == 'low' ) { + case 1: + fLetterSpacing = 0; + break; - switch ( iScale ) { + case 2: + fLetterSpacing = - 1; + break; - case 1 : fLetterSpacing = - 1; break; - case 2 : - case 3 : fLetterSpacing = - 2.1; break; - case 4 : fLetterSpacing = - 3.1; break; - case 5 : fLetterSpacing = - 4.15; break; + case 3: + fLetterSpacing = - 1.04; + break; - } + case 4: + case 5: + fLetterSpacing = - 2.1; + break; - } + } - if ( strResolution == 'medium' ) { + } - switch ( iScale ) { + if ( strResolution == 'high' ) { - case 1 : fLetterSpacing = 0; break; - case 2 : fLetterSpacing = - 1; break; - case 3 : fLetterSpacing = - 1.04; break; - case 4 : - case 5 : fLetterSpacing = - 2.1; break; + switch ( iScale ) { - } + case 1: + case 2: + fLetterSpacing = 0; + break; - } + case 3: + case 4: + case 5: + fLetterSpacing = - 1; + break; - if ( strResolution == 'high' ) { + } - switch ( iScale ) { + } // can't get a span or div to flow like an img element, but a table works? + // convert img element to ascii - case 1 : - case 2 : fLetterSpacing = 0; break; - case 3 : - case 4 : - case 5 : fLetterSpacing = - 1; break; - } + function asciifyImage( canvasRenderer, oAscii ) { - } + oCtx.clearRect( 0, 0, iWidth, iHeight ); + oCtx.drawImage( oCanvasImg, 0, 0, iWidth, iHeight ); + const oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data; // Coloring loop starts now + let strChars = ''; // console.time('rendering'); - // can't get a span or div to flow like an img element, but a table works? + for ( let y = 0; y < iHeight; y += 2 ) { + for ( let x = 0; x < iWidth; x ++ ) { - // convert img element to ascii + const iOffset = ( y * iWidth + x ) * 4; + const iRed = oImgData[ iOffset ]; + const iGreen = oImgData[ iOffset + 1 ]; + const iBlue = oImgData[ iOffset + 2 ]; + const iAlpha = oImgData[ iOffset + 3 ]; + let iCharIdx; + let fBrightness; + fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255; // fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255; - function asciifyImage( canvasRenderer, oAscii ) { + if ( iAlpha == 0 ) { - oCtx.clearRect( 0, 0, iWidth, iHeight ); - oCtx.drawImage( oCanvasImg, 0, 0, iWidth, iHeight ); - var oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data; + // should calculate alpha instead, but quick hack :) + //fBrightness *= (iAlpha / 255); + fBrightness = 1; - // Coloring loop starts now - var strChars = ''; + } - // console.time('rendering'); + iCharIdx = Math.floor( ( 1 - fBrightness ) * ( aCharList.length - 1 ) ); - for ( var y = 0; y < iHeight; y += 2 ) { + if ( bInvert ) { - for ( var x = 0; x < iWidth; x ++ ) { + iCharIdx = aCharList.length - iCharIdx - 1; - var iOffset = ( y * iWidth + x ) * 4; + } // good for debugging + //fBrightness = Math.floor(fBrightness * 10); + //strThisChar = fBrightness; - var iRed = oImgData[ iOffset ]; - var iGreen = oImgData[ iOffset + 1 ]; - var iBlue = oImgData[ iOffset + 2 ]; - var iAlpha = oImgData[ iOffset + 3 ]; - var iCharIdx; - var fBrightness; + let strThisChar = aCharList[ iCharIdx ]; + if ( strThisChar === undefined || strThisChar == ' ' ) strThisChar = ' '; - fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255; - // fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255; + if ( bColor ) { - if ( iAlpha == 0 ) { + strChars += '' + strThisChar + ''; - // should calculate alpha instead, but quick hack :) - //fBrightness *= (iAlpha / 255); - fBrightness = 1; + } else { - } + strChars += strThisChar; - iCharIdx = Math.floor( ( 1 - fBrightness ) * ( aCharList.length - 1 ) ); + } - if ( bInvert ) { + } - iCharIdx = aCharList.length - iCharIdx - 1; + strChars += '
'; } - // good for debugging - //fBrightness = Math.floor(fBrightness * 10); - //strThisChar = fBrightness; - - var strThisChar = aCharList[ iCharIdx ]; - - if ( strThisChar === undefined || strThisChar == ' ' ) - strThisChar = ' '; - - if ( bColor ) { - - strChars += '' + strThisChar + ''; - - } else { - - strChars += strThisChar; - - } + oAscii.innerHTML = '' + strChars + ''; // console.timeEnd('rendering'); + // return oAscii; } - strChars += '
'; - } - oAscii.innerHTML = '' + strChars + ''; - - // console.timeEnd('rendering'); - - // return oAscii; - } - // end modified asciifyImage block + THREE.AsciiEffect = AsciiEffect; -}; +} )(); diff --git a/examples/js/effects/OutlineEffect.js b/examples/js/effects/OutlineEffect.js index 555c5340cc73e2..94827ea9bfa51c 100644 --- a/examples/js/effects/OutlineEffect.js +++ b/examples/js/effects/OutlineEffect.js @@ -1,11 +1,13 @@ -/** +( function () { + + /** * Reference: https://en.wikipedia.org/wiki/Cel_shading * * API * * 1. Traditional * - * var effect = new THREE.OutlineEffect( renderer ); + * const effect = new OutlineEffect( renderer ); * * function render() { * @@ -15,8 +17,8 @@ * * 2. VR compatible * - * var effect = new THREE.OutlineEffect( renderer ); - * var renderingOutline = false; + * const effect = new OutlineEffect( renderer ); + * let renderingOutline = false; * * scene.onAfterRender = function () { * @@ -37,7 +39,7 @@ * } * * // How to set default outline parameters - * new THREE.OutlineEffect( renderer, { + * new OutlineEffect( renderer, { * defaultThickness: 0.01, * defaultColor: [ 0, 0, 0 ], * defaultAlpha: 0.8, @@ -54,512 +56,422 @@ * }; */ -THREE.OutlineEffect = function ( renderer, parameters ) { - - parameters = parameters || {}; - - this.enabled = true; - - var defaultThickness = parameters.defaultThickness !== undefined ? parameters.defaultThickness : 0.003; - var defaultColor = new THREE.Color().fromArray( parameters.defaultColor !== undefined ? parameters.defaultColor : [ 0, 0, 0 ] ); - var defaultAlpha = parameters.defaultAlpha !== undefined ? parameters.defaultAlpha : 1.0; - var defaultKeepAlive = parameters.defaultKeepAlive !== undefined ? parameters.defaultKeepAlive : false; - - // object.material.uuid -> outlineMaterial or - // object.material[ n ].uuid -> outlineMaterial - // save at the outline material creation and release - // if it's unused removeThresholdCount frames - // unless keepAlive is true. - var cache = {}; - - var removeThresholdCount = 60; - - // outlineMaterial.uuid -> object.material or - // outlineMaterial.uuid -> object.material[ n ] - // save before render and release after render. - var originalMaterials = {}; - - // object.uuid -> originalOnBeforeRender - // save before render and release after render. - var originalOnBeforeRenders = {}; - - //this.cache = cache; // for debug - - var uniformsOutline = { - outlineThickness: { value: defaultThickness }, - outlineColor: { value: defaultColor }, - outlineAlpha: { value: defaultAlpha } - }; - - var vertexShader = [ - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - - 'uniform float outlineThickness;', - - 'vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {', - ' float thickness = outlineThickness;', - ' const float ratio = 1.0;', // TODO: support outline thickness ratio for each vertex - ' vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );', - // NOTE: subtract pos2 from pos because BackSide objectNormal is negative - ' vec4 norm = normalize( pos - pos2 );', - ' return pos + norm * thickness * pos.w * ratio;', - '}', + class OutlineEffect { + + constructor( renderer, parameters = {} ) { + + this.enabled = true; + const defaultThickness = parameters.defaultThickness !== undefined ? parameters.defaultThickness : 0.003; + const defaultColor = new THREE.Color().fromArray( parameters.defaultColor !== undefined ? parameters.defaultColor : [ 0, 0, 0 ] ); + const defaultAlpha = parameters.defaultAlpha !== undefined ? parameters.defaultAlpha : 1.0; + const defaultKeepAlive = parameters.defaultKeepAlive !== undefined ? parameters.defaultKeepAlive : false; // object.material.uuid -> outlineMaterial or + // object.material[ n ].uuid -> outlineMaterial + // save at the outline material creation and release + // if it's unused removeThresholdCount frames + // unless keepAlive is true. + + const cache = {}; + const removeThresholdCount = 60; // outlineMaterial.uuid -> object.material or + // outlineMaterial.uuid -> object.material[ n ] + // save before render and release after render. + + const originalMaterials = {}; // object.uuid -> originalOnBeforeRender + // save before render and release after render. + + const originalOnBeforeRenders = {}; //this.cache = cache; // for debug + + const uniformsOutline = { + outlineThickness: { + value: defaultThickness + }, + outlineColor: { + value: defaultColor + }, + outlineAlpha: { + value: defaultAlpha + } + }; + const vertexShader = [ '#include ', '#include ', '#include ', '#include ', '#include ', '#include ', '#include ', '#include ', 'uniform float outlineThickness;', 'vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {', ' float thickness = outlineThickness;', ' const float ratio = 1.0;', // TODO: support outline thickness ratio for each vertex + ' vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );', // NOTE: subtract pos2 from pos because THREE.BackSide objectNormal is negative + ' vec4 norm = normalize( pos - pos2 );', ' return pos + norm * thickness * pos.w * ratio;', '}', 'void main() {', ' #include ', ' #include ', ' #include ', ' #include ', ' #include ', ' #include ', ' #include ', ' #include ', ' #include ', ' #include ', ' vec3 outlineNormal = - objectNormal;', // the outline material is always rendered with THREE.BackSide + ' gl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );', ' #include ', ' #include ', ' #include ', '}' ].join( '\n' ); + const fragmentShader = [ '#include ', '#include ', '#include ', '#include ', 'uniform vec3 outlineColor;', 'uniform float outlineAlpha;', 'void main() {', ' #include ', ' #include ', ' gl_FragColor = vec4( outlineColor, outlineAlpha );', ' #include ', ' #include ', ' #include ', ' #include ', '}' ].join( '\n' ); + + function createMaterial() { + + return new THREE.ShaderMaterial( { + type: 'OutlineEffect', + uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib[ 'fog' ], THREE.UniformsLib[ 'displacementmap' ], uniformsOutline ] ), + vertexShader: vertexShader, + fragmentShader: fragmentShader, + side: THREE.BackSide + } ); - 'void main() {', + } - ' #include ', + function getOutlineMaterialFromCache( originalMaterial ) { - ' #include ', - ' #include ', - ' #include ', - ' #include ', + let data = cache[ originalMaterial.uuid ]; - ' #include ', - ' #include ', - ' #include ', - ' #include ', - ' #include ', + if ( data === undefined ) { - ' vec3 outlineNormal = - objectNormal;', // the outline material is always rendered with THREE.BackSide + data = { + material: createMaterial(), + used: true, + keepAlive: defaultKeepAlive, + count: 0 + }; + cache[ originalMaterial.uuid ] = data; - ' gl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );', + } - ' #include ', - ' #include ', - ' #include ', + data.used = true; + return data.material; - '}', + } - ].join( '\n' ); + function getOutlineMaterial( originalMaterial ) { - var fragmentShader = [ + const outlineMaterial = getOutlineMaterialFromCache( originalMaterial ); + originalMaterials[ outlineMaterial.uuid ] = originalMaterial; + updateOutlineMaterial( outlineMaterial, originalMaterial ); + return outlineMaterial; - '#include ', - '#include ', - '#include ', - '#include ', + } - 'uniform vec3 outlineColor;', - 'uniform float outlineAlpha;', + function isCompatible( object ) { - 'void main() {', + const geometry = object.geometry; + let hasNormals = false; - ' #include ', - ' #include ', + if ( object.geometry !== undefined ) { - ' gl_FragColor = vec4( outlineColor, outlineAlpha );', + if ( geometry.isBufferGeometry ) { - ' #include ', - ' #include ', - ' #include ', - ' #include ', + hasNormals = geometry.attributes.normal !== undefined; - '}' + } else { - ].join( '\n' ); + hasNormals = true; // the renderer always produces a normal attribute for Geometry - function createMaterial() { + } - return new THREE.ShaderMaterial( { - type: 'OutlineEffect', - uniforms: THREE.UniformsUtils.merge( [ - THREE.UniformsLib[ 'fog' ], - THREE.UniformsLib[ 'displacementmap' ], - uniformsOutline - ] ), - vertexShader: vertexShader, - fragmentShader: fragmentShader, - side: THREE.BackSide - } ); + } - } + return object.isMesh === true && object.material !== undefined && hasNormals === true; - function getOutlineMaterialFromCache( originalMaterial ) { + } - var data = cache[ originalMaterial.uuid ]; + function setOutlineMaterial( object ) { - if ( data === undefined ) { + if ( isCompatible( object ) === false ) return; - data = { - material: createMaterial(), - used: true, - keepAlive: defaultKeepAlive, - count: 0 - }; + if ( Array.isArray( object.material ) ) { - cache[ originalMaterial.uuid ] = data; + for ( let i = 0, il = object.material.length; i < il; i ++ ) { - } + object.material[ i ] = getOutlineMaterial( object.material[ i ] ); - data.used = true; + } - return data.material; + } else { - } + object.material = getOutlineMaterial( object.material ); - function getOutlineMaterial( originalMaterial ) { + } - var outlineMaterial = getOutlineMaterialFromCache( originalMaterial ); + originalOnBeforeRenders[ object.uuid ] = object.onBeforeRender; + object.onBeforeRender = onBeforeRender; - originalMaterials[ outlineMaterial.uuid ] = originalMaterial; + } - updateOutlineMaterial( outlineMaterial, originalMaterial ); + function restoreOriginalMaterial( object ) { - return outlineMaterial; + if ( isCompatible( object ) === false ) return; - } + if ( Array.isArray( object.material ) ) { - function isCompatible( object ) { + for ( let i = 0, il = object.material.length; i < il; i ++ ) { - var geometry = object.geometry; - var hasNormals = false; + object.material[ i ] = originalMaterials[ object.material[ i ].uuid ]; - if ( object.geometry !== undefined ) { + } - if ( geometry.isBufferGeometry ) { + } else { - hasNormals = geometry.attributes.normal !== undefined; + object.material = originalMaterials[ object.material.uuid ]; - } else { + } - hasNormals = true; // the renderer always produces a normal attribute for Geometry + object.onBeforeRender = originalOnBeforeRenders[ object.uuid ]; } - } - - return ( object.isMesh === true && object.material !== undefined && hasNormals === true ); - - } - - function setOutlineMaterial( object ) { - - if ( isCompatible( object ) === false ) return; + function onBeforeRender( renderer, scene, camera, geometry, material ) { - if ( Array.isArray( object.material ) ) { + const originalMaterial = originalMaterials[ material.uuid ]; // just in case - for ( var i = 0, il = object.material.length; i < il; i ++ ) { - - object.material[ i ] = getOutlineMaterial( object.material[ i ] ); + if ( originalMaterial === undefined ) return; + updateUniforms( material, originalMaterial ); } - } else { - - object.material = getOutlineMaterial( object.material ); + function updateUniforms( material, originalMaterial ) { - } + const outlineParameters = originalMaterial.userData.outlineParameters; + material.uniforms.outlineAlpha.value = originalMaterial.opacity; - originalOnBeforeRenders[ object.uuid ] = object.onBeforeRender; - object.onBeforeRender = onBeforeRender; + if ( outlineParameters !== undefined ) { - } + if ( outlineParameters.thickness !== undefined ) material.uniforms.outlineThickness.value = outlineParameters.thickness; + if ( outlineParameters.color !== undefined ) material.uniforms.outlineColor.value.fromArray( outlineParameters.color ); + if ( outlineParameters.alpha !== undefined ) material.uniforms.outlineAlpha.value = outlineParameters.alpha; - function restoreOriginalMaterial( object ) { - - if ( isCompatible( object ) === false ) return; + } - if ( Array.isArray( object.material ) ) { + if ( originalMaterial.displacementMap ) { - for ( var i = 0, il = object.material.length; i < il; i ++ ) { + material.uniforms.displacementMap.value = originalMaterial.displacementMap; + material.uniforms.displacementScale.value = originalMaterial.displacementScale; + material.uniforms.displacementBias.value = originalMaterial.displacementBias; - object.material[ i ] = originalMaterials[ object.material[ i ].uuid ]; + } } - } else { + function updateOutlineMaterial( material, originalMaterial ) { - object.material = originalMaterials[ object.material.uuid ]; + if ( material.name === 'invisible' ) return; + const outlineParameters = originalMaterial.userData.outlineParameters; + material.skinning = originalMaterial.skinning; + material.morphTargets = originalMaterial.morphTargets; + material.morphNormals = originalMaterial.morphNormals; + material.fog = originalMaterial.fog; + material.toneMapped = originalMaterial.toneMapped; + material.premultipliedAlpha = originalMaterial.premultipliedAlpha; + material.displacementMap = originalMaterial.displacementMap; - } - - object.onBeforeRender = originalOnBeforeRenders[ object.uuid ]; - - } + if ( outlineParameters !== undefined ) { - function onBeforeRender( renderer, scene, camera, geometry, material ) { + if ( originalMaterial.visible === false ) { - var originalMaterial = originalMaterials[ material.uuid ]; + material.visible = false; - // just in case - if ( originalMaterial === undefined ) return; - - updateUniforms( material, originalMaterial ); - - } + } else { - function updateUniforms( material, originalMaterial ) { + material.visible = outlineParameters.visible !== undefined ? outlineParameters.visible : true; - var outlineParameters = originalMaterial.userData.outlineParameters; + } - material.uniforms.outlineAlpha.value = originalMaterial.opacity; + material.transparent = outlineParameters.alpha !== undefined && outlineParameters.alpha < 1.0 ? true : originalMaterial.transparent; + if ( outlineParameters.keepAlive !== undefined ) cache[ originalMaterial.uuid ].keepAlive = outlineParameters.keepAlive; - if ( outlineParameters !== undefined ) { + } else { - if ( outlineParameters.thickness !== undefined ) material.uniforms.outlineThickness.value = outlineParameters.thickness; - if ( outlineParameters.color !== undefined ) material.uniforms.outlineColor.value.fromArray( outlineParameters.color ); - if ( outlineParameters.alpha !== undefined ) material.uniforms.outlineAlpha.value = outlineParameters.alpha; - - } - - if ( originalMaterial.displacementMap ) { - - material.uniforms.displacementMap.value = originalMaterial.displacementMap; - material.uniforms.displacementScale.value = originalMaterial.displacementScale; - material.uniforms.displacementBias.value = originalMaterial.displacementBias; - - } + material.transparent = originalMaterial.transparent; + material.visible = originalMaterial.visible; - } - - function updateOutlineMaterial( material, originalMaterial ) { - - if ( material.name === 'invisible' ) return; - - var outlineParameters = originalMaterial.userData.outlineParameters; - - material.skinning = originalMaterial.skinning; - material.morphTargets = originalMaterial.morphTargets; - material.morphNormals = originalMaterial.morphNormals; - material.fog = originalMaterial.fog; - material.toneMapped = originalMaterial.toneMapped; - material.premultipliedAlpha = originalMaterial.premultipliedAlpha; - material.displacementMap = originalMaterial.displacementMap; + } - if ( outlineParameters !== undefined ) { + if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false; - if ( originalMaterial.visible === false ) { + if ( originalMaterial.clippingPlanes ) { - material.visible = false; + material.clipping = true; + material.clippingPlanes = originalMaterial.clippingPlanes; + material.clipIntersection = originalMaterial.clipIntersection; + material.clipShadows = originalMaterial.clipShadows; - } else { + } - material.visible = ( outlineParameters.visible !== undefined ) ? outlineParameters.visible : true; + material.version = originalMaterial.version; // update outline material if necessary } - material.transparent = ( outlineParameters.alpha !== undefined && outlineParameters.alpha < 1.0 ) ? true : originalMaterial.transparent; + function cleanupCache() { - if ( outlineParameters.keepAlive !== undefined ) cache[ originalMaterial.uuid ].keepAlive = outlineParameters.keepAlive; + let keys; // clear originialMaterials - } else { + keys = Object.keys( originalMaterials ); - material.transparent = originalMaterial.transparent; - material.visible = originalMaterial.visible; + for ( let i = 0, il = keys.length; i < il; i ++ ) { - } + originalMaterials[ keys[ i ] ] = undefined; - if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false; + } // clear originalOnBeforeRenders - if ( originalMaterial.clippingPlanes ) { - material.clipping = true; + keys = Object.keys( originalOnBeforeRenders ); - material.clippingPlanes = originalMaterial.clippingPlanes; - material.clipIntersection = originalMaterial.clipIntersection; - material.clipShadows = originalMaterial.clipShadows; + for ( let i = 0, il = keys.length; i < il; i ++ ) { - } + originalOnBeforeRenders[ keys[ i ] ] = undefined; - material.version = originalMaterial.version; // update outline material if necessary + } // remove unused outlineMaterial from cache - } - function cleanupCache() { + keys = Object.keys( cache ); - var keys; + for ( let i = 0, il = keys.length; i < il; i ++ ) { - // clear originialMaterials - keys = Object.keys( originalMaterials ); + const key = keys[ i ]; - for ( var i = 0, il = keys.length; i < il; i ++ ) { + if ( cache[ key ].used === false ) { - originalMaterials[ keys[ i ] ] = undefined; + cache[ key ].count ++; - } + if ( cache[ key ].keepAlive === false && cache[ key ].count > removeThresholdCount ) { - // clear originalOnBeforeRenders - keys = Object.keys( originalOnBeforeRenders ); + delete cache[ key ]; - for ( var i = 0, il = keys.length; i < il; i ++ ) { - - originalOnBeforeRenders[ keys[ i ] ] = undefined; - - } + } - // remove unused outlineMaterial from cache - keys = Object.keys( cache ); + } else { - for ( var i = 0, il = keys.length; i < il; i ++ ) { + cache[ key ].used = false; + cache[ key ].count = 0; - var key = keys[ i ]; - - if ( cache[ key ].used === false ) { - - cache[ key ].count ++; - - if ( cache[ key ].keepAlive === false && cache[ key ].count > removeThresholdCount ) { - - delete cache[ key ]; + } } - } else { - - cache[ key ].used = false; - cache[ key ].count = 0; - } - } - - } - - this.render = function ( scene, camera ) { - - var renderTarget; - var forceClear = false; - - if ( arguments[ 2 ] !== undefined ) { - - console.warn( 'THREE.OutlineEffect.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' ); - renderTarget = arguments[ 2 ]; + this.render = function ( scene, camera ) { - } - - if ( arguments[ 3 ] !== undefined ) { - - console.warn( 'THREE.OutlineEffect.render(): the forceClear argument has been removed. Use .clear() instead.' ); - forceClear = arguments[ 3 ]; - - } - - if ( renderTarget !== undefined ) renderer.setRenderTarget( renderTarget ); - - if ( forceClear ) renderer.clear(); + let renderTarget; + let forceClear = false; - if ( this.enabled === false ) { + if ( arguments[ 2 ] !== undefined ) { - renderer.render( scene, camera ); - return; + console.warn( 'THREE.OutlineEffect.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' ); + renderTarget = arguments[ 2 ]; - } - - var currentAutoClear = renderer.autoClear; - renderer.autoClear = this.autoClear; - - renderer.render( scene, camera ); - - renderer.autoClear = currentAutoClear; + } - this.renderOutline( scene, camera ); + if ( arguments[ 3 ] !== undefined ) { - }; + console.warn( 'THREE.OutlineEffect.render(): the forceClear argument has been removed. Use .clear() instead.' ); + forceClear = arguments[ 3 ]; - this.renderOutline = function ( scene, camera ) { + } - var currentAutoClear = renderer.autoClear; - var currentSceneAutoUpdate = scene.autoUpdate; - var currentSceneBackground = scene.background; - var currentShadowMapEnabled = renderer.shadowMap.enabled; + if ( renderTarget !== undefined ) renderer.setRenderTarget( renderTarget ); + if ( forceClear ) renderer.clear(); - scene.autoUpdate = false; - scene.background = null; - renderer.autoClear = false; - renderer.shadowMap.enabled = false; + if ( this.enabled === false ) { - scene.traverse( setOutlineMaterial ); + renderer.render( scene, camera ); + return; - renderer.render( scene, camera ); + } - scene.traverse( restoreOriginalMaterial ); + const currentAutoClear = renderer.autoClear; + renderer.autoClear = this.autoClear; + renderer.render( scene, camera ); + renderer.autoClear = currentAutoClear; + this.renderOutline( scene, camera ); - cleanupCache(); + }; - scene.autoUpdate = currentSceneAutoUpdate; - scene.background = currentSceneBackground; - renderer.autoClear = currentAutoClear; - renderer.shadowMap.enabled = currentShadowMapEnabled; + this.renderOutline = function ( scene, camera ) { + + const currentAutoClear = renderer.autoClear; + const currentSceneAutoUpdate = scene.autoUpdate; + const currentSceneBackground = scene.background; + const currentShadowMapEnabled = renderer.shadowMap.enabled; + scene.autoUpdate = false; + scene.background = null; + renderer.autoClear = false; + renderer.shadowMap.enabled = false; + scene.traverse( setOutlineMaterial ); + renderer.render( scene, camera ); + scene.traverse( restoreOriginalMaterial ); + cleanupCache(); + scene.autoUpdate = currentSceneAutoUpdate; + scene.background = currentSceneBackground; + renderer.autoClear = currentAutoClear; + renderer.shadowMap.enabled = currentShadowMapEnabled; - }; + }; + /* + * See #9918 + * + * The following property copies and wrapper methods enable + * OutlineEffect to be called from other *Effect, like + * + * effect = new StereoEffect( new OutlineEffect( renderer ) ); + * + * function render () { + * + * effect.render( scene, camera ); + * + * } + */ + + + this.autoClear = renderer.autoClear; + this.domElement = renderer.domElement; + this.shadowMap = renderer.shadowMap; + + this.clear = function ( color, depth, stencil ) { + + renderer.clear( color, depth, stencil ); - /* - * See #9918 - * - * The following property copies and wrapper methods enable - * THREE.OutlineEffect to be called from other *Effect, like - * - * effect = new THREE.StereoEffect( new THREE.OutlineEffect( renderer ) ); - * - * function render () { - * - * effect.render( scene, camera ); - * - * } - */ - this.autoClear = renderer.autoClear; - this.domElement = renderer.domElement; - this.shadowMap = renderer.shadowMap; + }; - this.clear = function ( color, depth, stencil ) { + this.getPixelRatio = function () { - renderer.clear( color, depth, stencil ); + return renderer.getPixelRatio(); - }; + }; - this.getPixelRatio = function () { + this.setPixelRatio = function ( value ) { - return renderer.getPixelRatio(); + renderer.setPixelRatio( value ); - }; + }; - this.setPixelRatio = function ( value ) { + this.getSize = function ( target ) { - renderer.setPixelRatio( value ); + return renderer.getSize( target ); - }; + }; - this.getSize = function ( target ) { + this.setSize = function ( width, height, updateStyle ) { - return renderer.getSize( target ); + renderer.setSize( width, height, updateStyle ); - }; + }; - this.setSize = function ( width, height, updateStyle ) { + this.setViewport = function ( x, y, width, height ) { - renderer.setSize( width, height, updateStyle ); + renderer.setViewport( x, y, width, height ); - }; + }; - this.setViewport = function ( x, y, width, height ) { + this.setScissor = function ( x, y, width, height ) { - renderer.setViewport( x, y, width, height ); + renderer.setScissor( x, y, width, height ); - }; + }; - this.setScissor = function ( x, y, width, height ) { + this.setScissorTest = function ( boolean ) { - renderer.setScissor( x, y, width, height ); + renderer.setScissorTest( boolean ); - }; + }; - this.setScissorTest = function ( boolean ) { + this.setRenderTarget = function ( renderTarget ) { - renderer.setScissorTest( boolean ); + renderer.setRenderTarget( renderTarget ); - }; + }; - this.setRenderTarget = function ( renderTarget ) { + } - renderer.setRenderTarget( renderTarget ); + } - }; + THREE.OutlineEffect = OutlineEffect; -}; +} )(); diff --git a/examples/js/effects/ParallaxBarrierEffect.js b/examples/js/effects/ParallaxBarrierEffect.js index 4342243387f8cc..409ea922573e41 100644 --- a/examples/js/effects/ParallaxBarrierEffect.js +++ b/examples/js/effects/ParallaxBarrierEffect.js @@ -1,97 +1,75 @@ -THREE.ParallaxBarrierEffect = function ( renderer ) { +( function () { - var _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); + class ParallaxBarrierEffect { - var _scene = new THREE.Scene(); + constructor( renderer ) { - var _stereo = new THREE.StereoCamera(); + const _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat }; + const _scene = new THREE.Scene(); - var _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params ); - var _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params ); + const _stereo = new THREE.StereoCamera(); - var _material = new THREE.ShaderMaterial( { + const _params = { + minFilter: THREE.LinearFilter, + magFilter: THREE.NearestFilter, + format: THREE.RGBAFormat + }; - uniforms: { + const _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params ); - 'mapLeft': { value: _renderTargetL.texture }, - 'mapRight': { value: _renderTargetR.texture } + const _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params ); - }, + const _material = new THREE.ShaderMaterial( { + uniforms: { + 'mapLeft': { + value: _renderTargetL.texture + }, + 'mapRight': { + value: _renderTargetR.texture + } + }, + vertexShader: [ 'varying vec2 vUv;', 'void main() {', ' vUv = vec2( uv.x, uv.y );', ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}' ].join( '\n' ), + fragmentShader: [ 'uniform sampler2D mapLeft;', 'uniform sampler2D mapRight;', 'varying vec2 vUv;', 'void main() {', ' vec2 uv = vUv;', ' if ( ( mod( gl_FragCoord.y, 2.0 ) ) > 1.00 ) {', ' gl_FragColor = texture2D( mapLeft, uv );', ' } else {', ' gl_FragColor = texture2D( mapRight, uv );', ' }', '}' ].join( '\n' ) + } ); - vertexShader: [ + const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ); - 'varying vec2 vUv;', + _scene.add( mesh ); - 'void main() {', + this.setSize = function ( width, height ) { - ' vUv = vec2( uv.x, uv.y );', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + renderer.setSize( width, height ); + const pixelRatio = renderer.getPixelRatio(); - '}' + _renderTargetL.setSize( width * pixelRatio, height * pixelRatio ); - ].join( '\n' ), + _renderTargetR.setSize( width * pixelRatio, height * pixelRatio ); - fragmentShader: [ + }; - 'uniform sampler2D mapLeft;', - 'uniform sampler2D mapRight;', - 'varying vec2 vUv;', + this.render = function ( scene, camera ) { - 'void main() {', + scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); - ' vec2 uv = vUv;', + _stereo.update( camera ); - ' if ( ( mod( gl_FragCoord.y, 2.0 ) ) > 1.00 ) {', + renderer.setRenderTarget( _renderTargetL ); + renderer.clear(); + renderer.render( scene, _stereo.cameraL ); + renderer.setRenderTarget( _renderTargetR ); + renderer.clear(); + renderer.render( scene, _stereo.cameraR ); + renderer.setRenderTarget( null ); + renderer.render( _scene, _camera ); - ' gl_FragColor = texture2D( mapLeft, uv );', + }; - ' } else {', + } - ' gl_FragColor = texture2D( mapRight, uv );', + } - ' }', + THREE.ParallaxBarrierEffect = ParallaxBarrierEffect; - '}' - - ].join( '\n' ) - - } ); - - var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ); - _scene.add( mesh ); - - this.setSize = function ( width, height ) { - - renderer.setSize( width, height ); - - var pixelRatio = renderer.getPixelRatio(); - - _renderTargetL.setSize( width * pixelRatio, height * pixelRatio ); - _renderTargetR.setSize( width * pixelRatio, height * pixelRatio ); - - }; - - this.render = function ( scene, camera ) { - - scene.updateMatrixWorld(); - - if ( camera.parent === null ) camera.updateMatrixWorld(); - - _stereo.update( camera ); - - renderer.setRenderTarget( _renderTargetL ); - renderer.clear(); - renderer.render( scene, _stereo.cameraL ); - - renderer.setRenderTarget( _renderTargetR ); - renderer.clear(); - renderer.render( scene, _stereo.cameraR ); - - renderer.setRenderTarget( null ); - renderer.render( _scene, _camera ); - - }; - -}; +} )(); diff --git a/examples/js/effects/PeppersGhostEffect.js b/examples/js/effects/PeppersGhostEffect.js index dda5a326d936c2..b7ca0567e4c311 100644 --- a/examples/js/effects/PeppersGhostEffect.js +++ b/examples/js/effects/PeppersGhostEffect.js @@ -1,142 +1,166 @@ -/** +( function () { + + /** * peppers ghost effect based on http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS */ -THREE.PeppersGhostEffect = function ( renderer ) { + class PeppersGhostEffect { - var scope = this; + constructor( renderer ) { - scope.cameraDistance = 15; - scope.reflectFromAbove = false; + const scope = this; + scope.cameraDistance = 15; + scope.reflectFromAbove = false; // Internals - // Internals - var _halfWidth, _width, _height; + let _halfWidth, _width, _height; - var _cameraF = new THREE.PerspectiveCamera(); //front - var _cameraB = new THREE.PerspectiveCamera(); //back - var _cameraL = new THREE.PerspectiveCamera(); //left - var _cameraR = new THREE.PerspectiveCamera(); //right + const _cameraF = new THREE.PerspectiveCamera(); //front - var _position = new THREE.Vector3(); - var _quaternion = new THREE.Quaternion(); - var _scale = new THREE.Vector3(); - // Initialization - renderer.autoClear = false; + const _cameraB = new THREE.PerspectiveCamera(); //back - this.setSize = function ( width, height ) { - _halfWidth = width / 2; - if ( width < height ) { + const _cameraL = new THREE.PerspectiveCamera(); //left - _width = width / 3; - _height = width / 3; - } else { + const _cameraR = new THREE.PerspectiveCamera(); //right - _width = height / 3; - _height = height / 3; - } + const _position = new THREE.Vector3(); - renderer.setSize( width, height ); + const _quaternion = new THREE.Quaternion(); - }; + const _scale = new THREE.Vector3(); // Initialization - this.render = function ( scene, camera ) { - scene.updateMatrixWorld(); + renderer.autoClear = false; - if ( camera.parent === null ) camera.updateMatrixWorld(); + this.setSize = function ( width, height ) { - camera.matrixWorld.decompose( _position, _quaternion, _scale ); + _halfWidth = width / 2; - // front - _cameraF.position.copy( _position ); - _cameraF.quaternion.copy( _quaternion ); - _cameraF.translateZ( scope.cameraDistance ); - _cameraF.lookAt( scene.position ); + if ( width < height ) { - // back - _cameraB.position.copy( _position ); - _cameraB.quaternion.copy( _quaternion ); - _cameraB.translateZ( - ( scope.cameraDistance ) ); - _cameraB.lookAt( scene.position ); - _cameraB.rotation.z += 180 * ( Math.PI / 180 ); + _width = width / 3; + _height = width / 3; - // left - _cameraL.position.copy( _position ); - _cameraL.quaternion.copy( _quaternion ); - _cameraL.translateX( - ( scope.cameraDistance ) ); - _cameraL.lookAt( scene.position ); - _cameraL.rotation.x += 90 * ( Math.PI / 180 ); + } else { - // right - _cameraR.position.copy( _position ); - _cameraR.quaternion.copy( _quaternion ); - _cameraR.translateX( scope.cameraDistance ); - _cameraR.lookAt( scene.position ); - _cameraR.rotation.x += 90 * ( Math.PI / 180 ); + _width = height / 3; + _height = height / 3; + } - renderer.clear(); - renderer.setScissorTest( true ); + renderer.setSize( width, height ); - renderer.setScissor( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height ); - renderer.setViewport( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height ); + }; - if ( scope.reflectFromAbove ) { + this.render = function ( scene, camera ) { - renderer.render( scene, _cameraB ); + scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); + camera.matrixWorld.decompose( _position, _quaternion, _scale ); // front - } else { + _cameraF.position.copy( _position ); - renderer.render( scene, _cameraF ); + _cameraF.quaternion.copy( _quaternion ); - } + _cameraF.translateZ( scope.cameraDistance ); - renderer.setScissor( _halfWidth - ( _width / 2 ), 0, _width, _height ); - renderer.setViewport( _halfWidth - ( _width / 2 ), 0, _width, _height ); + _cameraF.lookAt( scene.position ); // back - if ( scope.reflectFromAbove ) { - renderer.render( scene, _cameraF ); + _cameraB.position.copy( _position ); - } else { + _cameraB.quaternion.copy( _quaternion ); - renderer.render( scene, _cameraB ); + _cameraB.translateZ( - scope.cameraDistance ); - } + _cameraB.lookAt( scene.position ); - renderer.setScissor( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height ); - renderer.setViewport( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height ); + _cameraB.rotation.z += 180 * ( Math.PI / 180 ); // left - if ( scope.reflectFromAbove ) { + _cameraL.position.copy( _position ); - renderer.render( scene, _cameraR ); + _cameraL.quaternion.copy( _quaternion ); - } else { + _cameraL.translateX( - scope.cameraDistance ); - renderer.render( scene, _cameraL ); + _cameraL.lookAt( scene.position ); - } + _cameraL.rotation.x += 90 * ( Math.PI / 180 ); // right - renderer.setScissor( _halfWidth + ( _width / 2 ), _height, _width, _height ); - renderer.setViewport( _halfWidth + ( _width / 2 ), _height, _width, _height ); + _cameraR.position.copy( _position ); - if ( scope.reflectFromAbove ) { + _cameraR.quaternion.copy( _quaternion ); - renderer.render( scene, _cameraL ); + _cameraR.translateX( scope.cameraDistance ); - } else { + _cameraR.lookAt( scene.position ); - renderer.render( scene, _cameraR ); + _cameraR.rotation.x += 90 * ( Math.PI / 180 ); + renderer.clear(); + renderer.setScissorTest( true ); + renderer.setScissor( _halfWidth - _width / 2, _height * 2, _width, _height ); + renderer.setViewport( _halfWidth - _width / 2, _height * 2, _width, _height ); - } + if ( scope.reflectFromAbove ) { + + renderer.render( scene, _cameraB ); + + } else { + + renderer.render( scene, _cameraF ); + + } + + renderer.setScissor( _halfWidth - _width / 2, 0, _width, _height ); + renderer.setViewport( _halfWidth - _width / 2, 0, _width, _height ); + + if ( scope.reflectFromAbove ) { + + renderer.render( scene, _cameraF ); + + } else { + + renderer.render( scene, _cameraB ); + + } - renderer.setScissorTest( false ); + renderer.setScissor( _halfWidth - _width / 2 - _width, _height, _width, _height ); + renderer.setViewport( _halfWidth - _width / 2 - _width, _height, _width, _height ); + + if ( scope.reflectFromAbove ) { + + renderer.render( scene, _cameraR ); + + } else { + + renderer.render( scene, _cameraL ); + + } + + renderer.setScissor( _halfWidth + _width / 2, _height, _width, _height ); + renderer.setViewport( _halfWidth + _width / 2, _height, _width, _height ); + + if ( scope.reflectFromAbove ) { + + renderer.render( scene, _cameraL ); + + } else { + + renderer.render( scene, _cameraR ); + + } + + renderer.setScissorTest( false ); + + }; + + } - }; + } + THREE.PeppersGhostEffect = PeppersGhostEffect; -}; +} )(); diff --git a/examples/js/effects/StereoEffect.js b/examples/js/effects/StereoEffect.js index dcd132d4d6c4f6..8a7a0944affed9 100644 --- a/examples/js/effects/StereoEffect.js +++ b/examples/js/effects/StereoEffect.js @@ -1,44 +1,50 @@ -THREE.StereoEffect = function ( renderer ) { +( function () { - var _stereo = new THREE.StereoCamera(); - _stereo.aspect = 0.5; - var size = new THREE.Vector2(); + class StereoEffect { - this.setEyeSeparation = function ( eyeSep ) { + constructor( renderer ) { - _stereo.eyeSep = eyeSep; + const _stereo = new THREE.StereoCamera(); - }; + _stereo.aspect = 0.5; + const size = new THREE.Vector2(); - this.setSize = function ( width, height ) { + this.setEyeSeparation = function ( eyeSep ) { - renderer.setSize( width, height ); + _stereo.eyeSep = eyeSep; - }; + }; - this.render = function ( scene, camera ) { + this.setSize = function ( width, height ) { - scene.updateMatrixWorld(); + renderer.setSize( width, height ); - if ( camera.parent === null ) camera.updateMatrixWorld(); + }; - _stereo.update( camera ); + this.render = function ( scene, camera ) { - renderer.getSize( size ); + scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); - if ( renderer.autoClear ) renderer.clear(); - renderer.setScissorTest( true ); + _stereo.update( camera ); - renderer.setScissor( 0, 0, size.width / 2, size.height ); - renderer.setViewport( 0, 0, size.width / 2, size.height ); - renderer.render( scene, _stereo.cameraL ); + renderer.getSize( size ); + if ( renderer.autoClear ) renderer.clear(); + renderer.setScissorTest( true ); + renderer.setScissor( 0, 0, size.width / 2, size.height ); + renderer.setViewport( 0, 0, size.width / 2, size.height ); + renderer.render( scene, _stereo.cameraL ); + renderer.setScissor( size.width / 2, 0, size.width / 2, size.height ); + renderer.setViewport( size.width / 2, 0, size.width / 2, size.height ); + renderer.render( scene, _stereo.cameraR ); + renderer.setScissorTest( false ); - renderer.setScissor( size.width / 2, 0, size.width / 2, size.height ); - renderer.setViewport( size.width / 2, 0, size.width / 2, size.height ); - renderer.render( scene, _stereo.cameraR ); + }; - renderer.setScissorTest( false ); + } - }; + } -}; + THREE.StereoEffect = StereoEffect; + +} )(); diff --git a/examples/js/environments/DebugEnvironment.js b/examples/js/environments/DebugEnvironment.js new file mode 100644 index 00000000000000..5d30a317cfb2d2 --- /dev/null +++ b/examples/js/environments/DebugEnvironment.js @@ -0,0 +1,53 @@ +( function () { + + class DebugEnvironment extends THREE.Scene { + + constructor() { + + super(); + const geometry = new THREE.BoxGeometry(); + geometry.deleteAttribute( 'uv' ); + const roomMaterial = new THREE.MeshStandardMaterial( { + metalness: 0, + side: THREE.BackSide + } ); + const room = new THREE.Mesh( geometry, roomMaterial ); + room.scale.setScalar( 10 ); + this.add( room ); + const mainLight = new THREE.PointLight( 0xffffff, 50, 0, 2 ); + this.add( mainLight ); + const material1 = new THREE.MeshLambertMaterial( { + color: 0xff0000, + emissive: 0xffffff, + emissiveIntensity: 10 + } ); + const light1 = new THREE.Mesh( geometry, material1 ); + light1.position.set( - 5, 2, 0 ); + light1.scale.set( 0.1, 1, 1 ); + this.add( light1 ); + const material2 = new THREE.MeshLambertMaterial( { + color: 0x00ff00, + emissive: 0xffffff, + emissiveIntensity: 10 + } ); + const light2 = new THREE.Mesh( geometry, material2 ); + light2.position.set( 0, 5, 0 ); + light2.scale.set( 1, 0.1, 1 ); + this.add( light2 ); + const material3 = new THREE.MeshLambertMaterial( { + color: 0x0000ff, + emissive: 0xffffff, + emissiveIntensity: 10 + } ); + const light3 = new THREE.Mesh( geometry, material3 ); + light3.position.set( 2, 1, 5 ); + light3.scale.set( 1.5, 2, 0.1 ); + this.add( light3 ); + + } + + } + + THREE.DebugEnvironment = DebugEnvironment; + +} )(); diff --git a/examples/js/environments/RoomEnvironment.js b/examples/js/environments/RoomEnvironment.js new file mode 100644 index 00000000000000..f698528f84338e --- /dev/null +++ b/examples/js/environments/RoomEnvironment.js @@ -0,0 +1,100 @@ +( function () { + + /** + * https://github.com/google/model-viewer/blob/master/packages/model-viewer/src/three-components/EnvironmentScene.ts + */ + + class RoomEnvironment extends THREE.Scene { + + constructor() { + + super(); + const geometry = new THREE.BoxGeometry(); + geometry.deleteAttribute( 'uv' ); + const roomMaterial = new THREE.MeshStandardMaterial( { + side: THREE.BackSide + } ); + const boxMaterial = new THREE.MeshStandardMaterial(); + const mainLight = new THREE.PointLight( 0xffffff, 5.0, 28, 2 ); + mainLight.position.set( 0.418, 16.199, 0.300 ); + this.add( mainLight ); + const room = new THREE.Mesh( geometry, roomMaterial ); + room.position.set( - 0.757, 13.219, 0.717 ); + room.scale.set( 31.713, 28.305, 28.591 ); + this.add( room ); + const box1 = new THREE.Mesh( geometry, boxMaterial ); + box1.position.set( - 10.906, 2.009, 1.846 ); + box1.rotation.set( 0, - 0.195, 0 ); + box1.scale.set( 2.328, 7.905, 4.651 ); + this.add( box1 ); + const box2 = new THREE.Mesh( geometry, boxMaterial ); + box2.position.set( - 5.607, - 0.754, - 0.758 ); + box2.rotation.set( 0, 0.994, 0 ); + box2.scale.set( 1.970, 1.534, 3.955 ); + this.add( box2 ); + const box3 = new THREE.Mesh( geometry, boxMaterial ); + box3.position.set( 6.167, 0.857, 7.803 ); + box3.rotation.set( 0, 0.561, 0 ); + box3.scale.set( 3.927, 6.285, 3.687 ); + this.add( box3 ); + const box4 = new THREE.Mesh( geometry, boxMaterial ); + box4.position.set( - 2.017, 0.018, 6.124 ); + box4.rotation.set( 0, 0.333, 0 ); + box4.scale.set( 2.002, 4.566, 2.064 ); + this.add( box4 ); + const box5 = new THREE.Mesh( geometry, boxMaterial ); + box5.position.set( 2.291, - 0.756, - 2.621 ); + box5.rotation.set( 0, - 0.286, 0 ); + box5.scale.set( 1.546, 1.552, 1.496 ); + this.add( box5 ); + const box6 = new THREE.Mesh( geometry, boxMaterial ); + box6.position.set( - 2.193, - 0.369, - 5.547 ); + box6.rotation.set( 0, 0.516, 0 ); + box6.scale.set( 3.875, 3.487, 2.986 ); + this.add( box6 ); // -x right + + const light1 = new THREE.Mesh( geometry, createAreaLightMaterial( 50 ) ); + light1.position.set( - 16.116, 14.37, 8.208 ); + light1.scale.set( 0.1, 2.428, 2.739 ); + this.add( light1 ); // -x left + + const light2 = new THREE.Mesh( geometry, createAreaLightMaterial( 50 ) ); + light2.position.set( - 16.109, 18.021, - 8.207 ); + light2.scale.set( 0.1, 2.425, 2.751 ); + this.add( light2 ); // +x + + const light3 = new THREE.Mesh( geometry, createAreaLightMaterial( 17 ) ); + light3.position.set( 14.904, 12.198, - 1.832 ); + light3.scale.set( 0.15, 4.265, 6.331 ); + this.add( light3 ); // +z + + const light4 = new THREE.Mesh( geometry, createAreaLightMaterial( 43 ) ); + light4.position.set( - 0.462, 8.89, 14.520 ); + light4.scale.set( 4.38, 5.441, 0.088 ); + this.add( light4 ); // -z + + const light5 = new THREE.Mesh( geometry, createAreaLightMaterial( 20 ) ); + light5.position.set( 3.235, 11.486, - 12.541 ); + light5.scale.set( 2.5, 2.0, 0.1 ); + this.add( light5 ); // +y + + const light6 = new THREE.Mesh( geometry, createAreaLightMaterial( 100 ) ); + light6.position.set( 0.0, 20.0, 0.0 ); + light6.scale.set( 1.0, 0.1, 1.0 ); + this.add( light6 ); + + } + + } + + function createAreaLightMaterial( intensity ) { + + const material = new THREE.MeshBasicMaterial(); + material.color.setScalar( intensity ); + return material; + + } + + THREE.RoomEnvironment = RoomEnvironment; + +} )(); diff --git a/examples/js/exporters/ColladaExporter.js b/examples/js/exporters/ColladaExporter.js index 3acfebc1228567..c3724e1be7e242 100644 --- a/examples/js/exporters/ColladaExporter.js +++ b/examples/js/exporters/ColladaExporter.js @@ -1,60 +1,53 @@ -/** +( function () { + + /** * https://github.com/gkjohnson/collada-exporter-js * * Usage: - * var exporter = new THREE.ColladaExporter(); + * const exporter = new ColladaExporter(); * - * var data = exporter.parse(mesh); + * const data = exporter.parse(mesh); * * Format Definition: * https://www.khronos.org/collada/ */ -THREE.ColladaExporter = function () {}; + class ColladaExporter { -THREE.ColladaExporter.prototype = { + parse( object, onDone, options = {} ) { - constructor: THREE.ColladaExporter, + options = Object.assign( { + version: '1.4.1', + author: null, + textureDirectory: '' + }, options ); - parse: function ( object, onDone, options ) { + if ( options.textureDirectory !== '' ) { - options = options || {}; + options.textureDirectory = `${options.textureDirectory}/`.replace( /\\/g, '/' ).replace( /\/+/g, '/' ); - options = Object.assign( { - version: '1.4.1', - author: null, - textureDirectory: '', - }, options ); + } - if ( options.textureDirectory !== '' ) { + const version = options.version; - options.textureDirectory = `${ options.textureDirectory }/` - .replace( /\\/g, '/' ) - .replace( /\/+/g, '/' ); + if ( version !== '1.4.1' && version !== '1.5.0' ) { - } + console.warn( `ColladaExporter : Version ${version} not supported for export. Only 1.4.1 and 1.5.0.` ); + return null; - var version = options.version; - if ( version !== '1.4.1' && version !== '1.5.0' ) { + } // Convert the urdf xml into a well-formatted, indented format - console.warn( `ColladaExporter : Version ${ version } not supported for export. Only 1.4.1 and 1.5.0.` ); - return null; - - } - // Convert the urdf xml into a well-formatted, indented format - function format( urdf ) { + function format( urdf ) { - var IS_END_TAG = /^<\//; - var IS_SELF_CLOSING = /(\?>$)|(\/>$)/; - var HAS_TEXT = /<[^>]+>[^<]*<\/[^<]+>/; + const IS_END_TAG = /^<\//; + const IS_SELF_CLOSING = /(\?>$)|(\/>$)/; + const HAS_TEXT = /<[^>]+>[^<]*<\/[^<]+>/; - var pad = ( ch, num ) => ( num > 0 ? ch + pad( ch, num - 1 ) : '' ); + const pad = ( ch, num ) => num > 0 ? ch + pad( ch, num - 1 ) : ''; - var tagnum = 0; - return urdf - .match( /(<[^>]+>[^<]+<\/[^<]+>)|(<[^>]+>)/g ) - .map( tag => { + let tagnum = 0; + return urdf.match( /(<[^>]+>[^<]+<\/[^<]+>)|(<[^>]+>)/g ).map( tag => { if ( ! HAS_TEXT.test( tag ) && ! IS_SELF_CLOSING.test( tag ) && IS_END_TAG.test( tag ) ) { @@ -62,7 +55,7 @@ THREE.ColladaExporter.prototype = { } - var res = `${ pad( ' ', tagnum ) }${ tag }`; + const res = `${pad( ' ', tagnum )}${tag}`; if ( ! HAS_TEXT.test( tag ) && ! IS_SELF_CLOSING.test( tag ) && ! IS_END_TAG.test( tag ) ) { @@ -72,592 +65,403 @@ THREE.ColladaExporter.prototype = { return res; - } ) - .join( '\n' ); + } ).join( '\n' ); - } + } // Convert an image into a png format for saving + + + function base64ToBuffer( str ) { - // Convert an image into a png format for saving - function base64ToBuffer( str ) { + const b = atob( str ); + const buf = new Uint8Array( b.length ); - var b = atob( str ); - var buf = new Uint8Array( b.length ); + for ( let i = 0, l = buf.length; i < l; i ++ ) { - for ( var i = 0, l = buf.length; i < l; i ++ ) { + buf[ i ] = b.charCodeAt( i ); + + } - buf[ i ] = b.charCodeAt( i ); + return buf; } - return buf; + let canvas, ctx; - } + function imageToData( image, ext ) { - var canvas, ctx; - function imageToData( image, ext ) { + canvas = canvas || document.createElement( 'canvas' ); + ctx = ctx || canvas.getContext( '2d' ); + canvas.width = image.width; + canvas.height = image.height; + ctx.drawImage( image, 0, 0 ); // Get the base64 encoded data - canvas = canvas || document.createElement( 'canvas' ); - ctx = ctx || canvas.getContext( '2d' ); + const base64data = canvas.toDataURL( `image/${ext}`, 1 ).replace( /^data:image\/(png|jpg);base64,/, '' ); // Convert to a uint8 array - canvas.width = image.width; - canvas.height = image.height; + return base64ToBuffer( base64data ); - ctx.drawImage( image, 0, 0 ); + } // gets the attribute array. Generate a new array if the attribute is interleaved - // Get the base64 encoded data - var base64data = canvas - .toDataURL( `image/${ ext }`, 1 ) - .replace( /^data:image\/(png|jpg);base64,/, '' ); - // Convert to a uint8 array - return base64ToBuffer( base64data ); + const getFuncs = [ 'getX', 'getY', 'getZ', 'getW' ]; - } + function attrBufferToArray( attr ) { + + if ( attr.isInterleavedBufferAttribute ) { - // gets the attribute array. Generate a new array if the attribute is interleaved - var getFuncs = [ 'getX', 'getY', 'getZ', 'getW' ]; - function attrBufferToArray( attr ) { + // use the typed array constructor to save on memory + const arr = new attr.array.constructor( attr.count * attr.itemSize ); + const size = attr.itemSize; - if ( attr.isInterleavedBufferAttribute ) { + for ( let i = 0, l = attr.count; i < l; i ++ ) { - // use the typed array constructor to save on memory - var arr = new attr.array.constructor( attr.count * attr.itemSize ); - var size = attr.itemSize; - for ( var i = 0, l = attr.count; i < l; i ++ ) { + for ( let j = 0; j < size; j ++ ) { - for ( var j = 0; j < size; j ++ ) { + arr[ i * size + j ] = attr[ getFuncs[ j ] ]( i ); - arr[ i * size + j ] = attr[ getFuncs[ j ] ]( i ); + } } - } + return arr; - return arr; + } else { - } else { + return attr.array; - return attr.array; + } - } + } // Returns an array of the same type starting at the `st` index, + // and `ct` length - } - // Returns an array of the same type starting at the `st` index, - // and `ct` length - function subArray( arr, st, ct ) { + function subArray( arr, st, ct ) { - if ( Array.isArray( arr ) ) return arr.slice( st, st + ct ); - else return new arr.constructor( arr.buffer, st * arr.BYTES_PER_ELEMENT, ct ); + if ( Array.isArray( arr ) ) return arr.slice( st, st + ct ); else return new arr.constructor( arr.buffer, st * arr.BYTES_PER_ELEMENT, ct ); - } + } // Returns the string for a geometry's attribute - // Returns the string for a geometry's attribute - function getAttribute( attr, name, params, type ) { - var array = attrBufferToArray( attr ); - var res = - `` + + function getAttribute( attr, name, params, type ) { - `` + - array.join( ' ' ) + - '' + + const array = attrBufferToArray( attr ); + const res = `` + `` + array.join( ' ' ) + '' + '' + `` + params.map( n => `` ).join( '' ) + '' + '' + ''; + return res; - '' + - `` + + } // Returns the string for a node's transform information - params.map( n => `` ).join( '' ) + - '' + - '' + - ''; + let transMat; - return res; + function getTransform( o ) { - } + // ensure the object's matrix is up to date + // before saving the transform + o.updateMatrix(); + transMat = transMat || new THREE.Matrix4(); + transMat.copy( o.matrix ); + transMat.transpose(); + return `${transMat.toArray().join( ' ' )}`; - // Returns the string for a node's transform information - var transMat; - function getTransform( o ) { + } // Process the given piece of geometry into the geometry library + // Returns the mesh id - // ensure the object's matrix is up to date - // before saving the transform - o.updateMatrix(); - transMat = transMat || new THREE.Matrix4(); - transMat.copy( o.matrix ); - transMat.transpose(); - return `${ transMat.toArray().join( ' ' ) }`; + function processGeometry( g ) { - } + let info = geometryInfo.get( g ); - // Process the given piece of geometry into the geometry library - // Returns the mesh id - function processGeometry( g ) { + if ( ! info ) { - var info = geometryInfo.get( g ); + // convert the geometry to bufferGeometry if it isn't already + const bufferGeometry = g; - if ( ! info ) { + if ( bufferGeometry.isBufferGeometry !== true ) { - // convert the geometry to bufferGeometry if it isn't already - var bufferGeometry = g; + throw new Error( 'THREE.ColladaExporter: Geometry is not of type THREE.BufferGeometry.' ); - if ( bufferGeometry.isBufferGeometry !== true ) { + } - throw new Error( 'THREE.ColladaExporter: Geometry is not of type THREE.BufferGeometry.' ); + const meshid = `Mesh${libraryGeometries.length + 1}`; + const indexCount = bufferGeometry.index ? bufferGeometry.index.count * bufferGeometry.index.itemSize : bufferGeometry.attributes.position.count; + const groups = bufferGeometry.groups != null && bufferGeometry.groups.length !== 0 ? bufferGeometry.groups : [ { + start: 0, + count: indexCount, + materialIndex: 0 + } ]; + const gname = g.name ? ` name="${g.name}"` : ''; + let gnode = ``; // define the geometry node and the vertices for the geometry - } + const posName = `${meshid}-position`; + const vertName = `${meshid}-vertices`; + gnode += getAttribute( bufferGeometry.attributes.position, posName, [ 'X', 'Y', 'Z' ], 'float' ); + gnode += ``; // NOTE: We're not optimizing the attribute arrays here, so they're all the same length and + // can therefore share the same triangle indices. However, MeshLab seems to have trouble opening + // models with attributes that share an offset. + // MeshLab Bug#424: https://sourceforge.net/p/meshlab/bugs/424/ + // serialize normals - var meshid = `Mesh${ libraryGeometries.length + 1 }`; + let triangleInputs = ``; - var indexCount = - bufferGeometry.index ? - bufferGeometry.index.count * bufferGeometry.index.itemSize : - bufferGeometry.attributes.position.count; + if ( 'normal' in bufferGeometry.attributes ) { - var groups = - bufferGeometry.groups != null && bufferGeometry.groups.length !== 0 ? - bufferGeometry.groups : - [ { start: 0, count: indexCount, materialIndex: 0 } ]; + const normName = `${meshid}-normal`; + gnode += getAttribute( bufferGeometry.attributes.normal, normName, [ 'X', 'Y', 'Z' ], 'float' ); + triangleInputs += ``; + } // serialize uvs - var gname = g.name ? ` name="${ g.name }"` : ''; - var gnode = ``; - // define the geometry node and the vertices for the geometry - var posName = `${ meshid }-position`; - var vertName = `${ meshid }-vertices`; - gnode += getAttribute( bufferGeometry.attributes.position, posName, [ 'X', 'Y', 'Z' ], 'float' ); - gnode += ``; + if ( 'uv' in bufferGeometry.attributes ) { - // NOTE: We're not optimizing the attribute arrays here, so they're all the same length and - // can therefore share the same triangle indices. However, MeshLab seems to have trouble opening - // models with attributes that share an offset. - // MeshLab Bug#424: https://sourceforge.net/p/meshlab/bugs/424/ + const uvName = `${meshid}-texcoord`; + gnode += getAttribute( bufferGeometry.attributes.uv, uvName, [ 'S', 'T' ], 'float' ); + triangleInputs += ``; - // serialize normals - var triangleInputs = ``; - if ( 'normal' in bufferGeometry.attributes ) { + } // serialize lightmap uvs - var normName = `${ meshid }-normal`; - gnode += getAttribute( bufferGeometry.attributes.normal, normName, [ 'X', 'Y', 'Z' ], 'float' ); - triangleInputs += ``; - } + if ( 'uv2' in bufferGeometry.attributes ) { - // serialize uvs - if ( 'uv' in bufferGeometry.attributes ) { + const uvName = `${meshid}-texcoord2`; + gnode += getAttribute( bufferGeometry.attributes.uv2, uvName, [ 'S', 'T' ], 'float' ); + triangleInputs += ``; - var uvName = `${ meshid }-texcoord`; - gnode += getAttribute( bufferGeometry.attributes.uv, uvName, [ 'S', 'T' ], 'float' ); - triangleInputs += ``; + } // serialize colors - } - // serialize lightmap uvs - if ( 'uv2' in bufferGeometry.attributes ) { + if ( 'color' in bufferGeometry.attributes ) { - var uvName = `${ meshid }-texcoord2`; - gnode += getAttribute( bufferGeometry.attributes.uv2, uvName, [ 'S', 'T' ], 'float' ); - triangleInputs += ``; + const colName = `${meshid}-color`; + gnode += getAttribute( bufferGeometry.attributes.color, colName, [ 'X', 'Y', 'Z' ], 'uint8' ); + triangleInputs += ``; - } + } - // serialize colors - if ( 'color' in bufferGeometry.attributes ) { + let indexArray = null; - var colName = `${ meshid }-color`; - gnode += getAttribute( bufferGeometry.attributes.color, colName, [ 'X', 'Y', 'Z' ], 'uint8' ); - triangleInputs += ``; + if ( bufferGeometry.index ) { - } + indexArray = attrBufferToArray( bufferGeometry.index ); - var indexArray = null; - if ( bufferGeometry.index ) { + } else { - indexArray = attrBufferToArray( bufferGeometry.index ); + indexArray = new Array( indexCount ); - } else { + for ( let i = 0, l = indexArray.length; i < l; i ++ ) indexArray[ i ] = i; - indexArray = new Array( indexCount ); - for ( var i = 0, l = indexArray.length; i < l; i ++ ) indexArray[ i ] = i; + } - } + for ( let i = 0, l = groups.length; i < l; i ++ ) { - for ( var i = 0, l = groups.length; i < l; i ++ ) { + const group = groups[ i ]; + const subarr = subArray( indexArray, group.start, group.count ); + const polycount = subarr.length / 3; + gnode += ``; + gnode += triangleInputs; + gnode += `

${subarr.join( ' ' )}

`; + gnode += '
'; - var group = groups[ i ]; - var subarr = subArray( indexArray, group.start, group.count ); - var polycount = subarr.length / 3; - gnode += ``; - gnode += triangleInputs; + } - gnode += `

${ subarr.join( ' ' ) }

`; - gnode += '
'; + gnode += '
'; + libraryGeometries.push( gnode ); + info = { + meshid: meshid, + bufferGeometry: bufferGeometry + }; + geometryInfo.set( g, info ); } - gnode += '
'; + return info; - libraryGeometries.push( gnode ); + } // Process the given texture into the image library + // Returns the image library - info = { meshid: meshid, bufferGeometry: bufferGeometry }; - geometryInfo.set( g, info ); - } - - return info; + function processTexture( tex ) { - } + let texid = imageMap.get( tex ); - // Process the given texture into the image library - // Returns the image library - function processTexture( tex ) { + if ( texid == null ) { - var texid = imageMap.get( tex ); - if ( texid == null ) { + texid = `image-${libraryImages.length + 1}`; + const ext = 'png'; + const name = tex.name || texid; + let imageNode = ``; - texid = `image-${ libraryImages.length + 1 }`; + if ( version === '1.5.0' ) { - var ext = 'png'; - var name = tex.name || texid; - var imageNode = ``; + imageNode += `${options.textureDirectory}${name}.${ext}`; - if ( version === '1.5.0' ) { + } else { - imageNode += `${ options.textureDirectory }${ name }.${ ext }`; + // version image node 1.4.1 + imageNode += `${options.textureDirectory}${name}.${ext}`; - } else { + } - // version image node 1.4.1 - imageNode += `${ options.textureDirectory }${ name }.${ ext }`; + imageNode += ''; + libraryImages.push( imageNode ); + imageMap.set( tex, texid ); + textures.push( { + directory: options.textureDirectory, + name, + ext, + data: imageToData( tex.image, ext ), + original: tex + } ); } - imageNode += ''; - - libraryImages.push( imageNode ); - imageMap.set( tex, texid ); - textures.push( { - directory: options.textureDirectory, - name, - ext, - data: imageToData( tex.image, ext ), - original: tex - } ); + return texid; - } + } // Process the given material into the material and effect libraries + // Returns the material id - return texid; - - } - // Process the given material into the material and effect libraries - // Returns the material id - function processMaterial( m ) { + function processMaterial( m ) { - var matid = materialMap.get( m ); + let matid = materialMap.get( m ); - if ( matid == null ) { + if ( matid == null ) { - matid = `Mat${ libraryEffects.length + 1 }`; + matid = `Mat${libraryEffects.length + 1}`; + let type = 'phong'; - var type = 'phong'; + if ( m.isMeshLambertMaterial === true ) { - if ( m.isMeshLambertMaterial === true ) { + type = 'lambert'; - type = 'lambert'; + } else if ( m.isMeshBasicMaterial === true ) { - } else if ( m.isMeshBasicMaterial === true ) { + type = 'constant'; - type = 'constant'; + if ( m.map !== null ) { - if ( m.map !== null ) { + // The Collada spec does not support diffuse texture maps with the + // constant shader type. + // mrdoob/three.js#15469 + console.warn( 'ColladaExporter: Texture maps not supported with THREE.MeshBasicMaterial.' ); - // The Collada spec does not support diffuse texture maps with the - // constant shader type. - // mrdoob/three.js#15469 - console.warn( 'ColladaExporter: Texture maps not supported with MeshBasicMaterial.' ); + } } - } + const emissive = m.emissive ? m.emissive : new THREE.Color( 0, 0, 0 ); + const diffuse = m.color ? m.color : new THREE.Color( 0, 0, 0 ); + const specular = m.specular ? m.specular : new THREE.Color( 1, 1, 1 ); + const shininess = m.shininess || 0; + const reflectivity = m.reflectivity || 0; // Do not export and alpha map for the reasons mentioned in issue (#13792) + // in three.js alpha maps are black and white, but collada expects the alpha + // channel to specify the transparency + + let transparencyNode = ''; - var emissive = m.emissive ? m.emissive : new THREE.Color( 0, 0, 0 ); - var diffuse = m.color ? m.color : new THREE.Color( 0, 0, 0 ); - var specular = m.specular ? m.specular : new THREE.Color( 1, 1, 1 ); - var shininess = m.shininess || 0; - var reflectivity = m.reflectivity || 0; + if ( m.transparent === true ) { - // Do not export and alpha map for the reasons mentioned in issue (#13792) - // in three.js alpha maps are black and white, but collada expects the alpha - // channel to specify the transparency - var transparencyNode = ''; - if ( m.transparent === true ) { + transparencyNode += '' + ( m.map ? '' : '1' ) + ''; - transparencyNode += - '' + - ( - m.map ? - '' : - '1' - ) + - ''; + if ( m.opacity < 1 ) { - if ( m.opacity < 1 ) { + transparencyNode += `${m.opacity}`; - transparencyNode += `${ m.opacity }`; + } } + const techniqueNode = `<${type}>` + '' + ( m.emissiveMap ? '' : `${emissive.r} ${emissive.g} ${emissive.b} 1` ) + '' + ( type !== 'constant' ? '' + ( m.map ? '' : `${diffuse.r} ${diffuse.g} ${diffuse.b} 1` ) + '' : '' ) + ( type !== 'constant' ? '' + ( m.normalMap ? '' : '' ) + '' : '' ) + ( type === 'phong' ? `${specular.r} ${specular.g} ${specular.b} 1` + '' + ( m.specularMap ? '' : `${shininess}` ) + '' : '' ) + `${diffuse.r} ${diffuse.g} ${diffuse.b} 1` + `${reflectivity}` + transparencyNode + ``; + const effectnode = `` + '' + ( m.map ? '' + `${processTexture( m.map )}` + '' + 'diffuse-surface' : '' ) + ( m.specularMap ? '' + `${processTexture( m.specularMap )}` + '' + 'specular-surface' : '' ) + ( m.emissiveMap ? '' + `${processTexture( m.emissiveMap )}` + '' + 'emissive-surface' : '' ) + ( m.normalMap ? '' + `${processTexture( m.normalMap )}` + '' + 'bump-surface' : '' ) + techniqueNode + ( m.side === THREE.DoubleSide ? '1' : '' ) + '' + ''; + const materialName = m.name ? ` name="${m.name}"` : ''; + const materialNode = ``; + libraryMaterials.push( materialNode ); + libraryEffects.push( effectnode ); + materialMap.set( m, matid ); + } - var techniqueNode = `<${ type }>` + - - '' + - - ( - m.emissiveMap ? - '' : - `${ emissive.r } ${ emissive.g } ${ emissive.b } 1` - ) + - - '' + - - ( - type !== 'constant' ? - '' + - - ( - m.map ? - '' : - `${ diffuse.r } ${ diffuse.g } ${ diffuse.b } 1` - ) + - '' - : '' - ) + - - ( - type !== 'constant' ? - '' + - - ( - m.normalMap ? '' : '' - ) + - '' - : '' - ) + - - ( - type === 'phong' ? - `${ specular.r } ${ specular.g } ${ specular.b } 1` + - - '' + - - ( - m.specularMap ? - '' : - `${ shininess }` - ) + - - '' - : '' - ) + - - `${ diffuse.r } ${ diffuse.g } ${ diffuse.b } 1` + - - `${ reflectivity }` + - - transparencyNode + - - ``; - - var effectnode = - `` + - '' + - - ( - m.map ? - '' + - `${ processTexture( m.map ) }` + - '' + - 'diffuse-surface' : - '' - ) + - - ( - m.specularMap ? - '' + - `${ processTexture( m.specularMap ) }` + - '' + - 'specular-surface' : - '' - ) + - - ( - m.emissiveMap ? - '' + - `${ processTexture( m.emissiveMap ) }` + - '' + - 'emissive-surface' : - '' - ) + - - ( - m.normalMap ? - '' + - `${ processTexture( m.normalMap ) }` + - '' + - 'bump-surface' : - '' - ) + - - techniqueNode + - - ( - m.side === THREE.DoubleSide ? - '1' : - '' - ) + - - '' + - - ''; - - var materialName = m.name ? ` name="${ m.name }"` : ''; - var materialNode = ``; - - libraryMaterials.push( materialNode ); - libraryEffects.push( effectnode ); - materialMap.set( m, matid ); + return matid; - } + } // Recursively process the object into a scene - return matid; - } + function processObject( o ) { - // Recursively process the object into a scene - function processObject( o ) { + let node = ``; + node += getTransform( o ); - var node = ``; + if ( o.isMesh === true && o.geometry !== null ) { - node += getTransform( o ); + // function returns the id associated with the mesh and a "BufferGeometry" version + // of the geometry in case it's not a geometry. + const geomInfo = processGeometry( o.geometry ); + const meshid = geomInfo.meshid; + const geometry = geomInfo.bufferGeometry; // ids of the materials to bind to the geometry - if ( o.isMesh === true && o.geometry !== null ) { + let matids = null; + let matidsArray; // get a list of materials to bind to the sub groups of the geometry. + // If the amount of subgroups is greater than the materials, than reuse + // the materials. - // function returns the id associated with the mesh and a "BufferGeometry" version - // of the geometry in case it's not a geometry. - var geomInfo = processGeometry( o.geometry ); - var meshid = geomInfo.meshid; - var geometry = geomInfo.bufferGeometry; + const mat = o.material || new THREE.MeshBasicMaterial(); + const materials = Array.isArray( mat ) ? mat : [ mat ]; - // ids of the materials to bind to the geometry - var matids = null; - var matidsArray = []; + if ( geometry.groups.length > materials.length ) { - // get a list of materials to bind to the sub groups of the geometry. - // If the amount of subgroups is greater than the materials, than reuse - // the materials. - var mat = o.material || new THREE.MeshBasicMaterial(); - var materials = Array.isArray( mat ) ? mat : [ mat ]; + matidsArray = new Array( geometry.groups.length ); - if ( geometry.groups.length > materials.length ) { + } else { - matidsArray = new Array( geometry.groups.length ); + matidsArray = new Array( materials.length ); - } else { + } - matidsArray = new Array( materials.length ); + matids = matidsArray.fill().map( ( v, i ) => processMaterial( materials[ i % materials.length ] ) ); + node += `` + ( matids != null ? '' + matids.map( ( id, i ) => `` + '' + '' ).join( '' ) + '' : '' ) + ''; } - matids = matidsArray.fill().map( ( v, i ) => processMaterial( materials[ i % materials.length ] ) ); - - node += - `` + - - ( - matids != null ? - '' + - matids.map( ( id, i ) => - - `` + - - '' + - - '' - ).join( '' ) + - '' : - '' - ) + - - ''; + o.children.forEach( c => node += processObject( c ) ); + node += ''; + return node; } - o.children.forEach( c => node += processObject( c ) ); - - node += ''; + const geometryInfo = new WeakMap(); + const materialMap = new WeakMap(); + const imageMap = new WeakMap(); + const textures = []; + const libraryImages = []; + const libraryGeometries = []; + const libraryEffects = []; + const libraryMaterials = []; + const libraryVisualScenes = processObject( object ); + const specLink = version === '1.4.1' ? 'http://www.collada.org/2005/11/COLLADASchema' : 'https://www.khronos.org/collada/'; + let dae = '' + `` + '' + ( '' + 'three.js Collada Exporter' + ( options.author !== null ? `${options.author}` : '' ) + '' + `${new Date().toISOString()}` + `${new Date().toISOString()}` + 'Y_UP' ) + ''; + dae += `${libraryImages.join( '' )}`; + dae += `${libraryEffects.join( '' )}`; + dae += `${libraryMaterials.join( '' )}`; + dae += `${libraryGeometries.join( '' )}`; + dae += `${libraryVisualScenes}`; + dae += ''; + dae += ''; + const res = { + data: format( dae ), + textures + }; + + if ( typeof onDone === 'function' ) { + + requestAnimationFrame( () => onDone( res ) ); - return node; - - } - - var geometryInfo = new WeakMap(); - var materialMap = new WeakMap(); - var imageMap = new WeakMap(); - var textures = []; - - var libraryImages = []; - var libraryGeometries = []; - var libraryEffects = []; - var libraryMaterials = []; - var libraryVisualScenes = processObject( object ); - - var specLink = version === '1.4.1' ? 'http://www.collada.org/2005/11/COLLADASchema' : 'https://www.khronos.org/collada/'; - var dae = - '' + - `` + - '' + - ( - '' + - 'three.js Collada Exporter' + - ( options.author !== null ? `${ options.author }` : '' ) + - '' + - `${ ( new Date() ).toISOString() }` + - `${ ( new Date() ).toISOString() }` + - 'Y_UP' - ) + - ''; - - dae += `${ libraryImages.join( '' ) }`; - - dae += `${ libraryEffects.join( '' ) }`; - - dae += `${ libraryMaterials.join( '' ) }`; - - dae += `${ libraryGeometries.join( '' ) }`; - - dae += `${ libraryVisualScenes }`; - - dae += ''; - - dae += ''; - - var res = { - data: format( dae ), - textures - }; - - if ( typeof onDone === 'function' ) { + } - requestAnimationFrame( () => onDone( res ) ); + return res; } - return res; - } -}; + THREE.ColladaExporter = ColladaExporter; + +} )(); diff --git a/examples/js/exporters/DracoExporter.js b/examples/js/exporters/DracoExporter.js index de3bef82fd81e4..68fa34a680f222 100644 --- a/examples/js/exporters/DracoExporter.js +++ b/examples/js/exporters/DracoExporter.js @@ -1,4 +1,6 @@ -/** +( function () { + + /** * Export draco compressed files from threejs geometry objects. * * Draco files are compressed and usually are smaller than conventional 3D file formats. @@ -12,237 +14,211 @@ * - exportNormals */ -/* global DracoEncoderModule */ - -THREE.DRACOExporter = function () {}; - -THREE.DRACOExporter.prototype = { - - constructor: THREE.DRACOExporter, - - parse: function ( object, options ) { - - if ( object.isBufferGeometry === true ) { - - throw new Error( 'DRACOExporter: The first parameter of parse() is now an instance of Mesh or Points.' ); - - } - - if ( DracoEncoderModule === undefined ) { + /* global DracoEncoderModule */ + class DRACOExporter { - throw new Error( 'THREE.DRACOExporter: required the draco_decoder to work.' ); + parse( object, options = { + decodeSpeed: 5, + encodeSpeed: 5, + encoderMethod: DRACOExporter.MESH_EDGEBREAKER_ENCODING, + quantization: [ 16, 8, 8, 8, 8 ], + exportUvs: true, + exportNormals: true, + exportColor: false + } ) { - } - - if ( options === undefined ) { - - options = { + if ( object.isBufferGeometry === true ) { - decodeSpeed: 5, - encodeSpeed: 5, - encoderMethod: THREE.DRACOExporter.MESH_EDGEBREAKER_ENCODING, - quantization: [ 16, 8, 8, 8, 8 ], - exportUvs: true, - exportNormals: true, - exportColor: false, + throw new Error( 'DRACOExporter: The first parameter of parse() is now an instance of Mesh or Points.' ); - }; + } - } + if ( DracoEncoderModule === undefined ) { - var geometry = object.geometry; + throw new Error( 'THREE.DRACOExporter: required the draco_decoder to work.' ); - var dracoEncoder = DracoEncoderModule(); - var encoder = new dracoEncoder.Encoder(); - var builder; - var dracoObject; + } + const geometry = object.geometry; + const dracoEncoder = DracoEncoderModule(); + const encoder = new dracoEncoder.Encoder(); + let builder; + let dracoObject; - if ( geometry.isBufferGeometry !== true ) { + if ( geometry.isBufferGeometry !== true ) { - throw new Error( 'THREE.DRACOExporter.parse(geometry, options): geometry is not a THREE.BufferGeometry instance.' ); + throw new Error( 'THREE.DRACOExporter.parse(geometry, options): geometry is not a THREE.BufferGeometry instance.' ); - } + } - if ( object.isMesh === true ) { + if ( object.isMesh === true ) { - builder = new dracoEncoder.MeshBuilder(); - dracoObject = new dracoEncoder.Mesh(); + builder = new dracoEncoder.MeshBuilder(); + dracoObject = new dracoEncoder.Mesh(); + const vertices = geometry.getAttribute( 'position' ); + builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array ); + const faces = geometry.getIndex(); - var vertices = geometry.getAttribute( 'position' ); - builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array ); + if ( faces !== null ) { - var faces = geometry.getIndex(); + builder.AddFacesToMesh( dracoObject, faces.count / 3, faces.array ); - if ( faces !== null ) { + } else { - builder.AddFacesToMesh( dracoObject, faces.count / 3, faces.array ); + const faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array )( vertices.count ); - } else { + for ( let i = 0; i < faces.length; i ++ ) { - var faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array )( vertices.count ); + faces[ i ] = i; - for ( var i = 0; i < faces.length; i ++ ) { + } - faces[ i ] = i; + builder.AddFacesToMesh( dracoObject, vertices.count, faces ); } - builder.AddFacesToMesh( dracoObject, vertices.count, faces ); - - } + if ( options.exportNormals === true ) { - if ( options.exportNormals === true ) { + const normals = geometry.getAttribute( 'normal' ); - var normals = geometry.getAttribute( 'normal' ); + if ( normals !== undefined ) { - if ( normals !== undefined ) { + builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.NORMAL, normals.count, normals.itemSize, normals.array ); - builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.NORMAL, normals.count, normals.itemSize, normals.array ); + } } - } + if ( options.exportUvs === true ) { - if ( options.exportUvs === true ) { + const uvs = geometry.getAttribute( 'uv' ); - var uvs = geometry.getAttribute( 'uv' ); + if ( uvs !== undefined ) { - if ( uvs !== undefined ) { + builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.TEX_COORD, uvs.count, uvs.itemSize, uvs.array ); - builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.TEX_COORD, uvs.count, uvs.itemSize, uvs.array ); + } } - } + if ( options.exportColor === true ) { - if ( options.exportColor === true ) { + const colors = geometry.getAttribute( 'color' ); - var colors = geometry.getAttribute( 'color' ); + if ( colors !== undefined ) { - if ( colors !== undefined ) { + builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array ); - builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array ); + } } - } - - } else if ( object.isPoints === true ) { + } else if ( object.isPoints === true ) { - builder = new dracoEncoder.PointCloudBuilder(); - dracoObject = new dracoEncoder.PointCloud(); + builder = new dracoEncoder.PointCloudBuilder(); + dracoObject = new dracoEncoder.PointCloud(); + const vertices = geometry.getAttribute( 'position' ); + builder.AddFloatAttribute( dracoObject, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array ); - var vertices = geometry.getAttribute( 'position' ); - builder.AddFloatAttribute( dracoObject, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array ); + if ( options.exportColor === true ) { - if ( options.exportColor === true ) { + const colors = geometry.getAttribute( 'color' ); - var colors = geometry.getAttribute( 'color' ); + if ( colors !== undefined ) { - if ( colors !== undefined ) { + builder.AddFloatAttribute( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array ); - builder.AddFloatAttribute( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array ); + } } - } - - } else { - - throw new Error( 'DRACOExporter: Unsupported object type.' ); + } else { - } + throw new Error( 'DRACOExporter: Unsupported object type.' ); - //Compress using draco encoder + } //Compress using draco encoder - var encodedData = new dracoEncoder.DracoInt8Array(); - //Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression). + const encodedData = new dracoEncoder.DracoInt8Array(); //Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression). - var encodeSpeed = ( options.encodeSpeed !== undefined ) ? options.encodeSpeed : 5; - var decodeSpeed = ( options.decodeSpeed !== undefined ) ? options.decodeSpeed : 5; + const encodeSpeed = options.encodeSpeed !== undefined ? options.encodeSpeed : 5; + const decodeSpeed = options.decodeSpeed !== undefined ? options.decodeSpeed : 5; + encoder.SetSpeedOptions( encodeSpeed, decodeSpeed ); // Sets the desired encoding method for a given geometry. - encoder.SetSpeedOptions( encodeSpeed, decodeSpeed ); + if ( options.encoderMethod !== undefined ) { - // Sets the desired encoding method for a given geometry. + encoder.SetEncodingMethod( options.encoderMethod ); - if ( options.encoderMethod !== undefined ) { + } // Sets the quantization (number of bits used to represent) compression options for a named attribute. + // The attribute values will be quantized in a box defined by the maximum extent of the attribute values. - encoder.SetEncodingMethod( options.encoderMethod ); - } + if ( options.quantization !== undefined ) { - // Sets the quantization (number of bits used to represent) compression options for a named attribute. - // The attribute values will be quantized in a box defined by the maximum extent of the attribute values. - if ( options.quantization !== undefined ) { + for ( let i = 0; i < 5; i ++ ) { - for ( var i = 0; i < 5; i ++ ) { + if ( options.quantization[ i ] !== undefined ) { - if ( options.quantization[ i ] !== undefined ) { + encoder.SetAttributeQuantization( i, options.quantization[ i ] ); - encoder.SetAttributeQuantization( i, options.quantization[ i ] ); + } } } - } - - var length; + let length; - if ( object.isMesh === true ) { + if ( object.isMesh === true ) { - length = encoder.EncodeMeshToDracoBuffer( dracoObject, encodedData ); + length = encoder.EncodeMeshToDracoBuffer( dracoObject, encodedData ); - } else { + } else { - length = encoder.EncodePointCloudToDracoBuffer( dracoObject, true, encodedData ); + length = encoder.EncodePointCloudToDracoBuffer( dracoObject, true, encodedData ); - } + } - dracoEncoder.destroy( dracoObject ); + dracoEncoder.destroy( dracoObject ); - if ( length === 0 ) { + if ( length === 0 ) { - throw new Error( 'THREE.DRACOExporter: Draco encoding failed.' ); + throw new Error( 'THREE.DRACOExporter: Draco encoding failed.' ); - } + } //Copy encoded data to buffer. - //Copy encoded data to buffer. - var outputData = new Int8Array( new ArrayBuffer( length ) ); - for ( var i = 0; i < length; i ++ ) { + const outputData = new Int8Array( new ArrayBuffer( length ) ); - outputData[ i ] = encodedData.GetValue( i ); + for ( let i = 0; i < length; i ++ ) { - } + outputData[ i ] = encodedData.GetValue( i ); - dracoEncoder.destroy( encodedData ); - dracoEncoder.destroy( encoder ); - dracoEncoder.destroy( builder ); + } - return outputData; + dracoEncoder.destroy( encodedData ); + dracoEncoder.destroy( encoder ); + dracoEncoder.destroy( builder ); + return outputData; - } + } -}; + } // Encoder methods -// Encoder methods -THREE.DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1; -THREE.DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0; + DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1; + DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0; // Geometry type -// Geometry type + DRACOExporter.POINT_CLOUD = 0; + DRACOExporter.TRIANGULAR_MESH = 1; // Attribute type -THREE.DRACOExporter.POINT_CLOUD = 0; -THREE.DRACOExporter.TRIANGULAR_MESH = 1; + DRACOExporter.INVALID = - 1; + DRACOExporter.POSITION = 0; + DRACOExporter.NORMAL = 1; + DRACOExporter.COLOR = 2; + DRACOExporter.TEX_COORD = 3; + DRACOExporter.GENERIC = 4; -// Attribute type + THREE.DRACOExporter = DRACOExporter; -THREE.DRACOExporter.INVALID = - 1; -THREE.DRACOExporter.POSITION = 0; -THREE.DRACOExporter.NORMAL = 1; -THREE.DRACOExporter.COLOR = 2; -THREE.DRACOExporter.TEX_COORD = 3; -THREE.DRACOExporter.GENERIC = 4; +} )(); diff --git a/examples/js/exporters/GLTFExporter.js b/examples/js/exporters/GLTFExporter.js index d65f416756e1ee..9293d243e21499 100644 --- a/examples/js/exporters/GLTFExporter.js +++ b/examples/js/exporters/GLTFExporter.js @@ -1,34 +1,29 @@ -THREE.GLTFExporter = ( function () { +( function () { - function GLTFExporter() { + class GLTFExporter { - this.pluginCallbacks = []; + constructor() { - this.register( function ( writer ) { + this.pluginCallbacks = []; + this.register( function ( writer ) { - return new GLTFLightExtension( writer ); + return new GLTFLightExtension( writer ); - } ); - - this.register( function ( writer ) { - - return new GLTFMaterialsUnlitExtension( writer ); - - } ); - - this.register( function ( writer ) { + } ); + this.register( function ( writer ) { - return new GLTFMaterialsPBRSpecularGlossiness( writer ); + return new GLTFMaterialsUnlitExtension( writer ); - } ); + } ); + this.register( function ( writer ) { - } + return new GLTFMaterialsPBRSpecularGlossiness( writer ); - GLTFExporter.prototype = { + } ); - constructor: GLTFExporter, + } - register: function ( callback ) { + register( callback ) { if ( this.pluginCallbacks.indexOf( callback ) === - 1 ) { @@ -38,9 +33,9 @@ THREE.GLTFExporter = ( function () { return this; - }, + } - unregister: function ( callback ) { + unregister( callback ) { if ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) { @@ -50,20 +45,21 @@ THREE.GLTFExporter = ( function () { return this; - }, - + } /** - * Parse scenes and generate GLTF output - * @param {THREE.Scene or [THREE.Scenes]} input THREE.Scene or Array of THREE.Scenes - * @param {Function} onDone Callback on completed - * @param {Object} options options - */ - parse: function ( input, onDone, options ) { + * Parse scenes and generate GLTF output + * @param {Scene or [THREE.Scenes]} input THREE.Scene or Array of THREE.Scenes + * @param {Function} onDone Callback on completed + * @param {Object} options options + */ + - var writer = new GLTFWriter(); - var plugins = []; + parse( input, onDone, options ) { - for ( var i = 0, il = this.pluginCallbacks.length; i < il; i ++ ) { + const writer = new GLTFWriter(); + const plugins = []; + + for ( let i = 0, il = this.pluginCallbacks.length; i < il; i ++ ) { plugins.push( this.pluginCallbacks[ i ]( writer ) ); @@ -74,13 +70,12 @@ THREE.GLTFExporter = ( function () { } - }; - - //------------------------------------------------------------------------------ + } //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ - var WEBGL_CONSTANTS = { + + const WEBGL_CONSTANTS = { POINTS: 0x0000, LINES: 0x0001, LINE_LOOP: 0x0002, @@ -88,82 +83,72 @@ THREE.GLTFExporter = ( function () { TRIANGLES: 0x0004, TRIANGLE_STRIP: 0x0005, TRIANGLE_FAN: 0x0006, - UNSIGNED_BYTE: 0x1401, UNSIGNED_SHORT: 0x1403, FLOAT: 0x1406, UNSIGNED_INT: 0x1405, ARRAY_BUFFER: 0x8892, ELEMENT_ARRAY_BUFFER: 0x8893, - NEAREST: 0x2600, LINEAR: 0x2601, NEAREST_MIPMAP_NEAREST: 0x2700, LINEAR_MIPMAP_NEAREST: 0x2701, NEAREST_MIPMAP_LINEAR: 0x2702, LINEAR_MIPMAP_LINEAR: 0x2703, - CLAMP_TO_EDGE: 33071, MIRRORED_REPEAT: 33648, REPEAT: 10497 }; - - var THREE_TO_WEBGL = {}; - + const THREE_TO_WEBGL = {}; THREE_TO_WEBGL[ THREE.NearestFilter ] = WEBGL_CONSTANTS.NEAREST; THREE_TO_WEBGL[ THREE.NearestMipmapNearestFilter ] = WEBGL_CONSTANTS.NEAREST_MIPMAP_NEAREST; THREE_TO_WEBGL[ THREE.NearestMipmapLinearFilter ] = WEBGL_CONSTANTS.NEAREST_MIPMAP_LINEAR; THREE_TO_WEBGL[ THREE.LinearFilter ] = WEBGL_CONSTANTS.LINEAR; THREE_TO_WEBGL[ THREE.LinearMipmapNearestFilter ] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST; THREE_TO_WEBGL[ THREE.LinearMipmapLinearFilter ] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR; - THREE_TO_WEBGL[ THREE.ClampToEdgeWrapping ] = WEBGL_CONSTANTS.CLAMP_TO_EDGE; THREE_TO_WEBGL[ THREE.RepeatWrapping ] = WEBGL_CONSTANTS.REPEAT; THREE_TO_WEBGL[ THREE.MirroredRepeatWrapping ] = WEBGL_CONSTANTS.MIRRORED_REPEAT; - - var PATH_PROPERTIES = { + const PATH_PROPERTIES = { scale: 'scale', position: 'translation', quaternion: 'rotation', morphTargetInfluences: 'weights' - }; - - // GLB constants + }; // GLB constants // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#glb-file-format-specification - var GLB_HEADER_BYTES = 12; - var GLB_HEADER_MAGIC = 0x46546C67; - var GLB_VERSION = 2; - - var GLB_CHUNK_PREFIX_BYTES = 8; - var GLB_CHUNK_TYPE_JSON = 0x4E4F534A; - var GLB_CHUNK_TYPE_BIN = 0x004E4942; - - //------------------------------------------------------------------------------ + const GLB_HEADER_BYTES = 12; + const GLB_HEADER_MAGIC = 0x46546C67; + const GLB_VERSION = 2; + const GLB_CHUNK_PREFIX_BYTES = 8; + const GLB_CHUNK_TYPE_JSON = 0x4E4F534A; + const GLB_CHUNK_TYPE_BIN = 0x004E4942; //------------------------------------------------------------------------------ // Utility functions //------------------------------------------------------------------------------ /** - * Compare two arrays - * @param {Array} array1 Array 1 to compare - * @param {Array} array2 Array 2 to compare - * @return {Boolean} Returns true if both arrays are equal - */ + * Compare two arrays + * @param {Array} array1 Array 1 to compare + * @param {Array} array2 Array 2 to compare + * @return {Boolean} Returns true if both arrays are equal + */ + function equalArray( array1, array2 ) { - return ( array1.length === array2.length ) && array1.every( function ( element, index ) { + return array1.length === array2.length && array1.every( function ( element, index ) { return element === array2[ index ]; } ); } - /** - * Converts a string to an ArrayBuffer. - * @param {string} text - * @return {ArrayBuffer} - */ + * Converts a string to an ArrayBuffer. + * @param {string} text + * @return {ArrayBuffer} + */ + + function stringToArrayBuffer( text ) { if ( window.TextEncoder !== undefined ) { @@ -172,13 +157,12 @@ THREE.GLTFExporter = ( function () { } - var array = new Uint8Array( new ArrayBuffer( text.length ) ); + const array = new Uint8Array( new ArrayBuffer( text.length ) ); - for ( var i = 0, il = text.length; i < il; i ++ ) { + for ( let i = 0, il = text.length; i < il; i ++ ) { - var value = text.charCodeAt( i ); + const value = text.charCodeAt( i ); // Replacing multi-byte character with space(0x20). - // Replacing multi-byte character with space(0x20). array[ i ] = value > 0xFF ? 0x20 : value; } @@ -186,53 +170,49 @@ THREE.GLTFExporter = ( function () { return array.buffer; } - /** - * Is identity matrix - * - * @param {THREE.Matrix4} matrix - * @returns {Boolean} Returns true, if parameter is identity matrix - */ + * Is identity matrix + * + * @param {Matrix4} matrix + * @returns {Boolean} Returns true, if parameter is identity matrix + */ + + function isIdentityMatrix( matrix ) { return equalArray( matrix.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] ); } - /** - * Get the min and max vectors from the given attribute - * @param {THREE.BufferAttribute} attribute Attribute to find the min/max in range from start to start + count - * @param {Integer} start - * @param {Integer} count - * @return {Object} Object containing the `min` and `max` values (As an array of attribute.itemSize components) - */ - function getMinMax( attribute, start, count ) { + * Get the min and max vectors from the given attribute + * @param {BufferAttribute} attribute Attribute to find the min/max in range from start to start + count + * @param {Integer} start + * @param {Integer} count + * @return {Object} Object containing the `min` and `max` values (As an array of attribute.itemSize components) + */ - var output = { + function getMinMax( attribute, start, count ) { + + const output = { min: new Array( attribute.itemSize ).fill( Number.POSITIVE_INFINITY ), max: new Array( attribute.itemSize ).fill( Number.NEGATIVE_INFINITY ) - }; - for ( var i = start; i < start + count; i ++ ) { + for ( let i = start; i < start + count; i ++ ) { - for ( var a = 0; a < attribute.itemSize; a ++ ) { + for ( let a = 0; a < attribute.itemSize; a ++ ) { - var value; + let value; if ( attribute.itemSize > 4 ) { - // no support for interleaved data for itemSize > 4 - + // no support for interleaved data for itemSize > 4 value = attribute.array[ i * attribute.itemSize + a ]; } else { - if ( a === 0 ) value = attribute.getX( i ); - else if ( a === 1 ) value = attribute.getY( i ); - else if ( a === 2 ) value = attribute.getZ( i ); - else if ( a === 3 ) value = attribute.getW( i ); + if ( a === 0 ) value = attribute.getX( i ); else if ( a === 1 ) value = attribute.getY( i ); else if ( a === 2 ) value = attribute.getZ( i ); else if ( a === 3 ) value = attribute.getW( i ); } @@ -246,42 +226,42 @@ THREE.GLTFExporter = ( function () { return output; } - /** - * Get the required size + padding for a buffer, rounded to the next 4-byte boundary. - * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment - * - * @param {Integer} bufferSize The size the original buffer. - * @returns {Integer} new buffer size with required padding. - * - */ + * Get the required size + padding for a buffer, rounded to the next 4-byte boundary. + * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment + * + * @param {Integer} bufferSize The size the original buffer. + * @returns {Integer} new buffer size with required padding. + * + */ + + function getPaddedBufferSize( bufferSize ) { return Math.ceil( bufferSize / 4 ) * 4; } - /** - * Returns a buffer aligned to 4-byte boundary. - * - * @param {ArrayBuffer} arrayBuffer Buffer to pad - * @param {Integer} paddingByte (Optional) - * @returns {ArrayBuffer} The same buffer if it's already aligned to 4-byte boundary or a new buffer - */ - function getPaddedArrayBuffer( arrayBuffer, paddingByte ) { + * Returns a buffer aligned to 4-byte boundary. + * + * @param {ArrayBuffer} arrayBuffer Buffer to pad + * @param {Integer} paddingByte (Optional) + * @returns {ArrayBuffer} The same buffer if it's already aligned to 4-byte boundary or a new buffer + */ - paddingByte = paddingByte || 0; - var paddedLength = getPaddedBufferSize( arrayBuffer.byteLength ); + function getPaddedArrayBuffer( arrayBuffer, paddingByte = 0 ) { + + const paddedLength = getPaddedBufferSize( arrayBuffer.byteLength ); if ( paddedLength !== arrayBuffer.byteLength ) { - var array = new Uint8Array( paddedLength ); + const array = new Uint8Array( paddedLength ); array.set( new Uint8Array( arrayBuffer ) ); if ( paddingByte !== 0 ) { - for ( var i = arrayBuffer.byteLength; i < paddedLength; i ++ ) { + for ( let i = arrayBuffer.byteLength; i < paddedLength; i ++ ) { array[ i ] = paddingByte; @@ -297,63 +277,57 @@ THREE.GLTFExporter = ( function () { } - var cachedCanvas = null; - + let cachedCanvas = null; /** - * Writer - */ - function GLTFWriter() { - - this.plugins = []; - - this.options = {}; - this.pending = []; - this.buffers = []; - - this.byteOffset = 0; - this.buffers = []; - this.nodeMap = new Map(); - this.skins = []; - this.extensionsUsed = {}; - - this.uids = new Map(); - this.uid = 0; - - this.json = { - asset: { - version: '2.0', - generator: 'THREE.GLTFExporter' - } - }; - - this.cache = { - meshes: new Map(), - attributes: new Map(), - attributesNormalized: new Map(), - materials: new Map(), - textures: new Map(), - images: new Map() - }; - - } - - GLTFWriter.prototype = { + * Writer + */ + + class GLTFWriter { + + constructor() { + + this.plugins = []; + this.options = {}; + this.pending = []; + this.buffers = []; + this.byteOffset = 0; + this.buffers = []; + this.nodeMap = new Map(); + this.skins = []; + this.extensionsUsed = {}; + this.uids = new Map(); + this.uid = 0; + this.json = { + asset: { + version: '2.0', + generator: 'THREE.GLTFExporter' + } + }; + this.cache = { + meshes: new Map(), + attributes: new Map(), + attributesNormalized: new Map(), + materials: new Map(), + textures: new Map(), + images: new Map() + }; - constructor: GLTFWriter, + } - setPlugins: function ( plugins ) { + setPlugins( plugins ) { this.plugins = plugins; - }, - + } /** - * Parse scenes and generate GLTF output - * @param {THREE.Scene or [THREE.Scenes]} input THREE.Scene or Array of THREE.Scenes - * @param {Function} onDone Callback on completed - * @param {Object} options options - */ - write: function ( input, onDone, options ) { + * Parse scenes and generate GLTF output + * @param {Scene or [THREE.Scenes]} input THREE.Scene or Array of THREE.Scenes + * @param {Function} onDone Callback on completed + * @param {Object} options options + */ + + + write( input, onDone, options ) { this.options = Object.assign( {}, { // default options @@ -375,67 +349,54 @@ THREE.GLTFExporter = ( function () { } this.processInput( input ); - - var writer = this; - + const writer = this; Promise.all( this.pending ).then( function () { - var buffers = writer.buffers; - var json = writer.json; - var options = writer.options; - var extensionsUsed = writer.extensionsUsed; - - // Merge buffers. - var blob = new Blob( buffers, { type: 'application/octet-stream' } ); + const buffers = writer.buffers; + const json = writer.json; + const options = writer.options; + const extensionsUsed = writer.extensionsUsed; // Merge buffers. - // Declare extensions. - var extensionsUsedList = Object.keys( extensionsUsed ); + const blob = new Blob( buffers, { + type: 'application/octet-stream' + } ); // Declare extensions. - if ( extensionsUsedList.length > 0 ) json.extensionsUsed = extensionsUsedList; + const extensionsUsedList = Object.keys( extensionsUsed ); + if ( extensionsUsedList.length > 0 ) json.extensionsUsed = extensionsUsedList; // Update bytelength of the single buffer. - // Update bytelength of the single buffer. if ( json.buffers && json.buffers.length > 0 ) json.buffers[ 0 ].byteLength = blob.size; if ( options.binary === true ) { // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#glb-file-format-specification - - var reader = new window.FileReader(); + const reader = new window.FileReader(); reader.readAsArrayBuffer( blob ); + reader.onloadend = function () { // Binary chunk. - var binaryChunk = getPaddedArrayBuffer( reader.result ); - var binaryChunkPrefix = new DataView( new ArrayBuffer( GLB_CHUNK_PREFIX_BYTES ) ); + const binaryChunk = getPaddedArrayBuffer( reader.result ); + const binaryChunkPrefix = new DataView( new ArrayBuffer( GLB_CHUNK_PREFIX_BYTES ) ); binaryChunkPrefix.setUint32( 0, binaryChunk.byteLength, true ); - binaryChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_BIN, true ); + binaryChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_BIN, true ); // JSON chunk. - // JSON chunk. - var jsonChunk = getPaddedArrayBuffer( stringToArrayBuffer( JSON.stringify( json ) ), 0x20 ); - var jsonChunkPrefix = new DataView( new ArrayBuffer( GLB_CHUNK_PREFIX_BYTES ) ); + const jsonChunk = getPaddedArrayBuffer( stringToArrayBuffer( JSON.stringify( json ) ), 0x20 ); + const jsonChunkPrefix = new DataView( new ArrayBuffer( GLB_CHUNK_PREFIX_BYTES ) ); jsonChunkPrefix.setUint32( 0, jsonChunk.byteLength, true ); - jsonChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_JSON, true ); + jsonChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_JSON, true ); // GLB header. - // GLB header. - var header = new ArrayBuffer( GLB_HEADER_BYTES ); - var headerView = new DataView( header ); + const header = new ArrayBuffer( GLB_HEADER_BYTES ); + const headerView = new DataView( header ); headerView.setUint32( 0, GLB_HEADER_MAGIC, true ); headerView.setUint32( 4, GLB_VERSION, true ); - var totalByteLength = GLB_HEADER_BYTES - + jsonChunkPrefix.byteLength + jsonChunk.byteLength - + binaryChunkPrefix.byteLength + binaryChunk.byteLength; + const totalByteLength = GLB_HEADER_BYTES + jsonChunkPrefix.byteLength + jsonChunk.byteLength + binaryChunkPrefix.byteLength + binaryChunk.byteLength; headerView.setUint32( 8, totalByteLength, true ); - - var glbBlob = new Blob( [ - header, - jsonChunkPrefix, - jsonChunk, - binaryChunkPrefix, - binaryChunk - ], { type: 'application/octet-stream' } ); - - var glbReader = new window.FileReader(); + const glbBlob = new Blob( [ header, jsonChunkPrefix, jsonChunk, binaryChunkPrefix, binaryChunk ], { + type: 'application/octet-stream' + } ); + const glbReader = new window.FileReader(); glbReader.readAsArrayBuffer( glbBlob ); + glbReader.onloadend = function () { onDone( glbReader.result ); @@ -448,11 +409,12 @@ THREE.GLTFExporter = ( function () { if ( json.buffers && json.buffers.length > 0 ) { - var reader = new window.FileReader(); + const reader = new window.FileReader(); reader.readAsDataURL( blob ); + reader.onloadend = function () { - var base64data = reader.result; + const base64data = reader.result; json.buffers[ 0 ].uri = base64data; onDone( json ); @@ -468,30 +430,30 @@ THREE.GLTFExporter = ( function () { } ); - }, - + } /** - * Serializes a userData. - * - * @param {THREE.Object3D|THREE.Material} object - * @param {Object} objectDef - */ - serializeUserData: function ( object, objectDef ) { + * Serializes a userData. + * + * @param {THREE.Object3D|THREE.Material} object + * @param {Object} objectDef + */ - if ( Object.keys( object.userData ).length === 0 ) return; - var options = this.options; - var extensionsUsed = this.extensionsUsed; + serializeUserData( object, objectDef ) { + + if ( Object.keys( object.userData ).length === 0 ) return; + const options = this.options; + const extensionsUsed = this.extensionsUsed; try { - var json = JSON.parse( JSON.stringify( object.userData ) ); + const json = JSON.parse( JSON.stringify( object.userData ) ); if ( options.includeCustomExtensions && json.gltfExtensions ) { if ( objectDef.extensions === undefined ) objectDef.extensions = {}; - for ( var extensionName in json.gltfExtensions ) { + for ( const extensionName in json.gltfExtensions ) { objectDef.extensions[ extensionName ] = json.gltfExtensions[ extensionName ]; extensionsUsed[ extensionName ] = true; @@ -506,42 +468,40 @@ THREE.GLTFExporter = ( function () { } catch ( error ) { - console.warn( 'THREE.GLTFExporter: userData of \'' + object.name + '\' ' + - 'won\'t be serialized because of JSON.stringify error - ' + error.message ); + console.warn( 'THREE.GLTFExporter: userData of \'' + object.name + '\' ' + 'won\'t be serialized because of JSON.stringify error - ' + error.message ); } - }, - + } /** - * Assign and return a temporal unique id for an object - * especially which doesn't have .uuid - * @param {Object} object - * @return {Integer} - */ - getUID: function ( object ) { + * Assign and return a temporal unique id for an object + * especially which doesn't have .uuid + * @param {Object} object + * @return {Integer} + */ - if ( ! this.uids.has( object ) ) this.uids.set( object, this.uid ++ ); - return this.uids.get( object ); + getUID( object ) { - }, + if ( ! this.uids.has( object ) ) this.uids.set( object, this.uid ++ ); + return this.uids.get( object ); + } /** - * Checks if normal attribute values are normalized. - * - * @param {THREE.BufferAttribute} normal - * @returns {Boolean} - */ - isNormalizedNormalAttribute: function ( normal ) { + * Checks if normal attribute values are normalized. + * + * @param {BufferAttribute} normal + * @returns {Boolean} + */ - var cache = this.cache; - if ( cache.attributesNormalized.has( normal ) ) return false; + isNormalizedNormalAttribute( normal ) { - var v = new THREE.Vector3(); + const cache = this.cache; + if ( cache.attributesNormalized.has( normal ) ) return false; + const v = new THREE.Vector3(); - for ( var i = 0, il = normal.count; i < il; i ++ ) { + for ( let i = 0, il = normal.count; i < il; i ++ ) { // 0.0005 is from glTF-validator if ( Math.abs( v.fromBufferAttribute( normal, i ).length() - 1.0 ) > 0.0005 ) return false; @@ -550,25 +510,24 @@ THREE.GLTFExporter = ( function () { return true; - }, - + } /** - * Creates normalized normal buffer attribute. - * - * @param {THREE.BufferAttribute} normal - * @returns {THREE.BufferAttribute} - * - */ - createNormalizedNormalAttribute: function ( normal ) { + * Creates normalized normal buffer attribute. + * + * @param {BufferAttribute} normal + * @returns {BufferAttribute} + * + */ - var cache = this.cache; - if ( cache.attributesNormalized.has( normal ) ) return cache.attributesNormalized.get( normal ); + createNormalizedNormalAttribute( normal ) { - var attribute = normal.clone(); - var v = new THREE.Vector3(); + const cache = this.cache; + if ( cache.attributesNormalized.has( normal ) ) return cache.attributesNormalized.get( normal ); + const attribute = normal.clone(); + const v = new THREE.Vector3(); - for ( var i = 0, il = attribute.count; i < il; i ++ ) { + for ( let i = 0, il = attribute.count; i < il; i ++ ) { v.fromBufferAttribute( attribute, i ); @@ -588,22 +547,22 @@ THREE.GLTFExporter = ( function () { } cache.attributesNormalized.set( normal, attribute ); - return attribute; - }, - + } /** - * Applies a texture transform, if present, to the map definition. Requires - * the KHR_texture_transform extension. - * - * @param {Object} mapDef - * @param {THREE.Texture} texture - */ - applyTextureTransform: function ( mapDef, texture ) { + * Applies a texture transform, if present, to the map definition. Requires + * the KHR_texture_transform extension. + * + * @param {Object} mapDef + * @param {THREE.Texture} texture + */ + + + applyTextureTransform( mapDef, texture ) { - var didTransform = false; - var transformDef = {}; + let didTransform = false; + const transformDef = {}; if ( texture.offset.x !== 0 || texture.offset.y !== 0 ) { @@ -634,45 +593,43 @@ THREE.GLTFExporter = ( function () { } - }, - + } /** - * Process a buffer to append to the default one. - * @param {ArrayBuffer} buffer - * @return {Integer} - */ - processBuffer: function ( buffer ) { + * Process a buffer to append to the default one. + * @param {ArrayBuffer} buffer + * @return {Integer} + */ - var json = this.json; - var buffers = this.buffers; - if ( ! json.buffers ) json.buffers = [ { byteLength: 0 } ]; + processBuffer( buffer ) { - // All buffers are merged before export. - buffers.push( buffer ); + const json = this.json; + const buffers = this.buffers; + if ( ! json.buffers ) json.buffers = [ { + byteLength: 0 + } ]; // All buffers are merged before export. + buffers.push( buffer ); return 0; - }, - + } /** - * Process and generate a BufferView - * @param {THREE.BufferAttribute} attribute - * @param {number} componentType - * @param {number} start - * @param {number} count - * @param {number} target (Optional) Target usage of the BufferView - * @return {Object} - */ - processBufferView: function ( attribute, componentType, start, count, target ) { - - var json = this.json; + * Process and generate a BufferView + * @param {BufferAttribute} attribute + * @param {number} componentType + * @param {number} start + * @param {number} count + * @param {number} target (Optional) Target usage of the BufferView + * @return {Object} + */ - if ( ! json.bufferViews ) json.bufferViews = []; - // Create a new dataview and dump the attribute's array into it + processBufferView( attribute, componentType, start, count, target ) { + + const json = this.json; + if ( ! json.bufferViews ) json.bufferViews = []; // Create a new dataview and dump the attribute's array into it - var componentSize; + let componentSize; if ( componentType === WEBGL_CONSTANTS.UNSIGNED_BYTE ) { @@ -688,28 +645,24 @@ THREE.GLTFExporter = ( function () { } - var byteLength = getPaddedBufferSize( count * attribute.itemSize * componentSize ); - var dataView = new DataView( new ArrayBuffer( byteLength ) ); - var offset = 0; + const byteLength = getPaddedBufferSize( count * attribute.itemSize * componentSize ); + const dataView = new DataView( new ArrayBuffer( byteLength ) ); + let offset = 0; - for ( var i = start; i < start + count; i ++ ) { + for ( let i = start; i < start + count; i ++ ) { - for ( var a = 0; a < attribute.itemSize; a ++ ) { + for ( let a = 0; a < attribute.itemSize; a ++ ) { - var value; + let value; if ( attribute.itemSize > 4 ) { - // no support for interleaved data for itemSize > 4 - + // no support for interleaved data for itemSize > 4 value = attribute.array[ i * attribute.itemSize + a ]; } else { - if ( a === 0 ) value = attribute.getX( i ); - else if ( a === 1 ) value = attribute.getY( i ); - else if ( a === 2 ) value = attribute.getZ( i ); - else if ( a === 3 ) value = attribute.getW( i ); + if ( a === 0 ) value = attribute.getX( i ); else if ( a === 1 ) value = attribute.getY( i ); else if ( a === 2 ) value = attribute.getZ( i ); else if ( a === 3 ) value = attribute.getW( i ); } @@ -737,14 +690,11 @@ THREE.GLTFExporter = ( function () { } - var bufferViewDef = { - + const bufferViewDef = { buffer: this.processBuffer( dataView.buffer ), byteOffset: this.byteOffset, byteLength: byteLength - }; - if ( target !== undefined ) bufferViewDef.target = target; if ( target === WEBGL_CONSTANTS.ARRAY_BUFFER ) { @@ -755,47 +705,40 @@ THREE.GLTFExporter = ( function () { } this.byteOffset += byteLength; + json.bufferViews.push( bufferViewDef ); // @TODO Merge bufferViews where possible. - json.bufferViews.push( bufferViewDef ); - - // @TODO Merge bufferViews where possible. - var output = { - + const output = { id: json.bufferViews.length - 1, byteLength: 0 - }; - return output; - }, - + } /** - * Process and generate a BufferView from an image Blob. - * @param {Blob} blob - * @return {Promise} - */ - processBufferViewImage: function ( blob ) { + * Process and generate a BufferView from an image Blob. + * @param {Blob} blob + * @return {Promise} + */ - var writer = this; - var json = writer.json; - if ( ! json.bufferViews ) json.bufferViews = []; + processBufferViewImage( blob ) { + const writer = this; + const json = writer.json; + if ( ! json.bufferViews ) json.bufferViews = []; return new Promise( function ( resolve ) { - var reader = new window.FileReader(); + const reader = new window.FileReader(); reader.readAsArrayBuffer( blob ); - reader.onloadend = function () { - var buffer = getPaddedArrayBuffer( reader.result ); + reader.onloadend = function () { - var bufferViewDef = { + const buffer = getPaddedArrayBuffer( reader.result ); + const bufferViewDef = { buffer: writer.processBuffer( buffer ), byteOffset: writer.byteOffset, byteLength: buffer.byteLength }; - writer.byteOffset += buffer.byteLength; resolve( json.bufferViews.push( bufferViewDef ) - 1 ); @@ -803,34 +746,30 @@ THREE.GLTFExporter = ( function () { } ); - }, - + } /** - * Process attribute to generate an accessor - * @param {THREE.BufferAttribute} attribute Attribute to process - * @param {THREE.BufferGeometry} geometry (Optional) Geometry used for truncated draw range - * @param {Integer} start (Optional) - * @param {Integer} count (Optional) - * @return {Integer|null} Index of the processed accessor on the "accessors" array - */ - processAccessor: function ( attribute, geometry, start, count ) { + * Process attribute to generate an accessor + * @param {BufferAttribute} attribute Attribute to process + * @param {THREE.BufferGeometry} geometry (Optional) Geometry used for truncated draw range + * @param {Integer} start (Optional) + * @param {Integer} count (Optional) + * @return {Integer|null} Index of the processed accessor on the "accessors" array + */ - var options = this.options; - var json = this.json; - var types = { + processAccessor( attribute, geometry, start, count ) { + const options = this.options; + const json = this.json; + const types = { 1: 'SCALAR', 2: 'VEC2', 3: 'VEC3', 4: 'VEC4', 16: 'MAT4' - }; + let componentType; // Detect the component type of the attribute array (float, uint or ushort) - var componentType; - - // Detect the component type of the attribute array (float, uint or ushort) if ( attribute.array.constructor === Float32Array ) { componentType = WEBGL_CONSTANTS.FLOAT; @@ -854,41 +793,32 @@ THREE.GLTFExporter = ( function () { } if ( start === undefined ) start = 0; - if ( count === undefined ) count = attribute.count; + if ( count === undefined ) count = attribute.count; // @TODO Indexed buffer geometry with drawRange not supported yet - // @TODO Indexed buffer geometry with drawRange not supported yet if ( options.truncateDrawRange && geometry !== undefined && geometry.index === null ) { - var end = start + count; - var end2 = geometry.drawRange.count === Infinity - ? attribute.count - : geometry.drawRange.start + geometry.drawRange.count; - + const end = start + count; + const end2 = geometry.drawRange.count === Infinity ? attribute.count : geometry.drawRange.start + geometry.drawRange.count; start = Math.max( start, geometry.drawRange.start ); count = Math.min( end, end2 ) - start; - if ( count < 0 ) count = 0; - } - - // Skip creating an accessor if the attribute doesn't have data to export - if ( count === 0 ) return null; + } // Skip creating an accessor if the attribute doesn't have data to export - var minMax = getMinMax( attribute, start, count ); - var bufferViewTarget; - // If geometry isn't provided, don't infer the target usage of the bufferView. For + if ( count === 0 ) return null; + const minMax = getMinMax( attribute, start, count ); + let bufferViewTarget; // If geometry isn't provided, don't infer the target usage of the bufferView. For // animation samplers, target must not be set. + if ( geometry !== undefined ) { bufferViewTarget = attribute === geometry.index ? WEBGL_CONSTANTS.ELEMENT_ARRAY_BUFFER : WEBGL_CONSTANTS.ARRAY_BUFFER; } - var bufferView = this.processBufferView( attribute, componentType, start, count, bufferViewTarget ); - - var accessorDef = { - + const bufferView = this.processBufferView( attribute, componentType, start, count, bufferViewTarget ); + const accessorDef = { bufferView: bufferView.id, byteOffset: bufferView.byteOffset, componentType: componentType, @@ -896,51 +826,44 @@ THREE.GLTFExporter = ( function () { max: minMax.max, min: minMax.min, type: types[ attribute.itemSize ] - }; - if ( attribute.normalized === true ) accessorDef.normalized = true; if ( ! json.accessors ) json.accessors = []; - return json.accessors.push( accessorDef ) - 1; - }, - + } /** - * Process image - * @param {Image} image to process - * @param {Integer} format of the image (e.g. THREE.RGBFormat, THREE.RGBAFormat etc) - * @param {Boolean} flipY before writing out the image - * @return {Integer} Index of the processed texture in the "images" array - */ - processImage: function ( image, format, flipY ) { - - var writer = this; - var cache = writer.cache; - var json = writer.json; - var options = writer.options; - var pending = writer.pending; + * Process image + * @param {Image} image to process + * @param {Integer} format of the image (e.g. THREE.RGBFormat, THREE.RGBAFormat etc) + * @param {Boolean} flipY before writing out the image + * @return {Integer} Index of the processed texture in the "images" array + */ - if ( ! cache.images.has( image ) ) cache.images.set( image, {} ); - var cachedImages = cache.images.get( image ); - var mimeType = format === THREE.RGBAFormat ? 'image/png' : 'image/jpeg'; - var key = mimeType + ':flipY/' + flipY.toString(); + processImage( image, format, flipY ) { + const writer = this; + const cache = writer.cache; + const json = writer.json; + const options = writer.options; + const pending = writer.pending; + if ( ! cache.images.has( image ) ) cache.images.set( image, {} ); + const cachedImages = cache.images.get( image ); + const mimeType = format === THREE.RGBAFormat ? 'image/png' : 'image/jpeg'; + const key = mimeType + ':flipY/' + flipY.toString(); if ( cachedImages[ key ] !== undefined ) return cachedImages[ key ]; - if ( ! json.images ) json.images = []; - - var imageDef = { mimeType: mimeType }; + const imageDef = { + mimeType: mimeType + }; if ( options.embedImages ) { - var canvas = cachedCanvas = cachedCanvas || document.createElement( 'canvas' ); - + const canvas = cachedCanvas = cachedCanvas || document.createElement( 'canvas' ); canvas.width = Math.min( image.width, options.maxTextureSize ); canvas.height = Math.min( image.height, options.maxTextureSize ); - - var ctx = canvas.getContext( '2d' ); + const ctx = canvas.getContext( '2d' ); if ( flipY === true ) { @@ -949,10 +872,7 @@ THREE.GLTFExporter = ( function () { } - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement || typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas || typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) { ctx.drawImage( image, 0, 0, canvas.width, canvas.height ); @@ -970,13 +890,13 @@ THREE.GLTFExporter = ( function () { } - var data = image.data; + let data = image.data; if ( format === THREE.RGBFormat ) { data = new Uint8ClampedArray( image.height * image.width * 4 ); - for ( var i = 0, j = 0; i < data.length; i += 4, j += 3 ) { + for ( let i = 0, j = 0; i < data.length; i += 4, j += 3 ) { data[ i + 0 ] = image.data[ j + 0 ]; data[ i + 1 ] = image.data[ j + 1 ]; @@ -1020,53 +940,48 @@ THREE.GLTFExporter = ( function () { } - var index = json.images.push( imageDef ) - 1; + const index = json.images.push( imageDef ) - 1; cachedImages[ key ] = index; return index; - }, - + } /** - * Process sampler - * @param {Texture} map Texture to process - * @return {Integer} Index of the processed texture in the "samplers" array - */ - processSampler: function ( map ) { + * Process sampler + * @param {Texture} map Texture to process + * @return {Integer} Index of the processed texture in the "samplers" array + */ - var json = this.json; - if ( ! json.samplers ) json.samplers = []; + processSampler( map ) { - var samplerDef = { + const json = this.json; + if ( ! json.samplers ) json.samplers = []; + const samplerDef = { magFilter: THREE_TO_WEBGL[ map.magFilter ], minFilter: THREE_TO_WEBGL[ map.minFilter ], wrapS: THREE_TO_WEBGL[ map.wrapS ], wrapT: THREE_TO_WEBGL[ map.wrapT ] }; - return json.samplers.push( samplerDef ) - 1; - }, - + } /** - * Process texture - * @param {Texture} map Map to process - * @return {Integer} Index of the processed texture in the "textures" array - */ - processTexture: function ( map ) { + * Process texture + * @param {Texture} map Map to process + * @return {Integer} Index of the processed texture in the "textures" array + */ - var cache = this.cache; - var json = this.json; - if ( cache.textures.has( map ) ) return cache.textures.get( map ); + processTexture( map ) { + const cache = this.cache; + const json = this.json; + if ( cache.textures.has( map ) ) return cache.textures.get( map ); if ( ! json.textures ) json.textures = []; - - var textureDef = { + const textureDef = { sampler: this.processSampler( map ), source: this.processImage( map.image, map.format, map.flipY ) }; - if ( map.name ) textureDef.name = map.name; this._invokeAll( function ( ext ) { @@ -1075,22 +990,22 @@ THREE.GLTFExporter = ( function () { } ); - var index = json.textures.push( textureDef ) - 1; + const index = json.textures.push( textureDef ) - 1; cache.textures.set( map, index ); return index; - }, - + } /** - * Process material - * @param {THREE.Material} material Material to process - * @return {Integer|null} Index of the processed material in the "materials" array - */ - processMaterial: function ( material ) { + * Process material + * @param {THREE.Material} material Material to process + * @return {Integer|null} Index of the processed material in the "materials" array + */ + - var cache = this.cache; - var json = this.json; + processMaterial( material ) { + const cache = this.cache; + const json = this.json; if ( cache.materials.has( material ) ) return cache.materials.get( material ); if ( material.isShaderMaterial ) { @@ -1100,19 +1015,20 @@ THREE.GLTFExporter = ( function () { } - if ( ! json.materials ) json.materials = []; + if ( ! json.materials ) json.materials = []; // @QUESTION Should we avoid including any attribute that has the default value? - // @QUESTION Should we avoid including any attribute that has the default value? - var materialDef = { pbrMetallicRoughness: {} }; + const materialDef = { + pbrMetallicRoughness: {} + }; if ( material.isMeshStandardMaterial !== true && material.isMeshBasicMaterial !== true ) { console.warn( 'GLTFExporter: Use MeshStandardMaterial or MeshBasicMaterial for best results.' ); - } + } // pbrMetallicRoughness.baseColorFactor - // pbrMetallicRoughness.baseColorFactor - var color = material.color.toArray().concat( [ material.opacity ] ); + + const color = material.color.toArray().concat( [ material.opacity ] ); if ( ! equalArray( color, [ 1, 1, 1, 1 ] ) ) { @@ -1130,14 +1046,16 @@ THREE.GLTFExporter = ( function () { materialDef.pbrMetallicRoughness.metallicFactor = 0.5; materialDef.pbrMetallicRoughness.roughnessFactor = 0.5; - } + } // pbrMetallicRoughness.metallicRoughnessTexture + - // pbrMetallicRoughness.metallicRoughnessTexture if ( material.metalnessMap || material.roughnessMap ) { if ( material.metalnessMap === material.roughnessMap ) { - var metalRoughMapDef = { index: this.processTexture( material.metalnessMap ) }; + const metalRoughMapDef = { + index: this.processTexture( material.metalnessMap ) + }; this.applyTextureTransform( metalRoughMapDef, material.metalnessMap ); materialDef.pbrMetallicRoughness.metallicRoughnessTexture = metalRoughMapDef; @@ -1147,12 +1065,14 @@ THREE.GLTFExporter = ( function () { } - } + } // pbrMetallicRoughness.baseColorTexture or pbrSpecularGlossiness diffuseTexture + - // pbrMetallicRoughness.baseColorTexture or pbrSpecularGlossiness diffuseTexture if ( material.map ) { - var baseColorMapDef = { index: this.processTexture( material.map ) }; + const baseColorMapDef = { + index: this.processTexture( material.map ) + }; this.applyTextureTransform( baseColorMapDef, material.map ); materialDef.pbrMetallicRoughness.baseColorTexture = baseColorMapDef; @@ -1161,29 +1081,33 @@ THREE.GLTFExporter = ( function () { if ( material.emissive ) { // emissiveFactor - var emissive = material.emissive.clone().multiplyScalar( material.emissiveIntensity ).toArray(); + const emissive = material.emissive.clone().multiplyScalar( material.emissiveIntensity ).toArray(); if ( ! equalArray( emissive, [ 0, 0, 0 ] ) ) { materialDef.emissiveFactor = emissive; - } + } // emissiveTexture + - // emissiveTexture if ( material.emissiveMap ) { - var emissiveMapDef = { index: this.processTexture( material.emissiveMap ) }; + const emissiveMapDef = { + index: this.processTexture( material.emissiveMap ) + }; this.applyTextureTransform( emissiveMapDef, material.emissiveMap ); materialDef.emissiveTexture = emissiveMapDef; } - } + } // normalTexture + - // normalTexture if ( material.normalMap ) { - var normalMapDef = { index: this.processTexture( material.normalMap ) }; + const normalMapDef = { + index: this.processTexture( material.normalMap ) + }; if ( material.normalScale && material.normalScale.x !== - 1 ) { @@ -1200,12 +1124,12 @@ THREE.GLTFExporter = ( function () { this.applyTextureTransform( normalMapDef, material.normalMap ); materialDef.normalTexture = normalMapDef; - } + } // occlusionTexture + - // occlusionTexture if ( material.aoMap ) { - var occlusionMapDef = { + const occlusionMapDef = { index: this.processTexture( material.aoMap ), texCoord: 1 }; @@ -1219,9 +1143,9 @@ THREE.GLTFExporter = ( function () { this.applyTextureTransform( occlusionMapDef, material.aoMap ); materialDef.occlusionTexture = occlusionMapDef; - } + } // alphaMode + - // alphaMode if ( material.transparent ) { materialDef.alphaMode = 'BLEND'; @@ -1235,12 +1159,11 @@ THREE.GLTFExporter = ( function () { } - } + } // doubleSided + - // doubleSided if ( material.side === THREE.DoubleSide ) materialDef.doubleSided = true; if ( material.name !== '' ) materialDef.name = material.name; - this.serializeUserData( material, materialDef ); this._invokeAll( function ( ext ) { @@ -1249,29 +1172,29 @@ THREE.GLTFExporter = ( function () { } ); - var index = json.materials.push( materialDef ) - 1; + const index = json.materials.push( materialDef ) - 1; cache.materials.set( material, index ); return index; - }, - + } /** - * Process mesh - * @param {THREE.Mesh} mesh Mesh to process - * @return {Integer|null} Index of the processed mesh in the "meshes" array - */ - processMesh: function ( mesh ) { + * Process mesh + * @param {THREE.Mesh} mesh Mesh to process + * @return {Integer|null} Index of the processed mesh in the "meshes" array + */ - var cache = this.cache; - var json = this.json; - var meshCacheKeyParts = [ mesh.geometry.uuid ]; + processMesh( mesh ) { + + const cache = this.cache; + const json = this.json; + const meshCacheKeyParts = [ mesh.geometry.uuid ]; if ( Array.isArray( mesh.material ) ) { - for ( var i = 0, l = mesh.material.length; i < l; i ++ ) { + for ( let i = 0, l = mesh.material.length; i < l; i ++ ) { - meshCacheKeyParts.push( mesh.material[ i ].uuid ); + meshCacheKeyParts.push( mesh.material[ i ].uuid ); } @@ -1281,14 +1204,11 @@ THREE.GLTFExporter = ( function () { } - var meshCacheKey = meshCacheKeyParts.join( ':' ); - + const meshCacheKey = meshCacheKeyParts.join( ':' ); if ( cache.meshes.has( meshCacheKey ) ) return cache.meshes.get( meshCacheKey ); + const geometry = mesh.geometry; + let mode; // Use the correct mode - var geometry = mesh.geometry; - var mode; - - // Use the correct mode if ( mesh.isLineSegments ) { mode = WEBGL_CONSTANTS.LINES; @@ -1317,47 +1237,40 @@ THREE.GLTFExporter = ( function () { } - var meshDef = {}; - var attributes = {}; - var primitives = []; - var targets = []; + const meshDef = {}; + const attributes = {}; + const primitives = []; + const targets = []; // Conversion between attributes names in threejs and gltf spec - // Conversion between attributes names in threejs and gltf spec - var nameConversion = { + const nameConversion = { uv: 'TEXCOORD_0', uv2: 'TEXCOORD_1', color: 'COLOR_0', skinWeight: 'WEIGHTS_0', skinIndex: 'JOINTS_0' }; - - var originalNormal = geometry.getAttribute( 'normal' ); + const originalNormal = geometry.getAttribute( 'normal' ); if ( originalNormal !== undefined && ! this.isNormalizedNormalAttribute( originalNormal ) ) { console.warn( 'THREE.GLTFExporter: Creating normalized normal attribute from the non-normalized one.' ); - geometry.setAttribute( 'normal', this.createNormalizedNormalAttribute( originalNormal ) ); - } - - // @QUESTION Detect if .vertexColors = true? + } // @QUESTION Detect if .vertexColors = true? // For every attribute create an accessor - var modifiedAttribute = null; - for ( var attributeName in geometry.attributes ) { - // Ignore morph target attributes, which are exported later. - if ( attributeName.substr( 0, 5 ) === 'morph' ) continue; + let modifiedAttribute = null; - var attribute = geometry.attributes[ attributeName ]; - attributeName = nameConversion[ attributeName ] || attributeName.toUpperCase(); + for ( let attributeName in geometry.attributes ) { - // Prefix all geometry attributes except the ones specifically + // Ignore morph target attributes, which are exported later. + if ( attributeName.substr( 0, 5 ) === 'morph' ) continue; + const attribute = geometry.attributes[ attributeName ]; + attributeName = nameConversion[ attributeName ] || attributeName.toUpperCase(); // Prefix all geometry attributes except the ones specifically // listed in the spec; non-spec attributes are considered custom. - var validVertexAttributes = - /^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/; + const validVertexAttributes = /^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/; if ( ! validVertexAttributes.test( attributeName ) ) attributeName = '_' + attributeName; if ( cache.attributes.has( this.getUID( attribute ) ) ) { @@ -1365,22 +1278,20 @@ THREE.GLTFExporter = ( function () { attributes[ attributeName ] = cache.attributes.get( this.getUID( attribute ) ); continue; - } + } // JOINTS_0 must be UNSIGNED_BYTE or UNSIGNED_SHORT. + - // JOINTS_0 must be UNSIGNED_BYTE or UNSIGNED_SHORT. modifiedAttribute = null; - var array = attribute.array; + const array = attribute.array; - if ( attributeName === 'JOINTS_0' && - ! ( array instanceof Uint16Array ) && - ! ( array instanceof Uint8Array ) ) { + if ( attributeName === 'JOINTS_0' && ! ( array instanceof Uint16Array ) && ! ( array instanceof Uint8Array ) ) { console.warn( 'GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.' ); modifiedAttribute = new THREE.BufferAttribute( new Uint16Array( array ), attribute.itemSize, attribute.normalized ); } - var accessor = this.processAccessor( modifiedAttribute || attribute, geometry ); + const accessor = this.processAccessor( modifiedAttribute || attribute, geometry ); if ( accessor !== null ) { @@ -1391,21 +1302,19 @@ THREE.GLTFExporter = ( function () { } - if ( originalNormal !== undefined ) geometry.setAttribute( 'normal', originalNormal ); + if ( originalNormal !== undefined ) geometry.setAttribute( 'normal', originalNormal ); // Skip if no exportable attributes found - // Skip if no exportable attributes found - if ( Object.keys( attributes ).length === 0 ) return null; + if ( Object.keys( attributes ).length === 0 ) return null; // Morph targets - // Morph targets if ( mesh.morphTargetInfluences !== undefined && mesh.morphTargetInfluences.length > 0 ) { - var weights = []; - var targetNames = []; - var reverseDictionary = {}; + const weights = []; + const targetNames = []; + const reverseDictionary = {}; if ( mesh.morphTargetDictionary !== undefined ) { - for ( var key in mesh.morphTargetDictionary ) { + for ( const key in mesh.morphTargetDictionary ) { reverseDictionary[ mesh.morphTargetDictionary[ key ] ] = key; @@ -1413,16 +1322,15 @@ THREE.GLTFExporter = ( function () { } - for ( var i = 0; i < mesh.morphTargetInfluences.length; ++ i ) { + for ( let i = 0; i < mesh.morphTargetInfluences.length; ++ i ) { - var target = {}; - var warned = false; + const target = {}; + let warned = false; - for ( var attributeName in geometry.morphAttributes ) { + for ( const attributeName in geometry.morphAttributes ) { // glTF 2.0 morph supports only POSITION/NORMAL/TANGENT. // Three.js doesn't support TANGENT yet. - if ( attributeName !== 'position' && attributeName !== 'normal' ) { if ( ! warned ) { @@ -1436,36 +1344,29 @@ THREE.GLTFExporter = ( function () { } - var attribute = geometry.morphAttributes[ attributeName ][ i ]; - var gltfAttributeName = attributeName.toUpperCase(); - - // Three.js morph attribute has absolute values while the one of glTF has relative values. + const attribute = geometry.morphAttributes[ attributeName ][ i ]; + const gltfAttributeName = attributeName.toUpperCase(); // Three.js morph attribute has absolute values while the one of glTF has relative values. // // glTF 2.0 Specification: // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#morph-targets - var baseAttribute = geometry.attributes[ attributeName ]; + const baseAttribute = geometry.attributes[ attributeName ]; if ( cache.attributes.has( this.getUID( attribute ) ) ) { target[ gltfAttributeName ] = cache.attributes.get( this.getUID( attribute ) ); continue; - } + } // Clones attribute not to override + - // Clones attribute not to override - var relativeAttribute = attribute.clone(); + const relativeAttribute = attribute.clone(); if ( ! geometry.morphTargetsRelative ) { - for ( var j = 0, jl = attribute.count; j < jl; j ++ ) { + for ( let j = 0, jl = attribute.count; j < jl; j ++ ) { - relativeAttribute.setXYZ( - j, - attribute.getX( j ) - baseAttribute.getX( j ), - attribute.getY( j ) - baseAttribute.getY( j ), - attribute.getZ( j ) - baseAttribute.getZ( j ) - ); + relativeAttribute.setXYZ( j, attribute.getX( j ) - baseAttribute.getX( j ), attribute.getY( j ) - baseAttribute.getY( j ), attribute.getZ( j ) - baseAttribute.getZ( j ) ); } @@ -1477,9 +1378,7 @@ THREE.GLTFExporter = ( function () { } targets.push( target ); - weights.push( mesh.morphTargetInfluences[ i ] ); - if ( mesh.morphTargetDictionary !== undefined ) targetNames.push( reverseDictionary[ i ] ); } @@ -1495,27 +1394,27 @@ THREE.GLTFExporter = ( function () { } - var isMultiMaterial = Array.isArray( mesh.material ); - + const isMultiMaterial = Array.isArray( mesh.material ); if ( isMultiMaterial && geometry.groups.length === 0 ) return null; + const materials = isMultiMaterial ? mesh.material : [ mesh.material ]; + const groups = isMultiMaterial ? geometry.groups : [ { + materialIndex: 0, + start: undefined, + count: undefined + } ]; - var materials = isMultiMaterial ? mesh.material : [ mesh.material ]; - var groups = isMultiMaterial ? geometry.groups : [ { materialIndex: 0, start: undefined, count: undefined } ]; - - for ( var i = 0, il = groups.length; i < il; i ++ ) { + for ( let i = 0, il = groups.length; i < il; i ++ ) { - var primitive = { + const primitive = { mode: mode, - attributes: attributes, + attributes: attributes }; - this.serializeUserData( geometry, primitive ); - if ( targets.length > 0 ) primitive.targets = targets; if ( geometry.index !== null ) { - var cacheKey = this.getUID( geometry.index ); + let cacheKey = this.getUID( geometry.index ); if ( groups[ i ].start !== undefined || groups[ i ].count !== undefined ) { @@ -1538,16 +1437,13 @@ THREE.GLTFExporter = ( function () { } - var material = this.processMaterial( materials[ groups[ i ].materialIndex ] ); - + const material = this.processMaterial( materials[ groups[ i ].materialIndex ] ); if ( material !== null ) primitive.material = material; - primitives.push( primitive ); } meshDef.primitives = primitives; - if ( ! json.meshes ) json.meshes = []; this._invokeAll( function ( ext ) { @@ -1556,26 +1452,24 @@ THREE.GLTFExporter = ( function () { } ); - var index = json.meshes.push( meshDef ) - 1; + const index = json.meshes.push( meshDef ) - 1; cache.meshes.set( meshCacheKey, index ); return index; - }, - + } /** - * Process camera - * @param {THREE.Camera} camera Camera to process - * @return {Integer} Index of the processed mesh in the "camera" array - */ - processCamera: function ( camera ) { + * Process camera + * @param {THREE.Camera} camera Camera to process + * @return {Integer} Index of the processed mesh in the "camera" array + */ - var json = this.json; - if ( ! json.cameras ) json.cameras = []; - - var isOrtho = camera.isOrthographicCamera; + processCamera( camera ) { - var cameraDef = { + const json = this.json; + if ( ! json.cameras ) json.cameras = []; + const isOrtho = camera.isOrthographicCamera; + const cameraDef = { type: isOrtho ? 'orthographic' : 'perspective' }; @@ -1597,44 +1491,41 @@ THREE.GLTFExporter = ( function () { znear: camera.near < 0 ? 0 : camera.near }; - } + } // Question: Is saving "type" as name intentional? - // Question: Is saving "type" as name intentional? - if ( camera.name !== '' ) cameraDef.name = camera.type; + if ( camera.name !== '' ) cameraDef.name = camera.type; return json.cameras.push( cameraDef ) - 1; - }, - + } /** - * Creates glTF animation entry from AnimationClip object. - * - * Status: - * - Only properties listed in PATH_PROPERTIES may be animated. - * - * @param {THREE.AnimationClip} clip - * @param {THREE.Object3D} root - * @return {number|null} - */ - processAnimation: function ( clip, root ) { - - var json = this.json; - var nodeMap = this.nodeMap; + * Creates glTF animation entry from AnimationClip object. + * + * Status: + * - Only properties listed in PATH_PROPERTIES may be animated. + * + * @param {THREE.AnimationClip} clip + * @param {THREE.Object3D} root + * @return {number|null} + */ - if ( ! json.animations ) json.animations = []; - clip = THREE.GLTFExporter.Utils.mergeMorphTargetTracks( clip.clone(), root ); + processAnimation( clip, root ) { - var tracks = clip.tracks; - var channels = []; - var samplers = []; + const json = this.json; + const nodeMap = this.nodeMap; + if ( ! json.animations ) json.animations = []; + clip = GLTFExporter.Utils.mergeMorphTargetTracks( clip.clone(), root ); + const tracks = clip.tracks; + const channels = []; + const samplers = []; - for ( var i = 0; i < tracks.length; ++ i ) { + for ( let i = 0; i < tracks.length; ++ i ) { - var track = tracks[ i ]; - var trackBinding = THREE.PropertyBinding.parseTrackName( track.name ); - var trackNode = THREE.PropertyBinding.findNode( root, trackBinding.nodeName ); - var trackProperty = PATH_PROPERTIES[ trackBinding.propertyName ]; + const track = tracks[ i ]; + const trackBinding = THREE.PropertyBinding.parseTrackName( track.name ); + let trackNode = THREE.PropertyBinding.findNode( root, trackBinding.nodeName ); + const trackProperty = PATH_PROPERTIES[ trackBinding.propertyName ]; if ( trackBinding.objectName === 'bones' ) { @@ -1657,8 +1548,8 @@ THREE.GLTFExporter = ( function () { } - var inputItemSize = 1; - var outputItemSize = track.values.length / track.times.length; + const inputItemSize = 1; + let outputItemSize = track.values.length / track.times.length; if ( trackProperty === PATH_PROPERTIES.morphTargetInfluences ) { @@ -1666,20 +1557,17 @@ THREE.GLTFExporter = ( function () { } - var interpolation; - - // @TODO export CubicInterpolant(InterpolateSmooth) as CUBICSPLINE - + let interpolation; // @TODO export CubicInterpolant(InterpolateSmooth) as CUBICSPLINE // Detecting glTF cubic spline interpolant by checking factory method's special property // GLTFCubicSplineInterpolant is a custom interpolant and track doesn't return // valid value from .getInterpolation(). - if ( track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true ) { - interpolation = 'CUBICSPLINE'; + if ( track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true ) { - // itemSize of CUBICSPLINE keyframe is 9 + interpolation = 'CUBICSPLINE'; // itemSize of CUBICSPLINE keyframe is 9 // (VEC3 * 3: inTangent, splineVertex, and outTangent) // but needs to be stored as VEC3 so dividing by 3 here. + outputItemSize /= 3; } else if ( track.getInterpolation() === THREE.InterpolateDiscrete ) { @@ -1697,7 +1585,6 @@ THREE.GLTFExporter = ( function () { output: this.processAccessor( new THREE.BufferAttribute( track.values, outputItemSize ) ), interpolation: interpolation } ); - channels.push( { sampler: samplers.length - 1, target: { @@ -1713,35 +1600,29 @@ THREE.GLTFExporter = ( function () { samplers: samplers, channels: channels } ); - return json.animations.length - 1; - }, - + } /** - * @param {THREE.Object3D} object - * @return {number|null} - */ - processSkin: function ( object ) { - - var json = this.json; - var nodeMap = this.nodeMap; + * @param {THREE.Object3D} object + * @return {number|null} + */ - var node = json.nodes[ nodeMap.get( object ) ]; - var skeleton = object.skeleton; + processSkin( object ) { + const json = this.json; + const nodeMap = this.nodeMap; + const node = json.nodes[ nodeMap.get( object ) ]; + const skeleton = object.skeleton; if ( skeleton === undefined ) return null; - - var rootJoint = object.skeleton.bones[ 0 ]; - + const rootJoint = object.skeleton.bones[ 0 ]; if ( rootJoint === undefined ) return null; + const joints = []; + const inverseBindMatrices = new Float32Array( skeleton.bones.length * 16 ); + const temporaryBoneInverse = new THREE.Matrix4(); - var joints = []; - var inverseBindMatrices = new Float32Array( skeleton.bones.length * 16 ); - var temporaryBoneInverse = new THREE.Matrix4(); - - for ( var i = 0; i < skeleton.bones.length; ++ i ) { + for ( let i = 0; i < skeleton.bones.length; ++ i ) { joints.push( nodeMap.get( skeleton.bones[ i ] ) ); temporaryBoneInverse.copy( skeleton.boneInverses[ i ] ); @@ -1750,39 +1631,35 @@ THREE.GLTFExporter = ( function () { } if ( json.skins === undefined ) json.skins = []; - json.skins.push( { inverseBindMatrices: this.processAccessor( new THREE.BufferAttribute( inverseBindMatrices, 16 ) ), joints: joints, skeleton: nodeMap.get( rootJoint ) } ); - - var skinIndex = node.skin = json.skins.length - 1; - + const skinIndex = node.skin = json.skins.length - 1; return skinIndex; - }, - + } /** - * Process Object3D node - * @param {THREE.Object3D} node Object3D to processNode - * @return {Integer} Index of the node in the nodes list - */ - processNode: function ( object ) { + * Process Object3D node + * @param {THREE.Object3D} node Object3D to processNode + * @return {Integer} Index of the node in the nodes list + */ - var json = this.json; - var options = this.options; - var nodeMap = this.nodeMap; - if ( ! json.nodes ) json.nodes = []; + processNode( object ) { - var nodeDef = {}; + const json = this.json; + const options = this.options; + const nodeMap = this.nodeMap; + if ( ! json.nodes ) json.nodes = []; + const nodeDef = {}; if ( options.trs ) { - var rotation = object.quaternion.toArray(); - var position = object.position.toArray(); - var scale = object.scale.toArray(); + const rotation = object.quaternion.toArray(); + const position = object.position.toArray(); + const scale = object.scale.toArray(); if ( ! equalArray( rotation, [ 0, 0, 0, 1 ] ) ) { @@ -1816,17 +1693,15 @@ THREE.GLTFExporter = ( function () { } - } + } // We don't export empty strings name because it represents no-name in Three.js. - // We don't export empty strings name because it represents no-name in Three.js. - if ( object.name !== '' ) nodeDef.name = String( object.name ); + if ( object.name !== '' ) nodeDef.name = String( object.name ); this.serializeUserData( object, nodeDef ); if ( object.isMesh || object.isLine || object.isPoints ) { - var meshIndex = this.processMesh( object ); - + const meshIndex = this.processMesh( object ); if ( meshIndex !== null ) nodeDef.mesh = meshIndex; } else if ( object.isCamera ) { @@ -1839,16 +1714,15 @@ THREE.GLTFExporter = ( function () { if ( object.children.length > 0 ) { - var children = []; + const children = []; - for ( var i = 0, l = object.children.length; i < l; i ++ ) { + for ( let i = 0, l = object.children.length; i < l; i ++ ) { - var child = object.children[ i ]; + const child = object.children[ i ]; if ( child.visible || options.onlyVisible === false ) { - var nodeIndex = this.processNode( child ); - + const nodeIndex = this.processNode( child ); if ( nodeIndex !== null ) children.push( nodeIndex ); } @@ -1865,20 +1739,21 @@ THREE.GLTFExporter = ( function () { } ); - var nodeIndex = json.nodes.push( nodeDef ) - 1; + const nodeIndex = json.nodes.push( nodeDef ) - 1; nodeMap.set( object, nodeIndex ); return nodeIndex; - }, - + } /** - * Process Scene - * @param {THREE.Scene} node Scene to process - */ - processScene: function ( scene ) { + * Process THREE.Scene + * @param {Scene} node THREE.Scene to process + */ + - var json = this.json; - var options = this.options; + processScene( scene ) { + + const json = this.json; + const options = this.options; if ( ! json.scenes ) { @@ -1887,22 +1762,18 @@ THREE.GLTFExporter = ( function () { } - var sceneDef = {}; - + const sceneDef = {}; if ( scene.name !== '' ) sceneDef.name = scene.name; - json.scenes.push( sceneDef ); + const nodes = []; - var nodes = []; + for ( let i = 0, l = scene.children.length; i < l; i ++ ) { - for ( var i = 0, l = scene.children.length; i < l; i ++ ) { - - var child = scene.children[ i ]; + const child = scene.children[ i ]; if ( child.visible || options.onlyVisible === false ) { - var nodeIndex = this.processNode( child ); - + const nodeIndex = this.processNode( child ); if ( nodeIndex !== null ) nodes.push( nodeIndex ); } @@ -1910,21 +1781,21 @@ THREE.GLTFExporter = ( function () { } if ( nodes.length > 0 ) sceneDef.nodes = nodes; - this.serializeUserData( scene, sceneDef ); - }, - + } /** - * Creates a THREE.Scene to hold a list of objects and parse it - * @param {Array} objects List of objects to process - */ - processObjects: function ( objects ) { + * Creates a THREE.Scene to hold a list of objects and parse it + * @param {Array} objects List of objects to process + */ - var scene = new THREE.Scene(); + + processObjects( objects ) { + + const scene = new THREE.Scene(); scene.name = 'AuxScene'; - for ( var i = 0; i < objects.length; i ++ ) { + for ( let i = 0; i < objects.length; i ++ ) { // We push directly to children instead of calling `add` to prevent // modify the .parent and break its original scene and hierarchy @@ -1934,15 +1805,15 @@ THREE.GLTFExporter = ( function () { this.processScene( scene ); - }, - + } /** - * @param {THREE.Object3D|Array} input - */ - processInput: function ( input ) { + * @param {THREE.Object3D|Array} input + */ + - var options = this.options; + processInput( input ) { + const options = this.options; input = input instanceof Array ? input : [ input ]; this._invokeAll( function ( ext ) { @@ -1951,9 +1822,9 @@ THREE.GLTFExporter = ( function () { } ); - var objectsWithoutScene = []; + const objectsWithoutScene = []; - for ( var i = 0; i < input.length; i ++ ) { + for ( let i = 0; i < input.length; i ++ ) { if ( input[ i ] instanceof THREE.Scene ) { @@ -1969,13 +1840,13 @@ THREE.GLTFExporter = ( function () { if ( objectsWithoutScene.length > 0 ) this.processObjects( objectsWithoutScene ); - for ( var i = 0; i < this.skins.length; ++ i ) { + for ( let i = 0; i < this.skins.length; ++ i ) { this.processSkin( this.skins[ i ] ); } - for ( var i = 0; i < options.animations.length; ++ i ) { + for ( let i = 0; i < options.animations.length; ++ i ) { this.processAnimation( options.animations[ i ], input[ 0 ] ); @@ -1987,11 +1858,11 @@ THREE.GLTFExporter = ( function () { } ); - }, + } - _invokeAll: function ( func ) { + _invokeAll( func ) { - for ( var i = 0, il = this.plugins.length; i < il; i ++ ) { + for ( let i = 0, il = this.plugins.length; i < il; i ++ ) { func( this.plugins[ i ] ); @@ -1999,25 +1870,24 @@ THREE.GLTFExporter = ( function () { } - }; - + } /** - * Punctual Lights Extension - * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual - */ - function GLTFLightExtension( writer ) { + * Punctual Lights Extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual + */ - this.writer = writer; - this.name = 'KHR_lights_punctual'; - } + class GLTFLightExtension { + + constructor( writer ) { - GLTFLightExtension.prototype = { + this.writer = writer; + this.name = 'KHR_lights_punctual'; - constructor: GLTFLightExtension, + } - writeNode: function ( light, nodeDef ) { + writeNode( light, nodeDef ) { if ( ! light.isLight ) return; @@ -2028,16 +1898,12 @@ THREE.GLTFExporter = ( function () { } - var writer = this.writer; - var json = writer.json; - var extensionsUsed = writer.extensionsUsed; - - var lightDef = {}; - + const writer = this.writer; + const json = writer.json; + const extensionsUsed = writer.extensionsUsed; + const lightDef = {}; if ( light.name ) lightDef.name = light.name; - lightDef.color = light.color.toArray(); - lightDef.intensity = light.intensity; if ( light.isDirectionalLight ) { @@ -2047,15 +1913,12 @@ THREE.GLTFExporter = ( function () { } else if ( light.isPointLight ) { lightDef.type = 'point'; - if ( light.distance > 0 ) lightDef.range = light.distance; } else if ( light.isSpotLight ) { lightDef.type = 'spot'; - if ( light.distance > 0 ) lightDef.range = light.distance; - lightDef.spot = {}; lightDef.spot.innerConeAngle = ( light.penumbra - 1.0 ) * light.angle * - 1.0; lightDef.spot.outerConeAngle = light.angle; @@ -2064,99 +1927,88 @@ THREE.GLTFExporter = ( function () { if ( light.decay !== undefined && light.decay !== 2 ) { - console.warn( 'THREE.GLTFExporter: Light decay may be lost. glTF is physically-based, ' - + 'and expects light.decay=2.' ); + console.warn( 'THREE.GLTFExporter: Light decay may be lost. glTF is physically-based, ' + 'and expects light.decay=2.' ); } - if ( light.target - && ( light.target.parent !== light - || light.target.position.x !== 0 - || light.target.position.y !== 0 - || light.target.position.z !== - 1 ) ) { + if ( light.target && ( light.target.parent !== light || light.target.position.x !== 0 || light.target.position.y !== 0 || light.target.position.z !== - 1 ) ) { - console.warn( 'THREE.GLTFExporter: Light direction may be lost. For best results, ' - + 'make light.target a child of the light with position 0,0,-1.' ); + console.warn( 'THREE.GLTFExporter: Light direction may be lost. For best results, ' + 'make light.target a child of the light with position 0,0,-1.' ); } if ( ! extensionsUsed[ this.name ] ) { json.extensions = json.extensions || {}; - json.extensions[ this.name ] = { lights: [] }; + json.extensions[ this.name ] = { + lights: [] + }; extensionsUsed[ this.name ] = true; } - var lights = json.extensions[ this.name ].lights; + const lights = json.extensions[ this.name ].lights; lights.push( lightDef ); - nodeDef.extensions = nodeDef.extensions || {}; - nodeDef.extensions[ this.name ] = { light: lights.length - 1 }; + nodeDef.extensions[ this.name ] = { + light: lights.length - 1 + }; } - }; - + } /** - * Unlit Materials Extension - * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit - */ - function GLTFMaterialsUnlitExtension( writer ) { - - this.writer = writer; - this.name = 'KHR_materials_unlit'; + * Unlit Materials Extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit + */ - } - GLTFMaterialsUnlitExtension.prototype = { + class GLTFMaterialsUnlitExtension { - constructor: GLTFMaterialsUnlitExtension, + constructor( writer ) { - writeMaterial: function ( material, materialDef ) { + this.writer = writer; + this.name = 'KHR_materials_unlit'; - if ( ! material.isMeshBasicMaterial ) return; + } - var writer = this.writer; - var extensionsUsed = writer.extensionsUsed; + writeMaterial( material, materialDef ) { + if ( ! material.isMeshBasicMaterial ) return; + const writer = this.writer; + const extensionsUsed = writer.extensionsUsed; materialDef.extensions = materialDef.extensions || {}; materialDef.extensions[ this.name ] = {}; - extensionsUsed[ this.name ] = true; - materialDef.pbrMetallicRoughness.metallicFactor = 0.0; materialDef.pbrMetallicRoughness.roughnessFactor = 0.9; } - }; - + } /** - * Specular-Glossiness Extension - * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness - */ - function GLTFMaterialsPBRSpecularGlossiness( writer ) { + * Specular-Glossiness Extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness + */ - this.writer = writer; - this.name = 'KHR_materials_pbrSpecularGlossiness'; - } - - GLTFMaterialsPBRSpecularGlossiness.prototype = { + class GLTFMaterialsPBRSpecularGlossiness { - constructor: GLTFMaterialsPBRSpecularGlossiness, + constructor( writer ) { - writeMaterial: function ( material, materialDef ) { + this.writer = writer; + this.name = 'KHR_materials_pbrSpecularGlossiness'; - if ( ! material.isGLTFSpecularGlossinessMaterial ) return; + } - var writer = this.writer; - var extensionsUsed = writer.extensionsUsed; + writeMaterial( material, materialDef ) { - var extensionDef = {}; + if ( ! material.isGLTFSpecularGlossinessMaterial ) return; + const writer = this.writer; + const extensionsUsed = writer.extensionsUsed; + const extensionDef = {}; if ( materialDef.pbrMetallicRoughness.baseColorFactor ) { @@ -2164,7 +2016,7 @@ THREE.GLTFExporter = ( function () { } - var specularFactor = [ 1, 1, 1 ]; + const specularFactor = [ 1, 1, 1 ]; material.specular.toArray( specularFactor, 0 ); extensionDef.specularFactor = specularFactor; extensionDef.glossinessFactor = material.glossiness; @@ -2177,7 +2029,9 @@ THREE.GLTFExporter = ( function () { if ( material.specularMap ) { - var specularMapDef = { index: writer.processTexture( material.specularMap ) }; + const specularMapDef = { + index: writer.processTexture( material.specularMap ) + }; writer.applyTextureTransform( specularMapDef, material.specularMap ); extensionDef.specularGlossinessTexture = specularMapDef; @@ -2189,29 +2043,28 @@ THREE.GLTFExporter = ( function () { } - }; - + } /** - * Static utility functions - */ - GLTFExporter.Utils = { + * Static utility functions + */ - insertKeyframe: function ( track, time ) { - var tolerance = 0.001; // 1ms - var valueSize = track.getValueSize(); + GLTFExporter.Utils = { + insertKeyframe: function ( track, time ) { - var times = new track.TimeBufferType( track.times.length + 1 ); - var values = new track.ValueBufferType( track.values.length + valueSize ); - var interpolant = track.createInterpolant( new track.ValueBufferType( valueSize ) ); + const tolerance = 0.001; // 1ms - var index; + const valueSize = track.getValueSize(); + const times = new track.TimeBufferType( track.times.length + 1 ); + const values = new track.ValueBufferType( track.values.length + valueSize ); + const interpolant = track.createInterpolant( new track.ValueBufferType( valueSize ) ); + let index; if ( track.times.length === 0 ) { times[ 0 ] = time; - for ( var i = 0; i < valueSize; i ++ ) { + for ( let i = 0; i < valueSize; i ++ ) { values[ i ] = 0; @@ -2222,13 +2075,10 @@ THREE.GLTFExporter = ( function () { } else if ( time < track.times[ 0 ] ) { if ( Math.abs( track.times[ 0 ] - time ) < tolerance ) return 0; - times[ 0 ] = time; times.set( track.times, 1 ); - values.set( interpolant.evaluate( time ), 0 ); values.set( track.values, valueSize ); - index = 0; } else if ( time > track.times[ track.times.length - 1 ] ) { @@ -2241,15 +2091,13 @@ THREE.GLTFExporter = ( function () { times[ times.length - 1 ] = time; times.set( track.times, 0 ); - values.set( track.values, 0 ); values.set( interpolant.evaluate( time ), track.values.length ); - index = times.length - 1; } else { - for ( var i = 0; i < track.times.length; i ++ ) { + for ( let i = 0; i < track.times.length; i ++ ) { if ( Math.abs( track.times[ i ] - time ) < tolerance ) return i; @@ -2258,13 +2106,10 @@ THREE.GLTFExporter = ( function () { times.set( track.times.slice( 0, i + 1 ), 0 ); times[ i + 1 ] = time; times.set( track.times.slice( i + 1 ), i + 2 ); - values.set( track.values.slice( 0, ( i + 1 ) * valueSize ), 0 ); values.set( interpolant.evaluate( time ), ( i + 1 ) * valueSize ); values.set( track.values.slice( ( i + 1 ) * valueSize ), ( i + 2 ) * valueSize ); - index = i + 1; - break; } @@ -2275,22 +2120,20 @@ THREE.GLTFExporter = ( function () { track.times = times; track.values = values; - return index; }, - mergeMorphTargetTracks: function ( clip, root ) { - var tracks = []; - var mergedTracks = {}; - var sourceTracks = clip.tracks; + const tracks = []; + const mergedTracks = {}; + const sourceTracks = clip.tracks; - for ( var i = 0; i < sourceTracks.length; ++ i ) { + for ( let i = 0; i < sourceTracks.length; ++ i ) { - var sourceTrack = sourceTracks[ i ]; - var sourceTrackBinding = THREE.PropertyBinding.parseTrackName( sourceTrack.name ); - var sourceTrackNode = THREE.PropertyBinding.findNode( root, sourceTrackBinding.nodeName ); + let sourceTrack = sourceTracks[ i ]; + const sourceTrackBinding = THREE.PropertyBinding.parseTrackName( sourceTrack.name ); + const sourceTrackNode = THREE.PropertyBinding.findNode( root, sourceTrackBinding.nodeName ); if ( sourceTrackBinding.propertyName !== 'morphTargetInfluences' || sourceTrackBinding.propertyIndex === undefined ) { @@ -2300,8 +2143,7 @@ THREE.GLTFExporter = ( function () { } - if ( sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodDiscrete - && sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodLinear ) { + if ( sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodDiscrete && sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodLinear ) { if ( sourceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { @@ -2312,14 +2154,13 @@ THREE.GLTFExporter = ( function () { } console.warn( 'THREE.GLTFExporter: Morph target interpolation mode not yet supported. Using LINEAR instead.' ); - sourceTrack = sourceTrack.clone(); sourceTrack.setInterpolation( THREE.InterpolateLinear ); } - var targetCount = sourceTrackNode.morphTargetInfluences.length; - var targetIndex = sourceTrackNode.morphTargetDictionary[ sourceTrackBinding.propertyIndex ]; + const targetCount = sourceTrackNode.morphTargetInfluences.length; + const targetIndex = sourceTrackNode.morphTargetDictionary[ sourceTrackBinding.propertyIndex ]; if ( targetIndex === undefined ) { @@ -2327,52 +2168,46 @@ THREE.GLTFExporter = ( function () { } - var mergedTrack; - - // If this is the first time we've seen this object, create a new + let mergedTrack; // If this is the first time we've seen this object, create a new // track to store merged keyframe data for each morph target. + if ( mergedTracks[ sourceTrackNode.uuid ] === undefined ) { mergedTrack = sourceTrack.clone(); + const values = new mergedTrack.ValueBufferType( targetCount * mergedTrack.times.length ); - var values = new mergedTrack.ValueBufferType( targetCount * mergedTrack.times.length ); - - for ( var j = 0; j < mergedTrack.times.length; j ++ ) { + for ( let j = 0; j < mergedTrack.times.length; j ++ ) { values[ j * targetCount + targetIndex ] = mergedTrack.values[ j ]; - } - - // We need to take into consideration the intended target node + } // We need to take into consideration the intended target node // of our original un-merged morphTarget animation. + + mergedTrack.name = ( sourceTrackBinding.nodeName || '' ) + '.morphTargetInfluences'; mergedTrack.values = values; - mergedTracks[ sourceTrackNode.uuid ] = mergedTrack; tracks.push( mergedTrack ); - continue; } - var sourceInterpolant = sourceTrack.createInterpolant( new sourceTrack.ValueBufferType( 1 ) ); - - mergedTrack = mergedTracks[ sourceTrackNode.uuid ]; - - // For every existing keyframe of the merged track, write a (possibly + const sourceInterpolant = sourceTrack.createInterpolant( new sourceTrack.ValueBufferType( 1 ) ); + mergedTrack = mergedTracks[ sourceTrackNode.uuid ]; // For every existing keyframe of the merged track, write a (possibly // interpolated) value from the source track. - for ( var j = 0; j < mergedTrack.times.length; j ++ ) { - mergedTrack.values[ j * targetCount + targetIndex ] = sourceInterpolant.evaluate( mergedTrack.times[ j ] ); + for ( let j = 0; j < mergedTrack.times.length; j ++ ) { - } + mergedTrack.values[ j * targetCount + targetIndex ] = sourceInterpolant.evaluate( mergedTrack.times[ j ] ); - // For every existing keyframe of the source track, write a (possibly + } // For every existing keyframe of the source track, write a (possibly // new) keyframe to the merged track. Values from the previous loop may // be written again, but keyframes are de-duplicated. - for ( var j = 0; j < sourceTrack.times.length; j ++ ) { - var keyframeIndex = this.insertKeyframe( mergedTrack, sourceTrack.times[ j ] ); + + for ( let j = 0; j < sourceTrack.times.length; j ++ ) { + + const keyframeIndex = this.insertKeyframe( mergedTrack, sourceTrack.times[ j ] ); mergedTrack.values[ keyframeIndex * targetCount + targetIndex ] = sourceTrack.values[ j ]; } @@ -2380,13 +2215,11 @@ THREE.GLTFExporter = ( function () { } clip.tracks = tracks; - return clip; } - }; - return GLTFExporter; + THREE.GLTFExporter = GLTFExporter; } )(); diff --git a/examples/js/exporters/MMDExporter.js b/examples/js/exporters/MMDExporter.js index 0a1329442dd138..c3dabde628344c 100644 --- a/examples/js/exporters/MMDExporter.js +++ b/examples/js/exporters/MMDExporter.js @@ -1,208 +1,194 @@ -/** +( function () { + + /** * Dependencies * - mmd-parser https://github.com/takahirox/mmd-parser */ -THREE.MMDExporter = function () { - - // Unicode to Shift_JIS table - var u2sTable; - - function unicodeToShiftjis( str ) { - - if ( u2sTable === undefined ) { + class MMDExporter { - var encoder = new MMDParser.CharsetEncoder(); // eslint-disable-line no-undef - var table = encoder.s2uTable; - u2sTable = {}; + /* TODO: implement + // mesh -> pmd + this.parsePmd = function ( object ) { + }; + */ - var keys = Object.keys( table ); + /* TODO: implement + // mesh -> pmx + this.parsePmx = function ( object ) { + }; + */ - for ( var i = 0, il = keys.length; i < il; i ++ ) { + /* TODO: implement + // animation + skeleton -> vmd + this.parseVmd = function ( object ) { + }; + */ - var key = keys[ i ]; + /* + * skeleton -> vpd + * Returns Shift_JIS encoded Uint8Array. Otherwise return strings. + */ + parseVpd( skin, outputShiftJis, useOriginalBones ) { - var value = table[ key ]; - key = parseInt( key ); + if ( skin.isSkinnedMesh !== true ) { - u2sTable[ value ] = key; + console.warn( 'THREE.MMDExporter: parseVpd() requires SkinnedMesh instance.' ); + return null; } - } - - var array = []; - - for ( var i = 0, il = str.length; i < il; i ++ ) { + function toStringsFromNumber( num ) { - var code = str.charCodeAt( i ); + if ( Math.abs( num ) < 1e-6 ) num = 0; + let a = num.toString(); - var value = u2sTable[ code ]; + if ( a.indexOf( '.' ) === - 1 ) { - if ( value === undefined ) { + a += '.'; - throw 'cannot convert charcode 0x' + code.toString( 16 ); + } - } else if ( value > 0xff ) { - - array.push( ( value >> 8 ) & 0xff ); - array.push( value & 0xff ); - - } else { - - array.push( value & 0xff ); + a += '000000'; + const index = a.indexOf( '.' ); + const d = a.slice( 0, index ); + const p = a.slice( index + 1, index + 7 ); + return d + '.' + p; } - } + function toStringsFromArray( array ) { - return new Uint8Array( array ); + const a = []; - } + for ( let i = 0, il = array.length; i < il; i ++ ) { - function getBindBones( skin ) { + a.push( toStringsFromNumber( array[ i ] ) ); - // any more efficient ways? - var poseSkin = skin.clone(); - poseSkin.pose(); - return poseSkin.skeleton.bones; + } - } + return a.join( ',' ); - /* TODO: implement - // mesh -> pmd - this.parsePmd = function ( object ) { + } - }; - */ + skin.updateMatrixWorld( true ); + const bones = skin.skeleton.bones; + const bones2 = getBindBones( skin ); + const position = new THREE.Vector3(); + const quaternion = new THREE.Quaternion(); + const quaternion2 = new THREE.Quaternion(); + const matrix = new THREE.Matrix4(); + const array = []; + array.push( 'Vocaloid Pose Data file' ); + array.push( '' ); + array.push( ( skin.name !== '' ? skin.name.replace( /\s/g, '_' ) : 'skin' ) + '.osm;' ); + array.push( bones.length + ';' ); + array.push( '' ); - /* TODO: implement - // mesh -> pmx - this.parsePmx = function ( object ) { + for ( let i = 0, il = bones.length; i < il; i ++ ) { - }; - */ + const bone = bones[ i ]; + const bone2 = bones2[ i ]; + /* + * use the bone matrix saved before solving IK. + * see CCDIKSolver for the detail. + */ - /* - * skeleton -> vpd - * Returns Shift_JIS encoded Uint8Array. Otherwise return strings. - */ - this.parseVpd = function ( skin, outputShiftJis, useOriginalBones ) { + if ( useOriginalBones === true && bone.userData.ik !== undefined && bone.userData.ik.originalMatrix !== undefined ) { - if ( skin.isSkinnedMesh !== true ) { + matrix.fromArray( bone.userData.ik.originalMatrix ); - console.warn( 'THREE.MMDExporter: parseVpd() requires SkinnedMesh instance.' ); - return null; + } else { - } + matrix.copy( bone.matrix ); - function toStringsFromNumber( num ) { + } - if ( Math.abs( num ) < 1e-6 ) num = 0; + position.setFromMatrixPosition( matrix ); + quaternion.setFromRotationMatrix( matrix ); + const pArray = position.sub( bone2.position ).toArray(); + const qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray(); // right to left - var a = num.toString(); + pArray[ 2 ] = - pArray[ 2 ]; + qArray[ 0 ] = - qArray[ 0 ]; + qArray[ 1 ] = - qArray[ 1 ]; + array.push( 'Bone' + i + '{' + bone.name ); + array.push( ' ' + toStringsFromArray( pArray ) + ';' ); + array.push( ' ' + toStringsFromArray( qArray ) + ';' ); + array.push( '}' ); + array.push( '' ); - if ( a.indexOf( '.' ) === - 1 ) { + } - a += '.'; + array.push( '' ); + const lines = array.join( '\n' ); + return outputShiftJis === true ? unicodeToShiftjis( lines ) : lines; - } + } - a += '000000'; + } // Unicode to Shift_JIS table - var index = a.indexOf( '.' ); - var d = a.slice( 0, index ); - var p = a.slice( index + 1, index + 7 ); + let u2sTable; - return d + '.' + p; + function unicodeToShiftjis( str ) { - } + if ( u2sTable === undefined ) { - function toStringsFromArray( array ) { + const encoder = new MMDParser.CharsetEncoder(); // eslint-disable-line no-undef - var a = []; + const table = encoder.s2uTable; + u2sTable = {}; + const keys = Object.keys( table ); - for ( var i = 0, il = array.length; i < il; i ++ ) { + for ( let i = 0, il = keys.length; i < il; i ++ ) { - a.push( toStringsFromNumber( array[ i ] ) ); + let key = keys[ i ]; + const value = table[ key ]; + key = parseInt( key ); + u2sTable[ value ] = key; } - return a.join( ',' ); - } - skin.updateMatrixWorld( true ); - - var bones = skin.skeleton.bones; - var bones2 = getBindBones( skin ); + const array = []; - var position = new THREE.Vector3(); - var quaternion = new THREE.Quaternion(); - var quaternion2 = new THREE.Quaternion(); - var matrix = new THREE.Matrix4(); + for ( let i = 0, il = str.length; i < il; i ++ ) { - var array = []; - array.push( 'Vocaloid Pose Data file' ); - array.push( '' ); - array.push( ( skin.name !== '' ? skin.name.replace( /\s/g, '_' ) : 'skin' ) + '.osm;' ); - array.push( bones.length + ';' ); - array.push( '' ); + const code = str.charCodeAt( i ); + const value = u2sTable[ code ]; - for ( var i = 0, il = bones.length; i < il; i ++ ) { + if ( value === undefined ) { - var bone = bones[ i ]; - var bone2 = bones2[ i ]; + throw 'cannot convert charcode 0x' + code.toString( 16 ); - /* - * use the bone matrix saved before solving IK. - * see CCDIKSolver for the detail. - */ - if ( useOriginalBones === true && - bone.userData.ik !== undefined && - bone.userData.ik.originalMatrix !== undefined ) { + } else if ( value > 0xff ) { - matrix.fromArray( bone.userData.ik.originalMatrix ); + array.push( value >> 8 & 0xff ); + array.push( value & 0xff ); } else { - matrix.copy( bone.matrix ); + array.push( value & 0xff ); } - position.setFromMatrixPosition( matrix ); - quaternion.setFromRotationMatrix( matrix ); - - var pArray = position.sub( bone2.position ).toArray(); - var qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray(); - - // right to left - pArray[ 2 ] = - pArray[ 2 ]; - qArray[ 0 ] = - qArray[ 0 ]; - qArray[ 1 ] = - qArray[ 1 ]; - - array.push( 'Bone' + i + '{' + bone.name ); - array.push( ' ' + toStringsFromArray( pArray ) + ';' ); - array.push( ' ' + toStringsFromArray( qArray ) + ';' ); - array.push( '}' ); - array.push( '' ); - } - array.push( '' ); + return new Uint8Array( array ); - var lines = array.join( '\n' ); + } - return ( outputShiftJis === true ) ? unicodeToShiftjis( lines ) : lines; + function getBindBones( skin ) { - }; + // any more efficient ways? + const poseSkin = skin.clone(); + poseSkin.pose(); + return poseSkin.skeleton.bones; - /* TODO: implement - // animation + skeleton -> vmd - this.parseVmd = function ( object ) { + } - }; - */ + THREE.MMDExporter = MMDExporter; -}; +} )(); diff --git a/examples/js/exporters/OBJExporter.js b/examples/js/exporters/OBJExporter.js index 2c76df295b58bc..bb9e4490d75284 100644 --- a/examples/js/exporters/OBJExporter.js +++ b/examples/js/exporters/OBJExporter.js @@ -1,304 +1,278 @@ -THREE.OBJExporter = function () {}; +( function () { -THREE.OBJExporter.prototype = { + class OBJExporter { - constructor: THREE.OBJExporter, + parse( object ) { - parse: function ( object ) { + let output = ''; + let indexVertex = 0; + let indexVertexUvs = 0; + let indexNormals = 0; + const vertex = new THREE.Vector3(); + const color = new THREE.Color(); + const normal = new THREE.Vector3(); + const uv = new THREE.Vector2(); + const face = []; - var output = ''; + function parseMesh( mesh ) { - var indexVertex = 0; - var indexVertexUvs = 0; - var indexNormals = 0; + let nbVertex = 0; + let nbNormals = 0; + let nbVertexUvs = 0; + const geometry = mesh.geometry; + const normalMatrixWorld = new THREE.Matrix3(); - var vertex = new THREE.Vector3(); - var color = new THREE.Color(); - var normal = new THREE.Vector3(); - var uv = new THREE.Vector2(); + if ( geometry.isBufferGeometry !== true ) { - var i, j, k, l, m, face = []; + throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' ); - var parseMesh = function ( mesh ) { + } // shortcuts - var nbVertex = 0; - var nbNormals = 0; - var nbVertexUvs = 0; - var geometry = mesh.geometry; + const vertices = geometry.getAttribute( 'position' ); + const normals = geometry.getAttribute( 'normal' ); + const uvs = geometry.getAttribute( 'uv' ); + const indices = geometry.getIndex(); // name of the mesh object - var normalMatrixWorld = new THREE.Matrix3(); + output += 'o ' + mesh.name + '\n'; // name of the mesh material - if ( geometry.isBufferGeometry !== true ) { + if ( mesh.material && mesh.material.name ) { - throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' ); + output += 'usemtl ' + mesh.material.name + '\n'; - } - - // shortcuts - var vertices = geometry.getAttribute( 'position' ); - var normals = geometry.getAttribute( 'normal' ); - var uvs = geometry.getAttribute( 'uv' ); - var indices = geometry.getIndex(); - - // name of the mesh object - output += 'o ' + mesh.name + '\n'; + } // vertices - // name of the mesh material - if ( mesh.material && mesh.material.name ) { - output += 'usemtl ' + mesh.material.name + '\n'; + if ( vertices !== undefined ) { - } - - // vertices + for ( let i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { - if ( vertices !== undefined ) { + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); // transform the vertex to world space - for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + vertex.applyMatrix4( mesh.matrixWorld ); // transform the vertex to export format - vertex.x = vertices.getX( i ); - vertex.y = vertices.getY( i ); - vertex.z = vertices.getZ( i ); + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; - // transform the vertex to world space - vertex.applyMatrix4( mesh.matrixWorld ); + } - // transform the vertex to export format - output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + } // uvs - } - } + if ( uvs !== undefined ) { - // uvs + for ( let i = 0, l = uvs.count; i < l; i ++, nbVertexUvs ++ ) { - if ( uvs !== undefined ) { + uv.x = uvs.getX( i ); + uv.y = uvs.getY( i ); // transform the uv to export format - for ( i = 0, l = uvs.count; i < l; i ++, nbVertexUvs ++ ) { + output += 'vt ' + uv.x + ' ' + uv.y + '\n'; - uv.x = uvs.getX( i ); - uv.y = uvs.getY( i ); + } - // transform the uv to export format - output += 'vt ' + uv.x + ' ' + uv.y + '\n'; + } // normals - } - } + if ( normals !== undefined ) { - // normals + normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); - if ( normals !== undefined ) { + for ( let i = 0, l = normals.count; i < l; i ++, nbNormals ++ ) { - normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); + normal.x = normals.getX( i ); + normal.y = normals.getY( i ); + normal.z = normals.getZ( i ); // transform the normal to world space - for ( i = 0, l = normals.count; i < l; i ++, nbNormals ++ ) { + normal.applyMatrix3( normalMatrixWorld ).normalize(); // transform the normal to export format - normal.x = normals.getX( i ); - normal.y = normals.getY( i ); - normal.z = normals.getZ( i ); + output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; - // transform the normal to world space - normal.applyMatrix3( normalMatrixWorld ).normalize(); + } - // transform the normal to export format - output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; + } // faces - } - } + if ( indices !== null ) { - // faces + for ( let i = 0, l = indices.count; i < l; i += 3 ) { - if ( indices !== null ) { + for ( let m = 0; m < 3; m ++ ) { - for ( i = 0, l = indices.count; i < l; i += 3 ) { + const j = indices.getX( i + m ) + 1; + face[ m ] = indexVertex + j + ( normals || uvs ? '/' + ( uvs ? indexVertexUvs + j : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); - for ( m = 0; m < 3; m ++ ) { + } // transform the face to export format - j = indices.getX( i + m ) + 1; - face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); + output += 'f ' + face.join( ' ' ) + '\n'; } - // transform the face to export format - output += 'f ' + face.join( ' ' ) + '\n'; + } else { - } + for ( let i = 0, l = vertices.count; i < l; i += 3 ) { - } else { + for ( let m = 0; m < 3; m ++ ) { - for ( i = 0, l = vertices.count; i < l; i += 3 ) { + const j = i + m + 1; + face[ m ] = indexVertex + j + ( normals || uvs ? '/' + ( uvs ? indexVertexUvs + j : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); - for ( m = 0; m < 3; m ++ ) { + } // transform the face to export format - j = i + m + 1; - face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' ); + output += 'f ' + face.join( ' ' ) + '\n'; } - // transform the face to export format - output += 'f ' + face.join( ' ' ) + '\n'; + } // update index - } - } + indexVertex += nbVertex; + indexVertexUvs += nbVertexUvs; + indexNormals += nbNormals; - // update index - indexVertex += nbVertex; - indexVertexUvs += nbVertexUvs; - indexNormals += nbNormals; + } - }; + function parseLine( line ) { - var parseLine = function ( line ) { + let nbVertex = 0; + const geometry = line.geometry; + const type = line.type; - var nbVertex = 0; + if ( geometry.isBufferGeometry !== true ) { - var geometry = line.geometry; - var type = line.type; + throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' ); - if ( geometry.isBufferGeometry !== true ) { + } // shortcuts - throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' ); - } + const vertices = geometry.getAttribute( 'position' ); // name of the line object - // shortcuts - var vertices = geometry.getAttribute( 'position' ); + output += 'o ' + line.name + '\n'; - // name of the line object - output += 'o ' + line.name + '\n'; + if ( vertices !== undefined ) { - if ( vertices !== undefined ) { + for ( let i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { - for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); // transform the vertex to world space - vertex.x = vertices.getX( i ); - vertex.y = vertices.getY( i ); - vertex.z = vertices.getZ( i ); + vertex.applyMatrix4( line.matrixWorld ); // transform the vertex to export format - // transform the vertex to world space - vertex.applyMatrix4( line.matrixWorld ); + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; - // transform the vertex to export format - output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + } } - } - - if ( type === 'Line' ) { - - output += 'l '; + if ( type === 'Line' ) { - for ( j = 1, l = vertices.count; j <= l; j ++ ) { + output += 'l '; - output += ( indexVertex + j ) + ' '; + for ( let j = 1, l = vertices.count; j <= l; j ++ ) { - } + output += indexVertex + j + ' '; - output += '\n'; + } - } + output += '\n'; - if ( type === 'LineSegments' ) { + } - for ( j = 1, k = j + 1, l = vertices.count; j < l; j += 2, k = j + 1 ) { + if ( type === 'LineSegments' ) { - output += 'l ' + ( indexVertex + j ) + ' ' + ( indexVertex + k ) + '\n'; + for ( let j = 1, k = j + 1, l = vertices.count; j < l; j += 2, k = j + 1 ) { - } + output += 'l ' + ( indexVertex + j ) + ' ' + ( indexVertex + k ) + '\n'; - } + } - // update index - indexVertex += nbVertex; + } // update index - }; - var parsePoints = function ( points ) { + indexVertex += nbVertex; - var nbVertex = 0; + } - var geometry = points.geometry; + function parsePoints( points ) { - if ( geometry.isBufferGeometry !== true ) { + let nbVertex = 0; + const geometry = points.geometry; - throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' ); + if ( geometry.isBufferGeometry !== true ) { - } + throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' ); - var vertices = geometry.getAttribute( 'position' ); - var colors = geometry.getAttribute( 'color' ); + } - output += 'o ' + points.name + '\n'; + const vertices = geometry.getAttribute( 'position' ); + const colors = geometry.getAttribute( 'color' ); + output += 'o ' + points.name + '\n'; - if ( vertices !== undefined ) { + if ( vertices !== undefined ) { - for ( i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { + for ( let i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) { - vertex.fromBufferAttribute( vertices, i ); - vertex.applyMatrix4( points.matrixWorld ); + vertex.fromBufferAttribute( vertices, i ); + vertex.applyMatrix4( points.matrixWorld ); + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z; - output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z; + if ( colors !== undefined ) { - if ( colors !== undefined ) { + color.fromBufferAttribute( colors, i ); + output += ' ' + color.r + ' ' + color.g + ' ' + color.b; - color.fromBufferAttribute( colors, i ); + } - output += ' ' + color.r + ' ' + color.g + ' ' + color.b; + output += '\n'; } - output += '\n'; - } - } - - output += 'p '; + output += 'p '; - for ( j = 1, l = vertices.count; j <= l; j ++ ) { + for ( let j = 1, l = vertices.count; j <= l; j ++ ) { - output += ( indexVertex + j ) + ' '; + output += indexVertex + j + ' '; - } + } - output += '\n'; + output += '\n'; // update index - // update index - indexVertex += nbVertex; + indexVertex += nbVertex; - }; + } - object.traverse( function ( child ) { + object.traverse( function ( child ) { - if ( child.isMesh === true ) { + if ( child.isMesh === true ) { - parseMesh( child ); + parseMesh( child ); - } + } - if ( child.isLine === true ) { + if ( child.isLine === true ) { - parseLine( child ); + parseLine( child ); - } + } - if ( child.isPoints === true ) { + if ( child.isPoints === true ) { - parsePoints( child ); + parsePoints( child ); - } + } - } ); + } ); + return output; - return output; + } } -}; + THREE.OBJExporter = OBJExporter; + +} )(); diff --git a/examples/js/exporters/PLYExporter.js b/examples/js/exporters/PLYExporter.js index b58c0d5e0807e7..ac42b21b0daf6e 100644 --- a/examples/js/exporters/PLYExporter.js +++ b/examples/js/exporters/PLYExporter.js @@ -1,8 +1,10 @@ -/** +( function () { + + /** * https://github.com/gkjohnson/ply-exporter-js * * Usage: - * var exporter = new THREE.PLYExporter(); + * const exporter = new PLYExporter(); * * // second argument is a list of options * exporter.parse(mesh, data => console.log(data), { binary: true, excludeAttributes: [ 'color' ], littleEndian: true }); @@ -11,513 +13,427 @@ * http://paulbourke.net/dataformats/ply/ */ -THREE.PLYExporter = function () {}; + class PLYExporter { -THREE.PLYExporter.prototype = { + parse( object, onDone, options ) { - constructor: THREE.PLYExporter, + if ( onDone && typeof onDone === 'object' ) { - parse: function ( object, onDone, options ) { + console.warn( 'THREE.PLYExporter: The options parameter is now the third argument to the "parse" function. See the documentation for the new API.' ); + options = onDone; + onDone = undefined; - if ( onDone && typeof onDone === 'object' ) { + } // Iterate over the valid meshes in the object - console.warn( 'THREE.PLYExporter: The options parameter is now the third argument to the "parse" function. See the documentation for the new API.' ); - options = onDone; - onDone = undefined; - } + function traverseMeshes( cb ) { - // Iterate over the valid meshes in the object - function traverseMeshes( cb ) { + object.traverse( function ( child ) { - object.traverse( function ( child ) { + if ( child.isMesh === true ) { - if ( child.isMesh === true ) { + const mesh = child; + const geometry = mesh.geometry; - var mesh = child; - var geometry = mesh.geometry; + if ( geometry.isBufferGeometry !== true ) { - if ( geometry.isBufferGeometry !== true ) { + throw new Error( 'THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.' ); - throw new Error( 'THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.' ); + } - } + if ( geometry.hasAttribute( 'position' ) === true ) { - if ( geometry.hasAttribute( 'position' ) === true ) { + cb( mesh, geometry ); - cb( mesh, geometry ); + } } - } + } ); - } ); + } // Default options - } - // Default options - var defaultOptions = { - binary: false, - excludeAttributes: [], // normal, uv, color, index - littleEndian: false - }; + const defaultOptions = { + binary: false, + excludeAttributes: [], + // normal, uv, color, index + littleEndian: false + }; + options = Object.assign( defaultOptions, options ); + const excludeAttributes = options.excludeAttributes; + let includeNormals = false; + let includeColors = false; + let includeUVs = false; // count the vertices, check which properties are used, + // and cache the BufferGeometry - options = Object.assign( defaultOptions, options ); + let vertexCount = 0; + let faceCount = 0; + object.traverse( function ( child ) { - var excludeAttributes = options.excludeAttributes; - var includeNormals = false; - var includeColors = false; - var includeUVs = false; + if ( child.isMesh === true ) { - // count the vertices, check which properties are used, - // and cache the BufferGeometry - var vertexCount = 0; - var faceCount = 0; - object.traverse( function ( child ) { + const mesh = child; + const geometry = mesh.geometry; - if ( child.isMesh === true ) { + if ( geometry.isBufferGeometry !== true ) { - var mesh = child; - var geometry = mesh.geometry; + throw new Error( 'THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.' ); - if ( geometry.isBufferGeometry !== true ) { + } - throw new Error( 'THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.' ); + const vertices = geometry.getAttribute( 'position' ); + const normals = geometry.getAttribute( 'normal' ); + const uvs = geometry.getAttribute( 'uv' ); + const colors = geometry.getAttribute( 'color' ); + const indices = geometry.getIndex(); - } + if ( vertices === undefined ) { - var vertices = geometry.getAttribute( 'position' ); - var normals = geometry.getAttribute( 'normal' ); - var uvs = geometry.getAttribute( 'uv' ); - var colors = geometry.getAttribute( 'color' ); - var indices = geometry.getIndex(); + return; - if ( vertices === undefined ) { + } - return; + vertexCount += vertices.count; + faceCount += indices ? indices.count / 3 : vertices.count / 3; + if ( normals !== undefined ) includeNormals = true; + if ( uvs !== undefined ) includeUVs = true; + if ( colors !== undefined ) includeColors = true; } - vertexCount += vertices.count; - faceCount += indices ? indices.count / 3 : vertices.count / 3; - - if ( normals !== undefined ) includeNormals = true; + } ); + const includeIndices = excludeAttributes.indexOf( 'index' ) === - 1; + includeNormals = includeNormals && excludeAttributes.indexOf( 'normal' ) === - 1; + includeColors = includeColors && excludeAttributes.indexOf( 'color' ) === - 1; + includeUVs = includeUVs && excludeAttributes.indexOf( 'uv' ) === - 1; - if ( uvs !== undefined ) includeUVs = true; + if ( includeIndices && faceCount !== Math.floor( faceCount ) ) { - if ( colors !== undefined ) includeColors = true; + // point cloud meshes will not have an index array and may not have a + // number of vertices that is divisble by 3 (and therefore representable + // as triangles) + console.error( 'PLYExporter: Failed to generate a valid PLY file with triangle indices because the ' + 'number of indices is not divisible by 3.' ); + return null; } - } ); - - var includeIndices = excludeAttributes.indexOf( 'index' ) === - 1; - includeNormals = includeNormals && excludeAttributes.indexOf( 'normal' ) === - 1; - includeColors = includeColors && excludeAttributes.indexOf( 'color' ) === - 1; - includeUVs = includeUVs && excludeAttributes.indexOf( 'uv' ) === - 1; - + const indexByteCount = 4; + let header = 'ply\n' + `format ${options.binary ? options.littleEndian ? 'binary_little_endian' : 'binary_big_endian' : 'ascii'} 1.0\n` + `element vertex ${vertexCount}\n` + // position + 'property float x\n' + 'property float y\n' + 'property float z\n'; - if ( includeIndices && faceCount !== Math.floor( faceCount ) ) { + if ( includeNormals === true ) { - // point cloud meshes will not have an index array and may not have a - // number of vertices that is divisble by 3 (and therefore representable - // as triangles) - console.error( + // normal + header += 'property float nx\n' + 'property float ny\n' + 'property float nz\n'; - 'PLYExporter: Failed to generate a valid PLY file with triangle indices because the ' + - 'number of indices is not divisible by 3.' - - ); - - return null; - - } - - var indexByteCount = 4; - - var header = - 'ply\n' + - `format ${ options.binary ? ( options.littleEndian ? 'binary_little_endian' : 'binary_big_endian' ) : 'ascii' } 1.0\n` + - `element vertex ${vertexCount}\n` + - - // position - 'property float x\n' + - 'property float y\n' + - 'property float z\n'; - - if ( includeNormals === true ) { - - // normal - header += - 'property float nx\n' + - 'property float ny\n' + - 'property float nz\n'; - - } - - if ( includeUVs === true ) { - - // uvs - header += - 'property float s\n' + - 'property float t\n'; - - } - - if ( includeColors === true ) { - - // colors - header += - 'property uchar red\n' + - 'property uchar green\n' + - 'property uchar blue\n'; - - } + } - if ( includeIndices === true ) { + if ( includeUVs === true ) { - // faces - header += - `element face ${faceCount}\n` + - 'property list uchar int vertex_index\n'; + // uvs + header += 'property float s\n' + 'property float t\n'; - } + } - header += 'end_header\n'; + if ( includeColors === true ) { + // colors + header += 'property uchar red\n' + 'property uchar green\n' + 'property uchar blue\n'; - // Generate attribute data - var vertex = new THREE.Vector3(); - var normalMatrixWorld = new THREE.Matrix3(); - var result = null; + } - if ( options.binary === true ) { + if ( includeIndices === true ) { - // Binary File Generation - var headerBin = new TextEncoder().encode( header ); + // faces + header += `element face ${faceCount}\n` + 'property list uchar int vertex_index\n'; - // 3 position values at 4 bytes - // 3 normal values at 4 bytes - // 3 color channels with 1 byte - // 2 uv values at 4 bytes - var vertexListLength = vertexCount * ( 4 * 3 + ( includeNormals ? 4 * 3 : 0 ) + ( includeColors ? 3 : 0 ) + ( includeUVs ? 4 * 2 : 0 ) ); + } - // 1 byte shape desciptor - // 3 vertex indices at ${indexByteCount} bytes - var faceListLength = includeIndices ? faceCount * ( indexByteCount * 3 + 1 ) : 0; - var output = new DataView( new ArrayBuffer( headerBin.length + vertexListLength + faceListLength ) ); - new Uint8Array( output.buffer ).set( headerBin, 0 ); + header += 'end_header\n'; // Generate attribute data + const vertex = new THREE.Vector3(); + const normalMatrixWorld = new THREE.Matrix3(); + let result = null; - var vOffset = headerBin.length; - var fOffset = headerBin.length + vertexListLength; - var writtenVertices = 0; - traverseMeshes( function ( mesh, geometry ) { + if ( options.binary === true ) { - var vertices = geometry.getAttribute( 'position' ); - var normals = geometry.getAttribute( 'normal' ); - var uvs = geometry.getAttribute( 'uv' ); - var colors = geometry.getAttribute( 'color' ); - var indices = geometry.getIndex(); + // Binary File Generation + const headerBin = new TextEncoder().encode( header ); // 3 position values at 4 bytes + // 3 normal values at 4 bytes + // 3 color channels with 1 byte + // 2 uv values at 4 bytes - normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); + const vertexListLength = vertexCount * ( 4 * 3 + ( includeNormals ? 4 * 3 : 0 ) + ( includeColors ? 3 : 0 ) + ( includeUVs ? 4 * 2 : 0 ) ); // 1 byte shape desciptor + // 3 vertex indices at ${indexByteCount} bytes - for ( var i = 0, l = vertices.count; i < l; i ++ ) { + const faceListLength = includeIndices ? faceCount * ( indexByteCount * 3 + 1 ) : 0; + const output = new DataView( new ArrayBuffer( headerBin.length + vertexListLength + faceListLength ) ); + new Uint8Array( output.buffer ).set( headerBin, 0 ); + let vOffset = headerBin.length; + let fOffset = headerBin.length + vertexListLength; + let writtenVertices = 0; + traverseMeshes( function ( mesh, geometry ) { - vertex.x = vertices.getX( i ); - vertex.y = vertices.getY( i ); - vertex.z = vertices.getZ( i ); + const vertices = geometry.getAttribute( 'position' ); + const normals = geometry.getAttribute( 'normal' ); + const uvs = geometry.getAttribute( 'uv' ); + const colors = geometry.getAttribute( 'color' ); + const indices = geometry.getIndex(); + normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); - vertex.applyMatrix4( mesh.matrixWorld ); + for ( let i = 0, l = vertices.count; i < l; i ++ ) { + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); + vertex.applyMatrix4( mesh.matrixWorld ); // Position information - // Position information - output.setFloat32( vOffset, vertex.x, options.littleEndian ); - vOffset += 4; + output.setFloat32( vOffset, vertex.x, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, vertex.y, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, vertex.z, options.littleEndian ); + vOffset += 4; // Normal information - output.setFloat32( vOffset, vertex.y, options.littleEndian ); - vOffset += 4; + if ( includeNormals === true ) { - output.setFloat32( vOffset, vertex.z, options.littleEndian ); - vOffset += 4; + if ( normals != null ) { - // Normal information - if ( includeNormals === true ) { + vertex.x = normals.getX( i ); + vertex.y = normals.getY( i ); + vertex.z = normals.getZ( i ); + vertex.applyMatrix3( normalMatrixWorld ).normalize(); + output.setFloat32( vOffset, vertex.x, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, vertex.y, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, vertex.z, options.littleEndian ); + vOffset += 4; - if ( normals != null ) { + } else { - vertex.x = normals.getX( i ); - vertex.y = normals.getY( i ); - vertex.z = normals.getZ( i ); + output.setFloat32( vOffset, 0, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, 0, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, 0, options.littleEndian ); + vOffset += 4; - vertex.applyMatrix3( normalMatrixWorld ).normalize(); + } - output.setFloat32( vOffset, vertex.x, options.littleEndian ); - vOffset += 4; + } // UV information - output.setFloat32( vOffset, vertex.y, options.littleEndian ); - vOffset += 4; - output.setFloat32( vOffset, vertex.z, options.littleEndian ); - vOffset += 4; + if ( includeUVs === true ) { - } else { + if ( uvs != null ) { - output.setFloat32( vOffset, 0, options.littleEndian ); - vOffset += 4; + output.setFloat32( vOffset, uvs.getX( i ), options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, uvs.getY( i ), options.littleEndian ); + vOffset += 4; - output.setFloat32( vOffset, 0, options.littleEndian ); - vOffset += 4; + } else if ( includeUVs !== false ) { - output.setFloat32( vOffset, 0, options.littleEndian ); - vOffset += 4; + output.setFloat32( vOffset, 0, options.littleEndian ); + vOffset += 4; + output.setFloat32( vOffset, 0, options.littleEndian ); + vOffset += 4; - } + } - } + } // Color information - // UV information - if ( includeUVs === true ) { - if ( uvs != null ) { + if ( includeColors === true ) { - output.setFloat32( vOffset, uvs.getX( i ), options.littleEndian ); - vOffset += 4; + if ( colors != null ) { - output.setFloat32( vOffset, uvs.getY( i ), options.littleEndian ); - vOffset += 4; + output.setUint8( vOffset, Math.floor( colors.getX( i ) * 255 ) ); + vOffset += 1; + output.setUint8( vOffset, Math.floor( colors.getY( i ) * 255 ) ); + vOffset += 1; + output.setUint8( vOffset, Math.floor( colors.getZ( i ) * 255 ) ); + vOffset += 1; - } else if ( includeUVs !== false ) { + } else { - output.setFloat32( vOffset, 0, options.littleEndian ); - vOffset += 4; + output.setUint8( vOffset, 255 ); + vOffset += 1; + output.setUint8( vOffset, 255 ); + vOffset += 1; + output.setUint8( vOffset, 255 ); + vOffset += 1; - output.setFloat32( vOffset, 0, options.littleEndian ); - vOffset += 4; + } } } - // Color information - if ( includeColors === true ) { + if ( includeIndices === true ) { - if ( colors != null ) { + // Create the face list + if ( indices !== null ) { - output.setUint8( vOffset, Math.floor( colors.getX( i ) * 255 ) ); - vOffset += 1; + for ( let i = 0, l = indices.count; i < l; i += 3 ) { - output.setUint8( vOffset, Math.floor( colors.getY( i ) * 255 ) ); - vOffset += 1; + output.setUint8( fOffset, 3 ); + fOffset += 1; + output.setUint32( fOffset, indices.getX( i + 0 ) + writtenVertices, options.littleEndian ); + fOffset += indexByteCount; + output.setUint32( fOffset, indices.getX( i + 1 ) + writtenVertices, options.littleEndian ); + fOffset += indexByteCount; + output.setUint32( fOffset, indices.getX( i + 2 ) + writtenVertices, options.littleEndian ); + fOffset += indexByteCount; - output.setUint8( vOffset, Math.floor( colors.getZ( i ) * 255 ) ); - vOffset += 1; + } } else { - output.setUint8( vOffset, 255 ); - vOffset += 1; + for ( let i = 0, l = vertices.count; i < l; i += 3 ) { - output.setUint8( vOffset, 255 ); - vOffset += 1; + output.setUint8( fOffset, 3 ); + fOffset += 1; + output.setUint32( fOffset, writtenVertices + i, options.littleEndian ); + fOffset += indexByteCount; + output.setUint32( fOffset, writtenVertices + i + 1, options.littleEndian ); + fOffset += indexByteCount; + output.setUint32( fOffset, writtenVertices + i + 2, options.littleEndian ); + fOffset += indexByteCount; - output.setUint8( vOffset, 255 ); - vOffset += 1; + } } - } - - } - - if ( includeIndices === true ) { - - // Create the face list - - if ( indices !== null ) { - - for ( var i = 0, l = indices.count; i < l; i += 3 ) { - - output.setUint8( fOffset, 3 ); - fOffset += 1; + } // Save the amount of verts we've already written so we can offset + // the face index on the next mesh - output.setUint32( fOffset, indices.getX( i + 0 ) + writtenVertices, options.littleEndian ); - fOffset += indexByteCount; - output.setUint32( fOffset, indices.getX( i + 1 ) + writtenVertices, options.littleEndian ); - fOffset += indexByteCount; + writtenVertices += vertices.count; - output.setUint32( fOffset, indices.getX( i + 2 ) + writtenVertices, options.littleEndian ); - fOffset += indexByteCount; + } ); + result = output.buffer; - } - - } else { - - for ( var i = 0, l = vertices.count; i < l; i += 3 ) { + } else { - output.setUint8( fOffset, 3 ); - fOffset += 1; + // Ascii File Generation + // count the number of vertices + let writtenVertices = 0; + let vertexList = ''; + let faceList = ''; + traverseMeshes( function ( mesh, geometry ) { - output.setUint32( fOffset, writtenVertices + i, options.littleEndian ); - fOffset += indexByteCount; + const vertices = geometry.getAttribute( 'position' ); + const normals = geometry.getAttribute( 'normal' ); + const uvs = geometry.getAttribute( 'uv' ); + const colors = geometry.getAttribute( 'color' ); + const indices = geometry.getIndex(); + normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); // form each line - output.setUint32( fOffset, writtenVertices + i + 1, options.littleEndian ); - fOffset += indexByteCount; + for ( let i = 0, l = vertices.count; i < l; i ++ ) { - output.setUint32( fOffset, writtenVertices + i + 2, options.littleEndian ); - fOffset += indexByteCount; + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); + vertex.applyMatrix4( mesh.matrixWorld ); // Position information - } - - } + let line = vertex.x + ' ' + vertex.y + ' ' + vertex.z; // Normal information - } + if ( includeNormals === true ) { + if ( normals != null ) { - // Save the amount of verts we've already written so we can offset - // the face index on the next mesh - writtenVertices += vertices.count; + vertex.x = normals.getX( i ); + vertex.y = normals.getY( i ); + vertex.z = normals.getZ( i ); + vertex.applyMatrix3( normalMatrixWorld ).normalize(); + line += ' ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z; - } ); + } else { - result = output.buffer; + line += ' 0 0 0'; - } else { + } - // Ascii File Generation - // count the number of vertices - var writtenVertices = 0; - var vertexList = ''; - var faceList = ''; + } // UV information - traverseMeshes( function ( mesh, geometry ) { - var vertices = geometry.getAttribute( 'position' ); - var normals = geometry.getAttribute( 'normal' ); - var uvs = geometry.getAttribute( 'uv' ); - var colors = geometry.getAttribute( 'color' ); - var indices = geometry.getIndex(); + if ( includeUVs === true ) { - normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); + if ( uvs != null ) { - // form each line - for ( var i = 0, l = vertices.count; i < l; i ++ ) { + line += ' ' + uvs.getX( i ) + ' ' + uvs.getY( i ); - vertex.x = vertices.getX( i ); - vertex.y = vertices.getY( i ); - vertex.z = vertices.getZ( i ); + } else if ( includeUVs !== false ) { - vertex.applyMatrix4( mesh.matrixWorld ); + line += ' 0 0'; + } - // Position information - var line = - vertex.x + ' ' + - vertex.y + ' ' + - vertex.z; + } // Color information - // Normal information - if ( includeNormals === true ) { - if ( normals != null ) { + if ( includeColors === true ) { - vertex.x = normals.getX( i ); - vertex.y = normals.getY( i ); - vertex.z = normals.getZ( i ); + if ( colors != null ) { - vertex.applyMatrix3( normalMatrixWorld ).normalize(); + line += ' ' + Math.floor( colors.getX( i ) * 255 ) + ' ' + Math.floor( colors.getY( i ) * 255 ) + ' ' + Math.floor( colors.getZ( i ) * 255 ); - line += ' ' + - vertex.x + ' ' + - vertex.y + ' ' + - vertex.z; + } else { - } else { + line += ' 255 255 255'; - line += ' 0 0 0'; + } } - } + vertexList += line + '\n'; - // UV information - if ( includeUVs === true ) { + } // Create the face list - if ( uvs != null ) { - line += ' ' + - uvs.getX( i ) + ' ' + - uvs.getY( i ); + if ( includeIndices === true ) { - } else if ( includeUVs !== false ) { + if ( indices !== null ) { - line += ' 0 0'; + for ( let i = 0, l = indices.count; i < l; i += 3 ) { - } + faceList += `3 ${indices.getX( i + 0 ) + writtenVertices}`; + faceList += ` ${indices.getX( i + 1 ) + writtenVertices}`; + faceList += ` ${indices.getX( i + 2 ) + writtenVertices}\n`; - } - - // Color information - if ( includeColors === true ) { - - if ( colors != null ) { - - line += ' ' + - Math.floor( colors.getX( i ) * 255 ) + ' ' + - Math.floor( colors.getY( i ) * 255 ) + ' ' + - Math.floor( colors.getZ( i ) * 255 ); + } } else { - line += ' 255 255 255'; - - } - - } - - vertexList += line + '\n'; - - } - - // Create the face list - if ( includeIndices === true ) { - - if ( indices !== null ) { + for ( let i = 0, l = vertices.count; i < l; i += 3 ) { - for ( var i = 0, l = indices.count; i < l; i += 3 ) { + faceList += `3 ${writtenVertices + i} ${writtenVertices + i + 1} ${writtenVertices + i + 2}\n`; - faceList += `3 ${ indices.getX( i + 0 ) + writtenVertices }`; - faceList += ` ${ indices.getX( i + 1 ) + writtenVertices }`; - faceList += ` ${ indices.getX( i + 2 ) + writtenVertices }\n`; + } } - } else { - - for ( var i = 0, l = vertices.count; i < l; i += 3 ) { - - faceList += `3 ${ writtenVertices + i } ${ writtenVertices + i + 1 } ${ writtenVertices + i + 2 }\n`; - - } + faceCount += indices ? indices.count / 3 : vertices.count / 3; } - faceCount += indices ? indices.count / 3 : vertices.count / 3; + writtenVertices += vertices.count; - } + } ); + result = `${header}${vertexList}${includeIndices ? `${faceList}\n` : '\n'}`; - writtenVertices += vertices.count; - - } ); + } - result = `${ header }${vertexList}${ includeIndices ? `${faceList}\n` : '\n' }`; + if ( typeof onDone === 'function' ) requestAnimationFrame( () => onDone( result ) ); + return result; } - if ( typeof onDone === 'function' ) requestAnimationFrame( () => onDone( result ) ); - return result; - } -}; + THREE.PLYExporter = PLYExporter; + +} )(); diff --git a/examples/js/exporters/STLExporter.js b/examples/js/exporters/STLExporter.js index 429b2c6a91ebf8..a85e18d907937b 100644 --- a/examples/js/exporters/STLExporter.js +++ b/examples/js/exporters/STLExporter.js @@ -1,198 +1,190 @@ -/** +( function () { + + /** * Usage: - * var exporter = new THREE.STLExporter(); + * const exporter = new STLExporter(); * * // second argument is a list of options - * var data = exporter.parse( mesh, { binary: true } ); + * const data = exporter.parse( mesh, { binary: true } ); * */ -THREE.STLExporter = function () {}; - -THREE.STLExporter.prototype = { - - constructor: THREE.STLExporter, + class STLExporter { - parse: function ( scene, options ) { + parse( scene, options = {} ) { - if ( options === undefined ) options = {}; + const binary = options.binary !== undefined ? options.binary : false; // - var binary = options.binary !== undefined ? options.binary : false; + const objects = []; + let triangles = 0; + scene.traverse( function ( object ) { - // + if ( object.isMesh ) { - var objects = []; - var triangles = 0; + const geometry = object.geometry; - scene.traverse( function ( object ) { + if ( geometry.isBufferGeometry !== true ) { - if ( object.isMesh ) { + throw new Error( 'THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.' ); - var geometry = object.geometry; + } - if ( geometry.isBufferGeometry !== true ) { - - throw new Error( 'THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.' ); + const index = geometry.index; + const positionAttribute = geometry.getAttribute( 'position' ); + triangles += index !== null ? index.count / 3 : positionAttribute.count / 3; + objects.push( { + object3d: object, + geometry: geometry + } ); } - var index = geometry.index; - var positionAttribute = geometry.getAttribute( 'position' ); - - triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 ); - - objects.push( { - object3d: object, - geometry: geometry - } ); - - } - - } ); - - var output; - var offset = 80; // skip header + } ); + let output; + let offset = 80; // skip header - if ( binary === true ) { - - var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4; - var arrayBuffer = new ArrayBuffer( bufferLength ); - output = new DataView( arrayBuffer ); - output.setUint32( offset, triangles, true ); offset += 4; - - } else { - - output = ''; - output += 'solid exported\n'; - - } + if ( binary === true ) { - var vA = new THREE.Vector3(); - var vB = new THREE.Vector3(); - var vC = new THREE.Vector3(); - var cb = new THREE.Vector3(); - var ab = new THREE.Vector3(); - var normal = new THREE.Vector3(); + const bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4; + const arrayBuffer = new ArrayBuffer( bufferLength ); + output = new DataView( arrayBuffer ); + output.setUint32( offset, triangles, true ); + offset += 4; - for ( var i = 0, il = objects.length; i < il; i ++ ) { + } else { - var object = objects[ i ].object3d; - var geometry = objects[ i ].geometry; + output = ''; + output += 'solid exported\n'; - var index = geometry.index; - var positionAttribute = geometry.getAttribute( 'position' ); + } - if ( index !== null ) { + const vA = new THREE.Vector3(); + const vB = new THREE.Vector3(); + const vC = new THREE.Vector3(); + const cb = new THREE.Vector3(); + const ab = new THREE.Vector3(); + const normal = new THREE.Vector3(); - // indexed geometry + for ( let i = 0, il = objects.length; i < il; i ++ ) { - for ( var j = 0; j < index.count; j += 3 ) { + const object = objects[ i ].object3d; + const geometry = objects[ i ].geometry; + const index = geometry.index; + const positionAttribute = geometry.getAttribute( 'position' ); - var a = index.getX( j + 0 ); - var b = index.getX( j + 1 ); - var c = index.getX( j + 2 ); + if ( index !== null ) { - writeFace( a, b, c, positionAttribute, object ); + // indexed geometry + for ( let j = 0; j < index.count; j += 3 ) { - } + const a = index.getX( j + 0 ); + const b = index.getX( j + 1 ); + const c = index.getX( j + 2 ); + writeFace( a, b, c, positionAttribute, object ); - } else { + } - // non-indexed geometry + } else { - for ( var j = 0; j < positionAttribute.count; j += 3 ) { + // non-indexed geometry + for ( let j = 0; j < positionAttribute.count; j += 3 ) { - var a = j + 0; - var b = j + 1; - var c = j + 2; + const a = j + 0; + const b = j + 1; + const c = j + 2; + writeFace( a, b, c, positionAttribute, object ); - writeFace( a, b, c, positionAttribute, object ); + } } } - } - - if ( binary === false ) { + if ( binary === false ) { - output += 'endsolid exported\n'; + output += 'endsolid exported\n'; - } - - return output; + } - function writeFace( a, b, c, positionAttribute, object ) { + return output; - vA.fromBufferAttribute( positionAttribute, a ); - vB.fromBufferAttribute( positionAttribute, b ); - vC.fromBufferAttribute( positionAttribute, c ); + function writeFace( a, b, c, positionAttribute, object ) { - if ( object.isSkinnedMesh === true ) { + vA.fromBufferAttribute( positionAttribute, a ); + vB.fromBufferAttribute( positionAttribute, b ); + vC.fromBufferAttribute( positionAttribute, c ); - object.boneTransform( a, vA ); - object.boneTransform( b, vB ); - object.boneTransform( c, vC ); + if ( object.isSkinnedMesh === true ) { - } + object.boneTransform( a, vA ); + object.boneTransform( b, vB ); + object.boneTransform( c, vC ); - vA.applyMatrix4( object.matrixWorld ); - vB.applyMatrix4( object.matrixWorld ); - vC.applyMatrix4( object.matrixWorld ); + } - writeNormal( vA, vB, vC ); + vA.applyMatrix4( object.matrixWorld ); + vB.applyMatrix4( object.matrixWorld ); + vC.applyMatrix4( object.matrixWorld ); + writeNormal( vA, vB, vC ); + writeVertex( vA ); + writeVertex( vB ); + writeVertex( vC ); - writeVertex( vA ); - writeVertex( vB ); - writeVertex( vC ); + if ( binary === true ) { - if ( binary === true ) { + output.setUint16( offset, 0, true ); + offset += 2; - output.setUint16( offset, 0, true ); offset += 2; + } else { - } else { + output += '\t\tendloop\n'; + output += '\tendfacet\n'; - output += '\t\tendloop\n'; - output += '\tendfacet\n'; + } } - } + function writeNormal( vA, vB, vC ) { - function writeNormal( vA, vB, vC ) { + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ).normalize(); + normal.copy( cb ).normalize(); - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ).normalize(); + if ( binary === true ) { - normal.copy( cb ).normalize(); + output.setFloat32( offset, normal.x, true ); + offset += 4; + output.setFloat32( offset, normal.y, true ); + offset += 4; + output.setFloat32( offset, normal.z, true ); + offset += 4; - if ( binary === true ) { + } else { - output.setFloat32( offset, normal.x, true ); offset += 4; - output.setFloat32( offset, normal.y, true ); offset += 4; - output.setFloat32( offset, normal.z, true ); offset += 4; + output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; + output += '\t\touter loop\n'; - } else { - - output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; - output += '\t\touter loop\n'; + } } - } + function writeVertex( vertex ) { - function writeVertex( vertex ) { + if ( binary === true ) { - if ( binary === true ) { + output.setFloat32( offset, vertex.x, true ); + offset += 4; + output.setFloat32( offset, vertex.y, true ); + offset += 4; + output.setFloat32( offset, vertex.z, true ); + offset += 4; - output.setFloat32( offset, vertex.x, true ); offset += 4; - output.setFloat32( offset, vertex.y, true ); offset += 4; - output.setFloat32( offset, vertex.z, true ); offset += 4; + } else { - } else { + output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; - output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + } } @@ -200,4 +192,6 @@ THREE.STLExporter.prototype = { } -}; + THREE.STLExporter = STLExporter; + +} )(); diff --git a/examples/js/exporters/USDZExporter.js b/examples/js/exporters/USDZExporter.js new file mode 100644 index 00000000000000..1042e07ca235de --- /dev/null +++ b/examples/js/exporters/USDZExporter.js @@ -0,0 +1,386 @@ +( function () { + + class USDZExporter { + + async parse( scene ) { + + let output = buildHeader(); + const materials = {}; + const textures = {}; + scene.traverse( object => { + + if ( object.isMesh ) { + + const geometry = object.geometry; + const material = object.material; + materials[ material.uuid ] = material; + if ( material.map !== null ) textures[ material.map.uuid ] = material.map; + if ( material.normalMap !== null ) textures[ material.normalMap.uuid ] = material.normalMap; + if ( material.aoMap !== null ) textures[ material.aoMap.uuid ] = material.aoMap; + if ( material.roughnessMap !== null ) textures[ material.roughnessMap.uuid ] = material.roughnessMap; + if ( material.metalnessMap !== null ) textures[ material.metalnessMap.uuid ] = material.metalnessMap; + if ( material.emissiveMap !== null ) textures[ material.emissiveMap.uuid ] = material.emissiveMap; + output += buildXform( object, buildMesh( geometry, material ) ); + + } + + } ); + output += buildMaterials( materials ); + output += buildTextures( textures ); + const files = { + 'model.usda': fflate.strToU8( output ) + }; + + for ( const uuid in textures ) { + + const texture = textures[ uuid ]; + files[ 'textures/Texture_' + texture.id + '.jpg' ] = await imgToU8( texture.image ); + + } // 64 byte alignment + // https://github.com/101arrowz/fflate/issues/39#issuecomment-777263109 + + + let offset = 0; + + for ( const filename in files ) { + + const file = files[ filename ]; + const headerSize = 34 + filename.length; + offset += headerSize; + const offsetMod64 = offset & 63; + + if ( offsetMod64 !== 4 ) { + + const padLength = 64 - offsetMod64; + const padding = new Uint8Array( padLength ); + files[ filename ] = [ file, { + extra: { + 12345: padding + } + } ]; + + } + + offset = file.length; + + } + + return fflate.zipSync( files, { + level: 0 + } ); + + } + + } + + async function imgToU8( image ) { + + if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement || typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas || typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) { + + const scale = 1024 / Math.max( image.width, image.height ); + const canvas = document.createElement( 'canvas' ); + canvas.width = image.width * Math.min( 1, scale ); + canvas.height = image.height * Math.min( 1, scale ); + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, canvas.width, canvas.height ); + const blob = await new Promise( resolve => canvas.toBlob( resolve, 'image/jpeg', 1 ) ); + return new Uint8Array( await blob.arrayBuffer() ); + + } + + } // + + + const PRECISION = 7; + + function buildHeader() { + + return `#usda 1.0 +( + customLayerData = { + string creator = "Three.js USDZExporter" + } + metersPerUnit = 1 + upAxis = "Y" +) + +`; + + } // Xform + + + function buildXform( object, define ) { + + const name = 'Object_' + object.id; + const transform = buildMatrix( object.matrixWorld ); + return `def Xform "${name}" +{ + matrix4d xformOp:transform = ${transform} + uniform token[] xformOpOrder = ["xformOp:transform"] + + ${define} +} + +`; + + } + + function buildMatrix( matrix ) { + + const array = matrix.elements; + return `( ${buildMatrixRow( array, 0 )}, ${buildMatrixRow( array, 4 )}, ${buildMatrixRow( array, 8 )}, ${buildMatrixRow( array, 12 )} )`; + + } + + function buildMatrixRow( array, offset ) { + + return `(${array[ offset + 0 ]}, ${array[ offset + 1 ]}, ${array[ offset + 2 ]}, ${array[ offset + 3 ]})`; + + } // Mesh + + + function buildMesh( geometry, material ) { + + const name = 'Geometry_' + geometry.id; + const attributes = geometry.attributes; + const count = attributes.position.count; + + if ( 'uv2' in attributes ) { + + console.warn( 'THREE.USDZExporter: uv2 not supported yet.' ); + + } + + return `def Mesh "${name}" + { + int[] faceVertexCounts = [${buildMeshVertexCount( geometry )}] + int[] faceVertexIndices = [${buildMeshVertexIndices( geometry )}] + rel material:binding = + normal3f[] normals = [${buildVector3Array( attributes.normal, count )}] ( + interpolation = "vertex" + ) + point3f[] points = [${buildVector3Array( attributes.position, count )}] + float2[] primvars:st = [${buildVector2Array( attributes.uv, count )}] ( + interpolation = "vertex" + ) + uniform token subdivisionScheme = "none" + } +`; + + } + + function buildMeshVertexCount( geometry ) { + + const count = geometry.index !== null ? geometry.index.array.length : geometry.attributes.position.count; + return Array( count / 3 ).fill( 3 ).join( ', ' ); + + } + + function buildMeshVertexIndices( geometry ) { + + if ( geometry.index !== null ) { + + return geometry.index.array.join( ', ' ); + + } + + const array = []; + const length = geometry.attributes.position.count; + + for ( let i = 0; i < length; i ++ ) { + + array.push( i ); + + } + + return array.join( ', ' ); + + } + + function buildVector3Array( attribute, count ) { + + if ( attribute === undefined ) { + + console.warn( 'USDZExporter: Normals missing.' ); + return Array( count ).fill( '(0, 0, 0)' ).join( ', ' ); + + } + + const array = []; + const data = attribute.array; + + for ( let i = 0; i < data.length; i += 3 ) { + + array.push( `(${data[ i + 0 ].toPrecision( PRECISION )}, ${data[ i + 1 ].toPrecision( PRECISION )}, ${data[ i + 2 ].toPrecision( PRECISION )})` ); + + } + + return array.join( ', ' ); + + } + + function buildVector2Array( attribute, count ) { + + if ( attribute === undefined ) { + + console.warn( 'USDZExporter: UVs missing.' ); + return Array( count ).fill( '(0, 0)' ).join( ', ' ); + + } + + const array = []; + const data = attribute.array; + + for ( let i = 0; i < data.length; i += 2 ) { + + array.push( `(${data[ i + 0 ].toPrecision( PRECISION )}, ${1 - data[ i + 1 ].toPrecision( PRECISION )})` ); + + } + + return array.join( ', ' ); + + } // Materials + + + function buildMaterials( materials ) { + + const array = []; + + for ( const uuid in materials ) { + + const material = materials[ uuid ]; + array.push( buildMaterial( material ) ); + + } + + return `def "Materials" +{ +${array.join( '' )} +} + +`; + + } + + function buildMaterial( material ) { + + // https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html + const pad = ' '; + const parameters = []; + + if ( material.map !== null ) { + + parameters.push( `${pad}color3f inputs:diffuseColor.connect = ` ); + + } else { + + parameters.push( `${pad}color3f inputs:diffuseColor = ${buildColor( material.color )}` ); + + } + + if ( material.emissiveMap !== null ) { + + parameters.push( `${pad}color3f inputs:emissiveColor.connect = ` ); + + } else if ( material.emissive.getHex() > 0 ) { + + parameters.push( `${pad}color3f inputs:emissiveColor = ${buildColor( material.emissive )}` ); + + } + + if ( material.normalMap !== null ) { + + parameters.push( `${pad}normal3f inputs:normal.connect = ` ); + + } + + if ( material.aoMap !== null ) { + + parameters.push( `${pad}float inputs:occlusion.connect = ` ); + + } + + if ( material.roughnessMap !== null ) { + + parameters.push( `${pad}float inputs:roughness.connect = ` ); + + } else { + + parameters.push( `${pad}float inputs:roughness = ${material.roughness}` ); + + } + + if ( material.metalnessMap !== null ) { + + parameters.push( `${pad}float inputs:metallic.connect = ` ); + + } else { + + parameters.push( `${pad}float inputs:metallic = ${material.metalness}` ); + + } + + return ` + def Material "Material_${material.id}" + { + token outputs:surface.connect = + + def Shader "PreviewSurface" + { + uniform token info:id = "UsdPreviewSurface" +${parameters.join( '\n' )} + int inputs:useSpecularWorkflow = 0 + token outputs:surface + } + } +`; + + } + + function buildTextures( textures ) { + + const array = []; + + for ( const uuid in textures ) { + + const texture = textures[ uuid ]; + array.push( buildTexture( texture ) ); + + } + + return `def "Textures" +{ +${array.join( '' )} +} + +`; + + } + + function buildTexture( texture ) { + + return ` + def Shader "Texture_${texture.id}" + { + uniform token info:id = "UsdUVTexture" + asset inputs:file = @textures/Texture_${texture.id}.jpg@ + token inputs:wrapS = "repeat" + token inputs:wrapT = "repeat" + float outputs:r + float outputs:g + float outputs:b + float3 outputs:rgb + } +`; + + } + + function buildColor( color ) { + + return `(${color.r}, ${color.g}, ${color.b})`; + + } + + THREE.USDZExporter = USDZExporter; + +} )(); diff --git a/examples/js/geometries/BoxLineGeometry.js b/examples/js/geometries/BoxLineGeometry.js index 70f07691ae7f68..97a1ec33407568 100644 --- a/examples/js/geometries/BoxLineGeometry.js +++ b/examples/js/geometries/BoxLineGeometry.js @@ -1,63 +1,60 @@ -THREE.BoxLineGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) { +( function () { - THREE.BufferGeometry.call( this ); + class BoxLineGeometry extends THREE.BufferGeometry { - width = width || 1; - height = height || 1; - depth = depth || 1; + constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; + super(); + widthSegments = Math.floor( widthSegments ); + heightSegments = Math.floor( heightSegments ); + depthSegments = Math.floor( depthSegments ); + const widthHalf = width / 2; + const heightHalf = height / 2; + const depthHalf = depth / 2; + const segmentWidth = width / widthSegments; + const segmentHeight = height / heightSegments; + const segmentDepth = depth / depthSegments; + const vertices = []; + let x = - widthHalf; + let y = - heightHalf; + let z = - depthHalf; - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; + for ( let i = 0; i <= widthSegments; i ++ ) { - var segmentWidth = width / widthSegments; - var segmentHeight = height / heightSegments; - var segmentDepth = depth / depthSegments; + vertices.push( x, - heightHalf, - depthHalf, x, heightHalf, - depthHalf ); + vertices.push( x, heightHalf, - depthHalf, x, heightHalf, depthHalf ); + vertices.push( x, heightHalf, depthHalf, x, - heightHalf, depthHalf ); + vertices.push( x, - heightHalf, depthHalf, x, - heightHalf, - depthHalf ); + x += segmentWidth; - var vertices = []; + } - var x = - widthHalf, y = - heightHalf, z = - depthHalf; + for ( let i = 0; i <= heightSegments; i ++ ) { - for ( var i = 0; i <= widthSegments; i ++ ) { + vertices.push( - widthHalf, y, - depthHalf, widthHalf, y, - depthHalf ); + vertices.push( widthHalf, y, - depthHalf, widthHalf, y, depthHalf ); + vertices.push( widthHalf, y, depthHalf, - widthHalf, y, depthHalf ); + vertices.push( - widthHalf, y, depthHalf, - widthHalf, y, - depthHalf ); + y += segmentHeight; - vertices.push( x, - heightHalf, - depthHalf, x, heightHalf, - depthHalf ); - vertices.push( x, heightHalf, - depthHalf, x, heightHalf, depthHalf ); - vertices.push( x, heightHalf, depthHalf, x, - heightHalf, depthHalf ); - vertices.push( x, - heightHalf, depthHalf, x, - heightHalf, - depthHalf ); + } - x += segmentWidth; + for ( let i = 0; i <= depthSegments; i ++ ) { - } + vertices.push( - widthHalf, - heightHalf, z, - widthHalf, heightHalf, z ); + vertices.push( - widthHalf, heightHalf, z, widthHalf, heightHalf, z ); + vertices.push( widthHalf, heightHalf, z, widthHalf, - heightHalf, z ); + vertices.push( widthHalf, - heightHalf, z, - widthHalf, - heightHalf, z ); + z += segmentDepth; - for ( var i = 0; i <= heightSegments; i ++ ) { + } - vertices.push( - widthHalf, y, - depthHalf, widthHalf, y, - depthHalf ); - vertices.push( widthHalf, y, - depthHalf, widthHalf, y, depthHalf ); - vertices.push( widthHalf, y, depthHalf, - widthHalf, y, depthHalf ); - vertices.push( - widthHalf, y, depthHalf, - widthHalf, y, - depthHalf ); + this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); - y += segmentHeight; + } } - for ( var i = 0; i <= depthSegments; i ++ ) { - - vertices.push( - widthHalf, - heightHalf, z, - widthHalf, heightHalf, z ); - vertices.push( - widthHalf, heightHalf, z, widthHalf, heightHalf, z ); - vertices.push( widthHalf, heightHalf, z, widthHalf, - heightHalf, z ); - vertices.push( widthHalf, - heightHalf, z, - widthHalf, - heightHalf, z ); - - z += segmentDepth; - - } - - this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); - -}; + THREE.BoxLineGeometry = BoxLineGeometry; -THREE.BoxLineGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.BoxLineGeometry.prototype.constructor = THREE.BoxLineGeometry; +} )(); diff --git a/examples/js/geometries/ConvexGeometry.js b/examples/js/geometries/ConvexGeometry.js index 81de95ef4b8a75..2b3ec0b7a4529a 100644 --- a/examples/js/geometries/ConvexGeometry.js +++ b/examples/js/geometries/ConvexGeometry.js @@ -1,52 +1,48 @@ -// ConvexGeometry +( function () { -THREE.ConvexGeometry = function ( points ) { + class ConvexGeometry extends THREE.BufferGeometry { - THREE.BufferGeometry.call( this ); + constructor( points ) { - // buffers + super(); // buffers - var vertices = []; - var normals = []; + const vertices = []; + const normals = []; - if ( THREE.ConvexHull === undefined ) { + if ( THREE.ConvexHull === undefined ) { - console.error( 'THREE.ConvexBufferGeometry: ConvexBufferGeometry relies on THREE.ConvexHull' ); + console.error( 'THREE.ConvexBufferGeometry: ConvexBufferGeometry relies on THREE.ConvexHull' ); - } + } - var convexHull = new THREE.ConvexHull().setFromPoints( points ); + const convexHull = new THREE.ConvexHull().setFromPoints( points ); // generate vertices and normals - // generate vertices and normals + const faces = convexHull.faces; - var faces = convexHull.faces; + for ( let i = 0; i < faces.length; i ++ ) { - for ( var i = 0; i < faces.length; i ++ ) { + const face = faces[ i ]; + let edge = face.edge; // we move along a doubly-connected edge list to access all face points (see HalfEdge docs) - var face = faces[ i ]; - var edge = face.edge; + do { - // we move along a doubly-connected edge list to access all face points (see HalfEdge docs) + const point = edge.head().point; + vertices.push( point.x, point.y, point.z ); + normals.push( face.normal.x, face.normal.y, face.normal.z ); + edge = edge.next; - do { + } while ( edge !== face.edge ); - var point = edge.head().point; + } // build geometry - vertices.push( point.x, point.y, point.z ); - normals.push( face.normal.x, face.normal.y, face.normal.z ); - edge = edge.next; + this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); - } while ( edge !== face.edge ); + } } - // build geometry - - this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); - this.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); - -}; + THREE.ConvexGeometry = ConvexGeometry; -THREE.ConvexGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.ConvexGeometry.prototype.constructor = THREE.ConvexGeometry; +} )(); diff --git a/examples/js/geometries/DecalGeometry.js b/examples/js/geometries/DecalGeometry.js index 3fc692d498d92a..0fa6dbdc140454 100644 --- a/examples/js/geometries/DecalGeometry.js +++ b/examples/js/geometries/DecalGeometry.js @@ -1,4 +1,6 @@ -/** +( function () { + + /** * You can use this geometry to create a decal mesh, that serves different kinds of purposes. * e.g. adding unique details to models, performing dynamic visual environmental changes or covering seams. * @@ -13,336 +15,284 @@ * */ -THREE.DecalGeometry = function ( mesh, position, orientation, size ) { - - THREE.BufferGeometry.call( this ); - - // buffers - - var vertices = []; - var normals = []; - var uvs = []; + class DecalGeometry extends THREE.BufferGeometry { - // helpers + constructor( mesh, position, orientation, size ) { - var plane = new THREE.Vector3(); + super(); // buffers - // this matrix represents the transformation of the decal projector + const vertices = []; + const normals = []; + const uvs = []; // helpers - var projectorMatrix = new THREE.Matrix4(); - projectorMatrix.makeRotationFromEuler( orientation ); - projectorMatrix.setPosition( position ); + const plane = new THREE.Vector3(); // this matrix represents the transformation of the decal projector - var projectorMatrixInverse = new THREE.Matrix4(); - projectorMatrixInverse.copy( projectorMatrix ).invert(); + const projectorMatrix = new THREE.Matrix4(); + projectorMatrix.makeRotationFromEuler( orientation ); + projectorMatrix.setPosition( position ); + const projectorMatrixInverse = new THREE.Matrix4(); + projectorMatrixInverse.copy( projectorMatrix ).invert(); // generate buffers - // generate buffers + generate(); // build geometry - generate(); + this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); - // build geometry + function generate() { - this.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); - this.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) ); - this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); + let decalVertices = []; + const vertex = new THREE.Vector3(); + const normal = new THREE.Vector3(); // handle different geometry types - function generate() { + if ( mesh.geometry.isGeometry === true ) { - var i; + console.error( 'THREE.DecalGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' ); + return; - var decalVertices = []; - - var vertex = new THREE.Vector3(); - var normal = new THREE.Vector3(); + } - // handle different geometry types + const geometry = mesh.geometry; + const positionAttribute = geometry.attributes.position; + const normalAttribute = geometry.attributes.normal; // first, create an array of 'DecalVertex' objects + // three consecutive 'DecalVertex' objects represent a single face + // + // this data structure will be later used to perform the clipping - if ( mesh.geometry.isGeometry === true ) { + if ( geometry.index !== null ) { - console.error( 'THREE.DecalGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' ); - return; + // indexed THREE.BufferGeometry + const index = geometry.index; - } + for ( let i = 0; i < index.count; i ++ ) { - var geometry = mesh.geometry; + vertex.fromBufferAttribute( positionAttribute, index.getX( i ) ); + normal.fromBufferAttribute( normalAttribute, index.getX( i ) ); + pushDecalVertex( decalVertices, vertex, normal ); - var positionAttribute = geometry.attributes.position; - var normalAttribute = geometry.attributes.normal; + } - // first, create an array of 'DecalVertex' objects - // three consecutive 'DecalVertex' objects represent a single face - // - // this data structure will be later used to perform the clipping + } else { - if ( geometry.index !== null ) { + // non-indexed THREE.BufferGeometry + for ( let i = 0; i < positionAttribute.count; i ++ ) { - // indexed BufferGeometry + vertex.fromBufferAttribute( positionAttribute, i ); + normal.fromBufferAttribute( normalAttribute, i ); + pushDecalVertex( decalVertices, vertex, normal ); - var index = geometry.index; + } - for ( i = 0; i < index.count; i ++ ) { + } // second, clip the geometry so that it doesn't extend out from the projector - vertex.fromBufferAttribute( positionAttribute, index.getX( i ) ); - normal.fromBufferAttribute( normalAttribute, index.getX( i ) ); - pushDecalVertex( decalVertices, vertex, normal ); + decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) ); + decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) ); + decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) ); + decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) ); + decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) ); + decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) ); // third, generate final vertices, normals and uvs - } + for ( let i = 0; i < decalVertices.length; i ++ ) { - } else { + const decalVertex = decalVertices[ i ]; // create texture coordinates (we are still in projector space) - // non-indexed BufferGeometry + uvs.push( 0.5 + decalVertex.position.x / size.x, 0.5 + decalVertex.position.y / size.y ); // transform the vertex back to world space - for ( i = 0; i < positionAttribute.count; i ++ ) { + decalVertex.position.applyMatrix4( projectorMatrix ); // now create vertex and normal buffer data - vertex.fromBufferAttribute( positionAttribute, i ); - normal.fromBufferAttribute( normalAttribute, i ); + vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z ); + normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z ); - pushDecalVertex( decalVertices, vertex, normal ); + } } - } - - // second, clip the geometry so that it doesn't extend out from the projector - - decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) ); - decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) ); - decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) ); - decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) ); - decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) ); - decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) ); - - // third, generate final vertices, normals and uvs + function pushDecalVertex( decalVertices, vertex, normal ) { - for ( i = 0; i < decalVertices.length; i ++ ) { + // transform the vertex to world space, then to projector space + vertex.applyMatrix4( mesh.matrixWorld ); + vertex.applyMatrix4( projectorMatrixInverse ); + normal.transformDirection( mesh.matrixWorld ); + decalVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) ); - var decalVertex = decalVertices[ i ]; - - // create texture coordinates (we are still in projector space) - - uvs.push( - 0.5 + ( decalVertex.position.x / size.x ), - 0.5 + ( decalVertex.position.y / size.y ) - ); + } - // transform the vertex back to world space + function clipGeometry( inVertices, plane ) { - decalVertex.position.applyMatrix4( projectorMatrix ); + const outVertices = []; + const s = 0.5 * Math.abs( size.dot( plane ) ); // a single iteration clips one face, + // which consists of three consecutive 'DecalVertex' objects - // now create vertex and normal buffer data + for ( let i = 0; i < inVertices.length; i += 3 ) { - vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z ); - normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z ); + let total = 0; + let nV1; + let nV2; + let nV3; + let nV4; + const d1 = inVertices[ i + 0 ].position.dot( plane ) - s; + const d2 = inVertices[ i + 1 ].position.dot( plane ) - s; + const d3 = inVertices[ i + 2 ].position.dot( plane ) - s; + const v1Out = d1 > 0; + const v2Out = d2 > 0; + const v3Out = d3 > 0; // calculate, how many vertices of the face lie outside of the clipping plane - } + total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 ); - } + switch ( total ) { - function pushDecalVertex( decalVertices, vertex, normal ) { + case 0: + { - // transform the vertex to world space, then to projector space + // the entire face lies inside of the plane, no clipping needed + outVertices.push( inVertices[ i ] ); + outVertices.push( inVertices[ i + 1 ] ); + outVertices.push( inVertices[ i + 2 ] ); + break; - vertex.applyMatrix4( mesh.matrixWorld ); - vertex.applyMatrix4( projectorMatrixInverse ); + } - normal.transformDirection( mesh.matrixWorld ); + case 1: + { - decalVertices.push( new THREE.DecalVertex( vertex.clone(), normal.clone() ) ); + // one vertex lies outside of the plane, perform clipping + if ( v1Out ) { - } + nV1 = inVertices[ i + 1 ]; + nV2 = inVertices[ i + 2 ]; + nV3 = clip( inVertices[ i ], nV1, plane, s ); + nV4 = clip( inVertices[ i ], nV2, plane, s ); - function clipGeometry( inVertices, plane ) { + } - var outVertices = []; + if ( v2Out ) { - var s = 0.5 * Math.abs( size.dot( plane ) ); + nV1 = inVertices[ i ]; + nV2 = inVertices[ i + 2 ]; + nV3 = clip( inVertices[ i + 1 ], nV1, plane, s ); + nV4 = clip( inVertices[ i + 1 ], nV2, plane, s ); + outVertices.push( nV3 ); + outVertices.push( nV2.clone() ); + outVertices.push( nV1.clone() ); + outVertices.push( nV2.clone() ); + outVertices.push( nV3.clone() ); + outVertices.push( nV4 ); + break; - // a single iteration clips one face, - // which consists of three consecutive 'DecalVertex' objects + } - for ( var i = 0; i < inVertices.length; i += 3 ) { + if ( v3Out ) { - var v1Out, v2Out, v3Out, total = 0; - var nV1, nV2, nV3, nV4; + nV1 = inVertices[ i ]; + nV2 = inVertices[ i + 1 ]; + nV3 = clip( inVertices[ i + 2 ], nV1, plane, s ); + nV4 = clip( inVertices[ i + 2 ], nV2, plane, s ); - var d1 = inVertices[ i + 0 ].position.dot( plane ) - s; - var d2 = inVertices[ i + 1 ].position.dot( plane ) - s; - var d3 = inVertices[ i + 2 ].position.dot( plane ) - s; + } - v1Out = d1 > 0; - v2Out = d2 > 0; - v3Out = d3 > 0; + outVertices.push( nV1.clone() ); + outVertices.push( nV2.clone() ); + outVertices.push( nV3 ); + outVertices.push( nV4 ); + outVertices.push( nV3.clone() ); + outVertices.push( nV2.clone() ); + break; - // calculate, how many vertices of the face lie outside of the clipping plane + } - total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 ); + case 2: + { - switch ( total ) { + // two vertices lies outside of the plane, perform clipping + if ( ! v1Out ) { - case 0: { + nV1 = inVertices[ i ].clone(); + nV2 = clip( nV1, inVertices[ i + 1 ], plane, s ); + nV3 = clip( nV1, inVertices[ i + 2 ], plane, s ); + outVertices.push( nV1 ); + outVertices.push( nV2 ); + outVertices.push( nV3 ); - // the entire face lies inside of the plane, no clipping needed + } - outVertices.push( inVertices[ i ] ); - outVertices.push( inVertices[ i + 1 ] ); - outVertices.push( inVertices[ i + 2 ] ); - break; + if ( ! v2Out ) { - } + nV1 = inVertices[ i + 1 ].clone(); + nV2 = clip( nV1, inVertices[ i + 2 ], plane, s ); + nV3 = clip( nV1, inVertices[ i ], plane, s ); + outVertices.push( nV1 ); + outVertices.push( nV2 ); + outVertices.push( nV3 ); - case 1: { + } - // one vertex lies outside of the plane, perform clipping + if ( ! v3Out ) { - if ( v1Out ) { + nV1 = inVertices[ i + 2 ].clone(); + nV2 = clip( nV1, inVertices[ i ], plane, s ); + nV3 = clip( nV1, inVertices[ i + 1 ], plane, s ); + outVertices.push( nV1 ); + outVertices.push( nV2 ); + outVertices.push( nV3 ); - nV1 = inVertices[ i + 1 ]; - nV2 = inVertices[ i + 2 ]; - nV3 = clip( inVertices[ i ], nV1, plane, s ); - nV4 = clip( inVertices[ i ], nV2, plane, s ); + } - } + break; - if ( v2Out ) { + } - nV1 = inVertices[ i ]; - nV2 = inVertices[ i + 2 ]; - nV3 = clip( inVertices[ i + 1 ], nV1, plane, s ); - nV4 = clip( inVertices[ i + 1 ], nV2, plane, s ); + case 3: + { - outVertices.push( nV3 ); - outVertices.push( nV2.clone() ); - outVertices.push( nV1.clone() ); + // the entire face lies outside of the plane, so let's discard the corresponding vertices + break; - outVertices.push( nV2.clone() ); - outVertices.push( nV3.clone() ); - outVertices.push( nV4 ); - break; + } } - if ( v3Out ) { - - nV1 = inVertices[ i ]; - nV2 = inVertices[ i + 1 ]; - nV3 = clip( inVertices[ i + 2 ], nV1, plane, s ); - nV4 = clip( inVertices[ i + 2 ], nV2, plane, s ); - - } - - outVertices.push( nV1.clone() ); - outVertices.push( nV2.clone() ); - outVertices.push( nV3 ); - - outVertices.push( nV4 ); - outVertices.push( nV3.clone() ); - outVertices.push( nV2.clone() ); - - break; - } - case 2: { + return outVertices; - // two vertices lies outside of the plane, perform clipping - - if ( ! v1Out ) { - - nV1 = inVertices[ i ].clone(); - nV2 = clip( nV1, inVertices[ i + 1 ], plane, s ); - nV3 = clip( nV1, inVertices[ i + 2 ], plane, s ); - outVertices.push( nV1 ); - outVertices.push( nV2 ); - outVertices.push( nV3 ); - - } - - if ( ! v2Out ) { - - nV1 = inVertices[ i + 1 ].clone(); - nV2 = clip( nV1, inVertices[ i + 2 ], plane, s ); - nV3 = clip( nV1, inVertices[ i ], plane, s ); - outVertices.push( nV1 ); - outVertices.push( nV2 ); - outVertices.push( nV3 ); - - } - - if ( ! v3Out ) { - - nV1 = inVertices[ i + 2 ].clone(); - nV2 = clip( nV1, inVertices[ i ], plane, s ); - nV3 = clip( nV1, inVertices[ i + 1 ], plane, s ); - outVertices.push( nV1 ); - outVertices.push( nV2 ); - outVertices.push( nV3 ); - - } - - break; - - } - - case 3: { + } - // the entire face lies outside of the plane, so let's discard the corresponding vertices + function clip( v0, v1, p, s ) { - break; + const d0 = v0.position.dot( p ) - s; + const d1 = v1.position.dot( p ) - s; + const s0 = d0 / ( d0 - d1 ); + const v = new DecalVertex( new THREE.Vector3( v0.position.x + s0 * ( v1.position.x - v0.position.x ), v0.position.y + s0 * ( v1.position.y - v0.position.y ), v0.position.z + s0 * ( v1.position.z - v0.position.z ) ), new THREE.Vector3( v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ), v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ), v0.normal.z + s0 * ( v1.normal.z - v0.normal.z ) ) ); // need to clip more values (texture coordinates)? do it this way: + // intersectpoint.value = a.value + s * ( b.value - a.value ); - } + return v; } } - return outVertices; - - } - - function clip( v0, v1, p, s ) { - - var d0 = v0.position.dot( p ) - s; - var d1 = v1.position.dot( p ) - s; + } // helper - var s0 = d0 / ( d0 - d1 ); - var v = new THREE.DecalVertex( - new THREE.Vector3( - v0.position.x + s0 * ( v1.position.x - v0.position.x ), - v0.position.y + s0 * ( v1.position.y - v0.position.y ), - v0.position.z + s0 * ( v1.position.z - v0.position.z ) - ), - new THREE.Vector3( - v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ), - v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ), - v0.normal.z + s0 * ( v1.normal.z - v0.normal.z ) - ) - ); + class DecalVertex { - // need to clip more values (texture coordinates)? do it this way: - // intersectpoint.value = a.value + s * ( b.value - a.value ); + constructor( position, normal ) { - return v; + this.position = position; + this.normal = normal; - } - -}; - -THREE.DecalGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.DecalGeometry.prototype.constructor = THREE.DecalGeometry; - -// helper + } -THREE.DecalVertex = function ( position, normal ) { + clone() { - this.position = position; - this.normal = normal; + return new this.constructor( this.position.clone(), this.normal.clone() ); -}; + } -THREE.DecalVertex.prototype.clone = function () { + } - return new this.constructor( this.position.clone(), this.normal.clone() ); + THREE.DecalGeometry = DecalGeometry; + THREE.DecalVertex = DecalVertex; -}; +} )(); diff --git a/examples/js/geometries/LightningStrike.js b/examples/js/geometries/LightningStrike.js index a932cdd9025adf..aac0272b753ccd 100644 --- a/examples/js/geometries/LightningStrike.js +++ b/examples/js/geometries/LightningStrike.js @@ -1,10 +1,12 @@ -/** +( function () { + + /** * @fileoverview LightningStrike object for creating lightning strikes and voltaic arcs. * * * Usage * - * var myRay = new THREE.LightningStrike( paramsObject ); + * var myRay = new LightningStrike( paramsObject ); * var myRayMesh = new THREE.Mesh( myRay, myMaterial ); * scene.add( myRayMesh ); * ... @@ -84,7 +86,7 @@ * * @param {boolean} generateUVs If true, the ray geometry will have uv coordinates generated. u runs along the ray, and v across its perimeter. Default: false. * - * @param {Object} randomGenerator Set here your random number generator which will seed the SimplexNoise and other decisions during ray tree creation. + * @param {Object} randomGenerator Set here your random number generator which will seed the THREE.SimplexNoise and other decisions during ray tree creation. * It can be used to generate repeatable rays. For that, set also the noiseSeed parameter, and each ray created with that generator and seed pair will be identical in time. * The randomGenerator parameter should be an object with a random() function similar to Math.random, but seedable. * It must have also a getSeed() method, which returns the current seed, and a setSeed( seed ) method, which accepts as seed a fractional number from 0 to 1, as well as any other number. @@ -99,908 +101,774 @@ * */ -THREE.LightningStrike = function ( rayParameters ) { - - THREE.BufferGeometry.call( this ); - - this.type = 'LightningStrike'; - - // Set parameters, and set undefined parameters to default values - rayParameters = rayParameters || {}; - this.init( THREE.LightningStrike.copyParameters( rayParameters, rayParameters ) ); - - // Creates and populates the mesh - this.createMesh(); - -}; - -THREE.LightningStrike.prototype = Object.create( THREE.BufferGeometry.prototype ); - -THREE.LightningStrike.prototype.constructor = THREE.LightningStrike; - -THREE.LightningStrike.prototype.isLightningStrike = true; - -// Ray states -THREE.LightningStrike.RAY_INITIALIZED = 0; -THREE.LightningStrike.RAY_UNBORN = 1; -THREE.LightningStrike.RAY_PROPAGATING = 2; -THREE.LightningStrike.RAY_STEADY = 3; -THREE.LightningStrike.RAY_VANISHING = 4; -THREE.LightningStrike.RAY_EXTINGUISHED = 5; + class LightningStrike extends THREE.BufferGeometry { -THREE.LightningStrike.COS30DEG = Math.cos( 30 * Math.PI / 180 ); -THREE.LightningStrike.SIN30DEG = Math.sin( 30 * Math.PI / 180 ); + constructor( rayParameters = {} ) { -THREE.LightningStrike.createRandomGenerator = function () { + super(); + this.type = 'LightningStrike'; // Set parameters, and set undefined parameters to default values - var numSeeds = 2053; - var seeds = []; + this.init( LightningStrike.copyParameters( rayParameters, rayParameters ) ); // Creates and populates the mesh - for ( var i = 0; i < numSeeds; i ++ ) { + this.createMesh(); - seeds.push( Math.random() ); - - } + } - var generator = { + static createRandomGenerator() { - currentSeed: 0, + const numSeeds = 2053; + const seeds = []; - random: function () { + for ( let i = 0; i < numSeeds; i ++ ) { - var value = seeds[ generator.currentSeed ]; + seeds.push( Math.random() ); - generator.currentSeed = ( generator.currentSeed + 1 ) % numSeeds; + } - return value; + const generator = { + currentSeed: 0, + random: function () { - }, + const value = seeds[ generator.currentSeed ]; + generator.currentSeed = ( generator.currentSeed + 1 ) % numSeeds; + return value; - getSeed: function () { + }, + getSeed: function () { - return generator.currentSeed / numSeeds; + return generator.currentSeed / numSeeds; - }, + }, + setSeed: function ( seed ) { - setSeed: function ( seed ) { + generator.currentSeed = Math.floor( seed * numSeeds ) % numSeeds; - generator.currentSeed = Math.floor( seed * numSeeds ) % numSeeds; + } + }; + return generator; } - }; + static copyParameters( dest = {}, source = {} ) { - return generator; + const vecCopy = function ( v ) { -}; + if ( source === dest ) { -THREE.LightningStrike.copyParameters = function ( dest, source ) { + return v; - source = source || {}; - dest = dest || {}; + } else { - var vecCopy = function ( v ) { + return v.clone(); - if ( source === dest ) { + } - return v; + }; - } else { + dest.sourceOffset = source.sourceOffset !== undefined ? vecCopy( source.sourceOffset ) : new THREE.Vector3( 0, 100, 0 ), dest.destOffset = source.destOffset !== undefined ? vecCopy( source.destOffset ) : new THREE.Vector3( 0, 0, 0 ), dest.timeScale = source.timeScale !== undefined ? source.timeScale : 1, dest.roughness = source.roughness !== undefined ? source.roughness : 0.9, dest.straightness = source.straightness !== undefined ? source.straightness : 0.7, dest.up0 = source.up0 !== undefined ? vecCopy( source.up0 ) : new THREE.Vector3( 0, 0, 1 ); + dest.up1 = source.up1 !== undefined ? vecCopy( source.up1 ) : new THREE.Vector3( 0, 0, 1 ), dest.radius0 = source.radius0 !== undefined ? source.radius0 : 1, dest.radius1 = source.radius1 !== undefined ? source.radius1 : 1, dest.radius0Factor = source.radius0Factor !== undefined ? source.radius0Factor : 0.5, dest.radius1Factor = source.radius1Factor !== undefined ? source.radius1Factor : 0.2, dest.minRadius = source.minRadius !== undefined ? source.minRadius : 0.2, // These parameters should not be changed after lightning creation. They can be changed but the ray will change its form abruptly: + dest.isEternal = source.isEternal !== undefined ? source.isEternal : source.birthTime === undefined || source.deathTime === undefined, dest.birthTime = source.birthTime, dest.deathTime = source.deathTime, dest.propagationTimeFactor = source.propagationTimeFactor !== undefined ? source.propagationTimeFactor : 0.1, dest.vanishingTimeFactor = source.vanishingTimeFactor !== undefined ? source.vanishingTimeFactor : 0.9, dest.subrayPeriod = source.subrayPeriod !== undefined ? source.subrayPeriod : 4, dest.subrayDutyCycle = source.subrayDutyCycle !== undefined ? source.subrayDutyCycle : 0.6; // These parameters cannot change after lightning creation: - return v.clone(); + dest.maxIterations = source.maxIterations !== undefined ? source.maxIterations : 9; + dest.isStatic = source.isStatic !== undefined ? source.isStatic : false; + dest.ramification = source.ramification !== undefined ? source.ramification : 5; + dest.maxSubrayRecursion = source.maxSubrayRecursion !== undefined ? source.maxSubrayRecursion : 3; + dest.recursionProbability = source.recursionProbability !== undefined ? source.recursionProbability : 0.6; + dest.generateUVs = source.generateUVs !== undefined ? source.generateUVs : false; + dest.randomGenerator = source.randomGenerator, dest.noiseSeed = source.noiseSeed, dest.onDecideSubrayCreation = source.onDecideSubrayCreation, dest.onSubrayCreation = source.onSubrayCreation; + return dest; } - }; - - dest.sourceOffset = source.sourceOffset !== undefined ? vecCopy( source.sourceOffset ) : new THREE.Vector3( 0, 100, 0 ), - dest.destOffset = source.destOffset !== undefined ? vecCopy( source.destOffset ) : new THREE.Vector3( 0, 0, 0 ), - - dest.timeScale = source.timeScale !== undefined ? source.timeScale : 1, - dest.roughness = source.roughness !== undefined ? source.roughness : 0.9, - dest.straightness = source.straightness !== undefined ? source.straightness : 0.7, - - dest.up0 = source.up0 !== undefined ? vecCopy( source.up0 ) : new THREE.Vector3( 0, 0, 1 ); - dest.up1 = source.up1 !== undefined ? vecCopy( source.up1 ) : new THREE.Vector3( 0, 0, 1 ), - dest.radius0 = source.radius0 !== undefined ? source.radius0 : 1, - dest.radius1 = source.radius1 !== undefined ? source.radius1 : 1, - dest.radius0Factor = source.radius0Factor !== undefined ? source.radius0Factor : 0.5, - dest.radius1Factor = source.radius1Factor !== undefined ? source.radius1Factor : 0.2, - dest.minRadius = source.minRadius !== undefined ? source.minRadius : 0.2, - - // These parameters should not be changed after lightning creation. They can be changed but the ray will change its form abruptly: - - dest.isEternal = source.isEternal !== undefined ? source.isEternal : ( source.birthTime === undefined || source.deathTime === undefined ), - dest.birthTime = source.birthTime, - dest.deathTime = source.deathTime, - dest.propagationTimeFactor = source.propagationTimeFactor !== undefined ? source.propagationTimeFactor : 0.1, - dest.vanishingTimeFactor = source.vanishingTimeFactor !== undefined ? source.vanishingTimeFactor : 0.9, - dest.subrayPeriod = source.subrayPeriod !== undefined ? source.subrayPeriod : 4, - dest.subrayDutyCycle = source.subrayDutyCycle !== undefined ? source.subrayDutyCycle : 0.6; + update( time ) { - // These parameters cannot change after lightning creation: + if ( this.isStatic ) return; - dest.maxIterations = source.maxIterations !== undefined ? source.maxIterations : 9; - dest.isStatic = source.isStatic !== undefined ? source.isStatic : false; - dest.ramification = source.ramification !== undefined ? source.ramification : 5; - dest.maxSubrayRecursion = source.maxSubrayRecursion !== undefined ? source.maxSubrayRecursion : 3; - dest.recursionProbability = source.recursionProbability !== undefined ? source.recursionProbability : 0.6; - dest.generateUVs = source.generateUVs !== undefined ? source.generateUVs : false; - dest.randomGenerator = source.randomGenerator, - dest.noiseSeed = source.noiseSeed, - dest.onDecideSubrayCreation = source.onDecideSubrayCreation, - dest.onSubrayCreation = source.onSubrayCreation; + if ( this.rayParameters.isEternal || this.rayParameters.birthTime <= time && time <= this.rayParameters.deathTime ) { - return dest; + this.updateMesh( time ); -}; + if ( time < this.subrays[ 0 ].endPropagationTime ) { -THREE.LightningStrike.prototype.update = function ( time ) { + this.state = LightningStrike.RAY_PROPAGATING; - if ( this.isStatic ) return; + } else if ( time > this.subrays[ 0 ].beginVanishingTime ) { - if ( this.rayParameters.isEternal || ( this.rayParameters.birthTime <= time && time <= this.rayParameters.deathTime ) ) { + this.state = LightningStrike.RAY_VANISHING; - this.updateMesh( time ); + } else { - if ( time < this.subrays[ 0 ].endPropagationTime ) { - - this.state = THREE.LightningStrike.RAY_PROPAGATING; - - } else if ( time > this.subrays[ 0 ].beginVanishingTime ) { - - this.state = THREE.LightningStrike.RAY_VANISHING; - - } else { - - this.state = THREE.LightningStrike.RAY_STEADY; - - } - - this.visible = true; - - } else { - - this.visible = false; - - if ( time < this.rayParameters.birthTime ) { - - this.state = THREE.LightningStrike.RAY_UNBORN; - - } else { - - this.state = THREE.LightningStrike.RAY_EXTINGUISHED; - - } - - } + this.state = LightningStrike.RAY_STEADY; -}; + } -THREE.LightningStrike.prototype.init = function ( rayParameters ) { + this.visible = true; - // Init all the state from the parameters + } else { - this.rayParameters = rayParameters; + this.visible = false; - // These parameters cannot change after lightning creation: + if ( time < this.rayParameters.birthTime ) { - this.maxIterations = rayParameters.maxIterations !== undefined ? Math.floor( rayParameters.maxIterations ) : 9; - rayParameters.maxIterations = this.maxIterations; - this.isStatic = rayParameters.isStatic !== undefined ? rayParameters.isStatic : false; - rayParameters.isStatic = this.isStatic; - this.ramification = rayParameters.ramification !== undefined ? Math.floor( rayParameters.ramification ) : 5; - rayParameters.ramification = this.ramification; - this.maxSubrayRecursion = rayParameters.maxSubrayRecursion !== undefined ? Math.floor( rayParameters.maxSubrayRecursion ) : 3; - rayParameters.maxSubrayRecursion = this.maxSubrayRecursion; - this.recursionProbability = rayParameters.recursionProbability !== undefined ? rayParameters.recursionProbability : 0.6; - rayParameters.recursionProbability = this.recursionProbability; - this.generateUVs = rayParameters.generateUVs !== undefined ? rayParameters.generateUVs : false; - rayParameters.generateUVs = this.generateUVs; + this.state = LightningStrike.RAY_UNBORN; - // Random generator - if ( rayParameters.randomGenerator !== undefined ) { + } else { - this.randomGenerator = rayParameters.randomGenerator; - this.seedGenerator = rayParameters.randomGenerator; + this.state = LightningStrike.RAY_EXTINGUISHED; - if ( rayParameters.noiseSeed !== undefined ) { + } - this.seedGenerator.setSeed( rayParameters.noiseSeed ); + } } - } else { + init( rayParameters ) { - this.randomGenerator = THREE.LightningStrike.createRandomGenerator(); - this.seedGenerator = Math; + // Init all the state from the parameters + this.rayParameters = rayParameters; // These parameters cannot change after lightning creation: - } + this.maxIterations = rayParameters.maxIterations !== undefined ? Math.floor( rayParameters.maxIterations ) : 9; + rayParameters.maxIterations = this.maxIterations; + this.isStatic = rayParameters.isStatic !== undefined ? rayParameters.isStatic : false; + rayParameters.isStatic = this.isStatic; + this.ramification = rayParameters.ramification !== undefined ? Math.floor( rayParameters.ramification ) : 5; + rayParameters.ramification = this.ramification; + this.maxSubrayRecursion = rayParameters.maxSubrayRecursion !== undefined ? Math.floor( rayParameters.maxSubrayRecursion ) : 3; + rayParameters.maxSubrayRecursion = this.maxSubrayRecursion; + this.recursionProbability = rayParameters.recursionProbability !== undefined ? rayParameters.recursionProbability : 0.6; + rayParameters.recursionProbability = this.recursionProbability; + this.generateUVs = rayParameters.generateUVs !== undefined ? rayParameters.generateUVs : false; + rayParameters.generateUVs = this.generateUVs; // Random generator - // Ray creation callbacks - if ( rayParameters.onDecideSubrayCreation !== undefined ) { + if ( rayParameters.randomGenerator !== undefined ) { - this.onDecideSubrayCreation = rayParameters.onDecideSubrayCreation; + this.randomGenerator = rayParameters.randomGenerator; + this.seedGenerator = rayParameters.randomGenerator; - } else { + if ( rayParameters.noiseSeed !== undefined ) { - this.createDefaultSubrayCreationCallbacks(); + this.seedGenerator.setSeed( rayParameters.noiseSeed ); - if ( rayParameters.onSubrayCreation !== undefined ) { + } - this.onSubrayCreation = rayParameters.onSubrayCreation; + } else { - } - - } + this.randomGenerator = LightningStrike.createRandomGenerator(); + this.seedGenerator = Math; - // Internal state + } // Ray creation callbacks - this.state = THREE.LightningStrike.RAY_INITIALIZED; - this.maxSubrays = Math.ceil( 1 + Math.pow( this.ramification, Math.max( 0, this.maxSubrayRecursion - 1 ) ) ); - rayParameters.maxSubrays = this.maxSubrays; + if ( rayParameters.onDecideSubrayCreation !== undefined ) { - this.maxRaySegments = 2 * ( 1 << this.maxIterations ); + this.onDecideSubrayCreation = rayParameters.onDecideSubrayCreation; - this.subrays = []; - - for ( var i = 0; i < this.maxSubrays; i ++ ) { - - this.subrays.push( this.createSubray() ); - - } + } else { - this.raySegments = []; + this.createDefaultSubrayCreationCallbacks(); - for ( var i = 0; i < this.maxRaySegments; i ++ ) { + if ( rayParameters.onSubrayCreation !== undefined ) { - this.raySegments.push( this.createSegment() ); + this.onSubrayCreation = rayParameters.onSubrayCreation; - } + } - this.time = 0; - this.timeFraction = 0; - this.currentSegmentCallback = null; - this.currentCreateTriangleVertices = this.generateUVs ? this.createTriangleVerticesWithUVs : this.createTriangleVerticesWithoutUVs; - this.numSubrays = 0; - this.currentSubray = null; - this.currentSegmentIndex = 0; - this.isInitialSegment = false; - this.subrayProbability = 0; - - this.currentVertex = 0; - this.currentIndex = 0; - this.currentCoordinate = 0; - this.currentUVCoordinate = 0; - this.vertices = null; - this.uvs = null; - this.indices = null; - this.positionAttribute = null; - this.uvsAttribute = null; - - this.simplexX = new THREE.SimplexNoise( this.seedGenerator ); - this.simplexY = new THREE.SimplexNoise( this.seedGenerator ); - this.simplexZ = new THREE.SimplexNoise( this.seedGenerator ); - - // Temp vectors - this.forwards = new THREE.Vector3(); - this.forwardsFill = new THREE.Vector3(); - this.side = new THREE.Vector3(); - this.down = new THREE.Vector3(); - this.middlePos = new THREE.Vector3(); - this.middleLinPos = new THREE.Vector3(); - this.newPos = new THREE.Vector3(); - this.vPos = new THREE.Vector3(); - this.cross1 = new THREE.Vector3(); - -}; - -THREE.LightningStrike.prototype.createMesh = function () { - - var maxDrawableSegmentsPerSubRay = 1 << this.maxIterations; - - var maxVerts = 3 * ( maxDrawableSegmentsPerSubRay + 1 ) * this.maxSubrays; - var maxIndices = 18 * maxDrawableSegmentsPerSubRay * this.maxSubrays; - - this.vertices = new Float32Array( maxVerts * 3 ); - this.indices = new Uint32Array( maxIndices ); - if ( this.generateUVs ) { - - this.uvs = new Float32Array( maxVerts * 2 ); + } // Internal state - } - // Populate the mesh - this.fillMesh( 0 ); + this.state = LightningStrike.RAY_INITIALIZED; + this.maxSubrays = Math.ceil( 1 + Math.pow( this.ramification, Math.max( 0, this.maxSubrayRecursion - 1 ) ) ); + rayParameters.maxSubrays = this.maxSubrays; + this.maxRaySegments = 2 * ( 1 << this.maxIterations ); + this.subrays = []; - this.setIndex( new THREE.Uint32BufferAttribute( this.indices, 1 ) ); + for ( let i = 0; i < this.maxSubrays; i ++ ) { - this.positionAttribute = new THREE.Float32BufferAttribute( this.vertices, 3 ); - this.setAttribute( 'position', this.positionAttribute ); + this.subrays.push( this.createSubray() ); - if ( this.generateUVs ) { + } - this.uvsAttribute = new THREE.Float32BufferAttribute( new Float32Array( this.uvs ), 2 ); - this.setAttribute( 'uv', this.uvsAttribute ); + this.raySegments = []; - } + for ( let i = 0; i < this.maxRaySegments; i ++ ) { - if ( ! this.isStatic ) { + this.raySegments.push( this.createSegment() ); - this.index.usage = THREE.DynamicDrawUsage; - this.positionAttribute.usage = THREE.DynamicDrawUsage; - if ( this.generateUVs ) { + } - this.uvsAttribute.usage = THREE.DynamicDrawUsage; + this.time = 0; + this.timeFraction = 0; + this.currentSegmentCallback = null; + this.currentCreateTriangleVertices = this.generateUVs ? this.createTriangleVerticesWithUVs : this.createTriangleVerticesWithoutUVs; + this.numSubrays = 0; + this.currentSubray = null; + this.currentSegmentIndex = 0; + this.isInitialSegment = false; + this.subrayProbability = 0; + this.currentVertex = 0; + this.currentIndex = 0; + this.currentCoordinate = 0; + this.currentUVCoordinate = 0; + this.vertices = null; + this.uvs = null; + this.indices = null; + this.positionAttribute = null; + this.uvsAttribute = null; + this.simplexX = new THREE.SimplexNoise( this.seedGenerator ); + this.simplexY = new THREE.SimplexNoise( this.seedGenerator ); + this.simplexZ = new THREE.SimplexNoise( this.seedGenerator ); // Temp vectors + + this.forwards = new THREE.Vector3(); + this.forwardsFill = new THREE.Vector3(); + this.side = new THREE.Vector3(); + this.down = new THREE.Vector3(); + this.middlePos = new THREE.Vector3(); + this.middleLinPos = new THREE.Vector3(); + this.newPos = new THREE.Vector3(); + this.vPos = new THREE.Vector3(); + this.cross1 = new THREE.Vector3(); } - } - - // Store buffers for later modification - this.vertices = this.positionAttribute.array; - this.indices = this.index.array; - if ( this.generateUVs ) { - - this.uvs = this.uvsAttribute.array; - - } - -}; - -THREE.LightningStrike.prototype.updateMesh = function ( time ) { - - this.fillMesh( time ); - - this.drawRange.count = this.currentIndex; + createMesh() { - this.index.needsUpdate = true; + const maxDrawableSegmentsPerSubRay = 1 << this.maxIterations; + const maxVerts = 3 * ( maxDrawableSegmentsPerSubRay + 1 ) * this.maxSubrays; + const maxIndices = 18 * maxDrawableSegmentsPerSubRay * this.maxSubrays; + this.vertices = new Float32Array( maxVerts * 3 ); + this.indices = new Uint32Array( maxIndices ); - this.positionAttribute.needsUpdate = true; - - if ( this.generateUVs ) { - - this.uvsAttribute.needsUpdate = true; - - } + if ( this.generateUVs ) { -}; + this.uvs = new Float32Array( maxVerts * 2 ); -THREE.LightningStrike.prototype.fillMesh = function ( time ) { + } // Populate the mesh - var scope = this; - this.currentVertex = 0; - this.currentIndex = 0; - this.currentCoordinate = 0; - this.currentUVCoordinate = 0; + this.fillMesh( 0 ); + this.setIndex( new THREE.Uint32BufferAttribute( this.indices, 1 ) ); + this.positionAttribute = new THREE.Float32BufferAttribute( this.vertices, 3 ); + this.setAttribute( 'position', this.positionAttribute ); - this.fractalRay( time, function fillVertices( segment ) { + if ( this.generateUVs ) { - var subray = scope.currentSubray; + this.uvsAttribute = new THREE.Float32BufferAttribute( new Float32Array( this.uvs ), 2 ); + this.setAttribute( 'uv', this.uvsAttribute ); - if ( time < subray.birthTime ) { //&& ( ! this.rayParameters.isEternal || scope.currentSubray.recursion > 0 ) ) { + } - return; + if ( ! this.isStatic ) { - } else if ( this.rayParameters.isEternal && scope.currentSubray.recursion == 0 ) { + this.index.usage = THREE.DynamicDrawUsage; + this.positionAttribute.usage = THREE.DynamicDrawUsage; - // Eternal rays don't propagate nor vanish, but its subrays do + if ( this.generateUVs ) { - scope.createPrism( segment ); + this.uvsAttribute.usage = THREE.DynamicDrawUsage; - scope.onDecideSubrayCreation( segment, scope ); + } - } else if ( time < subray.endPropagationTime ) { + } // Store buffers for later modification - if ( scope.timeFraction >= segment.fraction0 * subray.propagationTimeFactor ) { - // Ray propagation has arrived to this segment + this.vertices = this.positionAttribute.array; + this.indices = this.index.array; - scope.createPrism( segment ); + if ( this.generateUVs ) { - scope.onDecideSubrayCreation( segment, scope ); + this.uvs = this.uvsAttribute.array; } - } else if ( time < subray.beginVanishingTime ) { - - // Ray is steady (nor propagating nor vanishing) - - scope.createPrism( segment ); - - scope.onDecideSubrayCreation( segment, scope ); + } - } else { + updateMesh( time ) { - if ( scope.timeFraction <= subray.vanishingTimeFactor + segment.fraction1 * ( 1 - subray.vanishingTimeFactor ) ) { + this.fillMesh( time ); + this.drawRange.count = this.currentIndex; + this.index.needsUpdate = true; + this.positionAttribute.needsUpdate = true; - // Segment has not yet vanished + if ( this.generateUVs ) { - scope.createPrism( segment ); + this.uvsAttribute.needsUpdate = true; } - scope.onDecideSubrayCreation( segment, scope ); - } - } ); - -}; + fillMesh( time ) { -THREE.LightningStrike.prototype.addNewSubray = function ( /*rayParameters*/ ) { + const scope = this; + this.currentVertex = 0; + this.currentIndex = 0; + this.currentCoordinate = 0; + this.currentUVCoordinate = 0; + this.fractalRay( time, function fillVertices( segment ) { - return this.subrays[ this.numSubrays ++ ]; + const subray = scope.currentSubray; -}; + if ( time < subray.birthTime ) { -THREE.LightningStrike.prototype.initSubray = function ( subray, rayParameters ) { + //&& ( ! this.rayParameters.isEternal || scope.currentSubray.recursion > 0 ) ) { + return; - subray.pos0.copy( rayParameters.sourceOffset ); - subray.pos1.copy( rayParameters.destOffset ); - subray.up0.copy( rayParameters.up0 ); - subray.up1.copy( rayParameters.up1 ); - subray.radius0 = rayParameters.radius0; - subray.radius1 = rayParameters.radius1; - subray.birthTime = rayParameters.birthTime; - subray.deathTime = rayParameters.deathTime; - subray.timeScale = rayParameters.timeScale; - subray.roughness = rayParameters.roughness; - subray.straightness = rayParameters.straightness; - subray.propagationTimeFactor = rayParameters.propagationTimeFactor; - subray.vanishingTimeFactor = rayParameters.vanishingTimeFactor; + } else if ( this.rayParameters.isEternal && scope.currentSubray.recursion == 0 ) { - subray.maxIterations = this.maxIterations; - subray.seed = rayParameters.noiseSeed !== undefined ? rayParameters.noiseSeed : 0; - subray.recursion = 0; + // Eternal rays don't propagate nor vanish, but its subrays do + scope.createPrism( segment ); + scope.onDecideSubrayCreation( segment, scope ); -}; + } else if ( time < subray.endPropagationTime ) { -THREE.LightningStrike.prototype.fractalRay = function ( time, segmentCallback ) { + if ( scope.timeFraction >= segment.fraction0 * subray.propagationTimeFactor ) { - this.time = time; - this.currentSegmentCallback = segmentCallback; - this.numSubrays = 0; + // Ray propagation has arrived to this segment + scope.createPrism( segment ); + scope.onDecideSubrayCreation( segment, scope ); - // Add the top level subray - this.initSubray( this.addNewSubray(), this.rayParameters ); + } - // Process all subrays that are being generated until consuming all of them - for ( var subrayIndex = 0; subrayIndex < this.numSubrays; subrayIndex ++ ) { + } else if ( time < subray.beginVanishingTime ) { - var subray = this.subrays[ subrayIndex ]; - this.currentSubray = subray; + // Ray is steady (nor propagating nor vanishing) + scope.createPrism( segment ); + scope.onDecideSubrayCreation( segment, scope ); - this.randomGenerator.setSeed( subray.seed ); + } else { - subray.endPropagationTime = THREE.MathUtils.lerp( subray.birthTime, subray.deathTime, subray.propagationTimeFactor ); - subray.beginVanishingTime = THREE.MathUtils.lerp( subray.deathTime, subray.birthTime, 1 - subray.vanishingTimeFactor ); + if ( scope.timeFraction <= subray.vanishingTimeFactor + segment.fraction1 * ( 1 - subray.vanishingTimeFactor ) ) { - var random1 = this.randomGenerator.random; - subray.linPos0.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); - subray.linPos1.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); + // Segment has not yet vanished + scope.createPrism( segment ); - this.timeFraction = ( time - subray.birthTime ) / ( subray.deathTime - subray.birthTime ); + } - this.currentSegmentIndex = 0; - this.isInitialSegment = true; + scope.onDecideSubrayCreation( segment, scope ); - var segment = this.getNewSegment(); - segment.iteration = 0; - segment.pos0.copy( subray.pos0 ); - segment.pos1.copy( subray.pos1 ); - segment.linPos0.copy( subray.linPos0 ); - segment.linPos1.copy( subray.linPos1 ); - segment.up0.copy( subray.up0 ); - segment.up1.copy( subray.up1 ); - segment.radius0 = subray.radius0; - segment.radius1 = subray.radius1; - segment.fraction0 = 0; - segment.fraction1 = 1; - segment.positionVariationFactor = 1 - subray.straightness; + } - this.subrayProbability = this.ramification * Math.pow( this.recursionProbability, subray.recursion ) / ( 1 << subray.maxIterations ); + } ); - this.fractalRayRecursive( segment ); - - } - - this.currentSegmentCallback = null; - this.currentSubray = null; - -}; - -THREE.LightningStrike.prototype.fractalRayRecursive = function ( segment ) { - - // Leave recursion condition - if ( segment.iteration >= this.currentSubray.maxIterations ) { - - this.currentSegmentCallback( segment ); - - return; - - } - - // Interpolation - this.forwards.subVectors( segment.pos1, segment.pos0 ); - var lForwards = this.forwards.length(); - - if ( lForwards < 0.000001 ) { - - this.forwards.set( 0, 0, 0.01 ); - lForwards = this.forwards.length(); - - } - - var middleRadius = ( segment.radius0 + segment.radius1 ) * 0.5; - var middleFraction = ( segment.fraction0 + segment.fraction1 ) * 0.5; - - var timeDimension = this.time * this.currentSubray.timeScale * Math.pow( 2, segment.iteration ); - - this.middlePos.lerpVectors( segment.pos0, segment.pos1, 0.5 ); - this.middleLinPos.lerpVectors( segment.linPos0, segment.linPos1, 0.5 ); - var p = this.middleLinPos; - - // Noise - this.newPos.set( this.simplexX.noise4d( p.x, p.y, p.z, timeDimension ), - this.simplexY.noise4d( p.x, p.y, p.z, timeDimension ), - this.simplexZ.noise4d( p.x, p.y, p.z, timeDimension ) ); - - this.newPos.multiplyScalar( segment.positionVariationFactor * lForwards ); - this.newPos.add( this.middlePos ); - - // Recursion - - var newSegment1 = this.getNewSegment(); - newSegment1.pos0.copy( segment.pos0 ); - newSegment1.pos1.copy( this.newPos ); - newSegment1.linPos0.copy( segment.linPos0 ); - newSegment1.linPos1.copy( this.middleLinPos ); - newSegment1.up0.copy( segment.up0 ); - newSegment1.up1.copy( segment.up1 ); - newSegment1.radius0 = segment.radius0; - newSegment1.radius1 = middleRadius; - newSegment1.fraction0 = segment.fraction0; - newSegment1.fraction1 = middleFraction; - newSegment1.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness; - newSegment1.iteration = segment.iteration + 1; + } - var newSegment2 = this.getNewSegment(); - newSegment2.pos0.copy( this.newPos ); - newSegment2.pos1.copy( segment.pos1 ); - newSegment2.linPos0.copy( this.middleLinPos ); - newSegment2.linPos1.copy( segment.linPos1 ); - this.cross1.crossVectors( segment.up0, this.forwards.normalize() ); - newSegment2.up0.crossVectors( this.forwards, this.cross1 ).normalize(); - newSegment2.up1.copy( segment.up1 ); - newSegment2.radius0 = middleRadius; - newSegment2.radius1 = segment.radius1; - newSegment2.fraction0 = middleFraction; - newSegment2.fraction1 = segment.fraction1; - newSegment2.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness; - newSegment2.iteration = segment.iteration + 1; + addNewSubray( ) { - this.fractalRayRecursive( newSegment1 ); + return this.subrays[ this.numSubrays ++ ]; - this.fractalRayRecursive( newSegment2 ); + } -}; + initSubray( subray, rayParameters ) { + + subray.pos0.copy( rayParameters.sourceOffset ); + subray.pos1.copy( rayParameters.destOffset ); + subray.up0.copy( rayParameters.up0 ); + subray.up1.copy( rayParameters.up1 ); + subray.radius0 = rayParameters.radius0; + subray.radius1 = rayParameters.radius1; + subray.birthTime = rayParameters.birthTime; + subray.deathTime = rayParameters.deathTime; + subray.timeScale = rayParameters.timeScale; + subray.roughness = rayParameters.roughness; + subray.straightness = rayParameters.straightness; + subray.propagationTimeFactor = rayParameters.propagationTimeFactor; + subray.vanishingTimeFactor = rayParameters.vanishingTimeFactor; + subray.maxIterations = this.maxIterations; + subray.seed = rayParameters.noiseSeed !== undefined ? rayParameters.noiseSeed : 0; + subray.recursion = 0; -THREE.LightningStrike.prototype.createPrism = function ( segment ) { + } - // Creates one triangular prism and its vertices at the segment + fractalRay( time, segmentCallback ) { + + this.time = time; + this.currentSegmentCallback = segmentCallback; + this.numSubrays = 0; // Add the top level subray + + this.initSubray( this.addNewSubray(), this.rayParameters ); // Process all subrays that are being generated until consuming all of them + + for ( let subrayIndex = 0; subrayIndex < this.numSubrays; subrayIndex ++ ) { + + const subray = this.subrays[ subrayIndex ]; + this.currentSubray = subray; + this.randomGenerator.setSeed( subray.seed ); + subray.endPropagationTime = THREE.MathUtils.lerp( subray.birthTime, subray.deathTime, subray.propagationTimeFactor ); + subray.beginVanishingTime = THREE.MathUtils.lerp( subray.deathTime, subray.birthTime, 1 - subray.vanishingTimeFactor ); + const random1 = this.randomGenerator.random; + subray.linPos0.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); + subray.linPos1.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); + this.timeFraction = ( time - subray.birthTime ) / ( subray.deathTime - subray.birthTime ); + this.currentSegmentIndex = 0; + this.isInitialSegment = true; + const segment = this.getNewSegment(); + segment.iteration = 0; + segment.pos0.copy( subray.pos0 ); + segment.pos1.copy( subray.pos1 ); + segment.linPos0.copy( subray.linPos0 ); + segment.linPos1.copy( subray.linPos1 ); + segment.up0.copy( subray.up0 ); + segment.up1.copy( subray.up1 ); + segment.radius0 = subray.radius0; + segment.radius1 = subray.radius1; + segment.fraction0 = 0; + segment.fraction1 = 1; + segment.positionVariationFactor = 1 - subray.straightness; + this.subrayProbability = this.ramification * Math.pow( this.recursionProbability, subray.recursion ) / ( 1 << subray.maxIterations ); + this.fractalRayRecursive( segment ); - this.forwardsFill.subVectors( segment.pos1, segment.pos0 ).normalize(); + } - if ( this.isInitialSegment ) { + this.currentSegmentCallback = null; + this.currentSubray = null; - this.currentCreateTriangleVertices( segment.pos0, segment.up0, this.forwardsFill, segment.radius0, 0 ); + } - this.isInitialSegment = false; + fractalRayRecursive( segment ) { - } + // Leave recursion condition + if ( segment.iteration >= this.currentSubray.maxIterations ) { - this.currentCreateTriangleVertices( segment.pos1, segment.up0, this.forwardsFill, segment.radius1, segment.fraction1 ); + this.currentSegmentCallback( segment ); + return; - this.createPrismFaces(); + } // Interpolation -}; -THREE.LightningStrike.prototype.createTriangleVerticesWithoutUVs = function ( pos, up, forwards, radius ) { + this.forwards.subVectors( segment.pos1, segment.pos0 ); + let lForwards = this.forwards.length(); - // Create an equilateral triangle (only vertices) + if ( lForwards < 0.000001 ) { - this.side.crossVectors( up, forwards ).multiplyScalar( radius * THREE.LightningStrike.COS30DEG ); - this.down.copy( up ).multiplyScalar( - radius * THREE.LightningStrike.SIN30DEG ); + this.forwards.set( 0, 0, 0.01 ); + lForwards = this.forwards.length(); - var p = this.vPos; - var v = this.vertices; + } - p.copy( pos ).sub( this.side ).add( this.down ); + const middleRadius = ( segment.radius0 + segment.radius1 ) * 0.5; + const middleFraction = ( segment.fraction0 + segment.fraction1 ) * 0.5; + const timeDimension = this.time * this.currentSubray.timeScale * Math.pow( 2, segment.iteration ); + this.middlePos.lerpVectors( segment.pos0, segment.pos1, 0.5 ); + this.middleLinPos.lerpVectors( segment.linPos0, segment.linPos1, 0.5 ); + const p = this.middleLinPos; // Noise + + this.newPos.set( this.simplexX.noise4d( p.x, p.y, p.z, timeDimension ), this.simplexY.noise4d( p.x, p.y, p.z, timeDimension ), this.simplexZ.noise4d( p.x, p.y, p.z, timeDimension ) ); + this.newPos.multiplyScalar( segment.positionVariationFactor * lForwards ); + this.newPos.add( this.middlePos ); // Recursion + + const newSegment1 = this.getNewSegment(); + newSegment1.pos0.copy( segment.pos0 ); + newSegment1.pos1.copy( this.newPos ); + newSegment1.linPos0.copy( segment.linPos0 ); + newSegment1.linPos1.copy( this.middleLinPos ); + newSegment1.up0.copy( segment.up0 ); + newSegment1.up1.copy( segment.up1 ); + newSegment1.radius0 = segment.radius0; + newSegment1.radius1 = middleRadius; + newSegment1.fraction0 = segment.fraction0; + newSegment1.fraction1 = middleFraction; + newSegment1.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness; + newSegment1.iteration = segment.iteration + 1; + const newSegment2 = this.getNewSegment(); + newSegment2.pos0.copy( this.newPos ); + newSegment2.pos1.copy( segment.pos1 ); + newSegment2.linPos0.copy( this.middleLinPos ); + newSegment2.linPos1.copy( segment.linPos1 ); + this.cross1.crossVectors( segment.up0, this.forwards.normalize() ); + newSegment2.up0.crossVectors( this.forwards, this.cross1 ).normalize(); + newSegment2.up1.copy( segment.up1 ); + newSegment2.radius0 = middleRadius; + newSegment2.radius1 = segment.radius1; + newSegment2.fraction0 = middleFraction; + newSegment2.fraction1 = segment.fraction1; + newSegment2.positionVariationFactor = segment.positionVariationFactor * this.currentSubray.roughness; + newSegment2.iteration = segment.iteration + 1; + this.fractalRayRecursive( newSegment1 ); + this.fractalRayRecursive( newSegment2 ); - v[ this.currentCoordinate ++ ] = p.x; - v[ this.currentCoordinate ++ ] = p.y; - v[ this.currentCoordinate ++ ] = p.z; + } - p.copy( pos ).add( this.side ).add( this.down ); + createPrism( segment ) { - v[ this.currentCoordinate ++ ] = p.x; - v[ this.currentCoordinate ++ ] = p.y; - v[ this.currentCoordinate ++ ] = p.z; + // Creates one triangular prism and its vertices at the segment + this.forwardsFill.subVectors( segment.pos1, segment.pos0 ).normalize(); - p.copy( up ).multiplyScalar( radius ).add( pos ); + if ( this.isInitialSegment ) { - v[ this.currentCoordinate ++ ] = p.x; - v[ this.currentCoordinate ++ ] = p.y; - v[ this.currentCoordinate ++ ] = p.z; + this.currentCreateTriangleVertices( segment.pos0, segment.up0, this.forwardsFill, segment.radius0, 0 ); + this.isInitialSegment = false; - this.currentVertex += 3; + } -}; + this.currentCreateTriangleVertices( segment.pos1, segment.up0, this.forwardsFill, segment.radius1, segment.fraction1 ); + this.createPrismFaces(); -THREE.LightningStrike.prototype.createTriangleVerticesWithUVs = function ( pos, up, forwards, radius, u ) { + } - // Create an equilateral triangle (only vertices) + createTriangleVerticesWithoutUVs( pos, up, forwards, radius ) { + + // Create an equilateral triangle (only vertices) + this.side.crossVectors( up, forwards ).multiplyScalar( radius * LightningStrike.COS30DEG ); + this.down.copy( up ).multiplyScalar( - radius * LightningStrike.SIN30DEG ); + const p = this.vPos; + const v = this.vertices; + p.copy( pos ).sub( this.side ).add( this.down ); + v[ this.currentCoordinate ++ ] = p.x; + v[ this.currentCoordinate ++ ] = p.y; + v[ this.currentCoordinate ++ ] = p.z; + p.copy( pos ).add( this.side ).add( this.down ); + v[ this.currentCoordinate ++ ] = p.x; + v[ this.currentCoordinate ++ ] = p.y; + v[ this.currentCoordinate ++ ] = p.z; + p.copy( up ).multiplyScalar( radius ).add( pos ); + v[ this.currentCoordinate ++ ] = p.x; + v[ this.currentCoordinate ++ ] = p.y; + v[ this.currentCoordinate ++ ] = p.z; + this.currentVertex += 3; - this.side.crossVectors( up, forwards ).multiplyScalar( radius * THREE.LightningStrike.COS30DEG ); - this.down.copy( up ).multiplyScalar( - radius * THREE.LightningStrike.SIN30DEG ); + } - var p = this.vPos; - var v = this.vertices; - var uv = this.uvs; + createTriangleVerticesWithUVs( pos, up, forwards, radius, u ) { + + // Create an equilateral triangle (only vertices) + this.side.crossVectors( up, forwards ).multiplyScalar( radius * LightningStrike.COS30DEG ); + this.down.copy( up ).multiplyScalar( - radius * LightningStrike.SIN30DEG ); + const p = this.vPos; + const v = this.vertices; + const uv = this.uvs; + p.copy( pos ).sub( this.side ).add( this.down ); + v[ this.currentCoordinate ++ ] = p.x; + v[ this.currentCoordinate ++ ] = p.y; + v[ this.currentCoordinate ++ ] = p.z; + uv[ this.currentUVCoordinate ++ ] = u; + uv[ this.currentUVCoordinate ++ ] = 0; + p.copy( pos ).add( this.side ).add( this.down ); + v[ this.currentCoordinate ++ ] = p.x; + v[ this.currentCoordinate ++ ] = p.y; + v[ this.currentCoordinate ++ ] = p.z; + uv[ this.currentUVCoordinate ++ ] = u; + uv[ this.currentUVCoordinate ++ ] = 0.5; + p.copy( up ).multiplyScalar( radius ).add( pos ); + v[ this.currentCoordinate ++ ] = p.x; + v[ this.currentCoordinate ++ ] = p.y; + v[ this.currentCoordinate ++ ] = p.z; + uv[ this.currentUVCoordinate ++ ] = u; + uv[ this.currentUVCoordinate ++ ] = 1; + this.currentVertex += 3; - p.copy( pos ).sub( this.side ).add( this.down ); + } - v[ this.currentCoordinate ++ ] = p.x; - v[ this.currentCoordinate ++ ] = p.y; - v[ this.currentCoordinate ++ ] = p.z; + createPrismFaces( vertex + /*, index*/ + ) { + + const indices = this.indices; + vertex = this.currentVertex - 6; + indices[ this.currentIndex ++ ] = vertex + 1; + indices[ this.currentIndex ++ ] = vertex + 2; + indices[ this.currentIndex ++ ] = vertex + 5; + indices[ this.currentIndex ++ ] = vertex + 1; + indices[ this.currentIndex ++ ] = vertex + 5; + indices[ this.currentIndex ++ ] = vertex + 4; + indices[ this.currentIndex ++ ] = vertex + 0; + indices[ this.currentIndex ++ ] = vertex + 1; + indices[ this.currentIndex ++ ] = vertex + 4; + indices[ this.currentIndex ++ ] = vertex + 0; + indices[ this.currentIndex ++ ] = vertex + 4; + indices[ this.currentIndex ++ ] = vertex + 3; + indices[ this.currentIndex ++ ] = vertex + 2; + indices[ this.currentIndex ++ ] = vertex + 0; + indices[ this.currentIndex ++ ] = vertex + 3; + indices[ this.currentIndex ++ ] = vertex + 2; + indices[ this.currentIndex ++ ] = vertex + 3; + indices[ this.currentIndex ++ ] = vertex + 5; - uv[ this.currentUVCoordinate ++ ] = u; - uv[ this.currentUVCoordinate ++ ] = 0; + } - p.copy( pos ).add( this.side ).add( this.down ); + createDefaultSubrayCreationCallbacks() { - v[ this.currentCoordinate ++ ] = p.x; - v[ this.currentCoordinate ++ ] = p.y; - v[ this.currentCoordinate ++ ] = p.z; + const random1 = this.randomGenerator.random; - uv[ this.currentUVCoordinate ++ ] = u; - uv[ this.currentUVCoordinate ++ ] = 0.5; + this.onDecideSubrayCreation = function ( segment, lightningStrike ) { - p.copy( up ).multiplyScalar( radius ).add( pos ); + // Decide subrays creation at parent (sub)ray segment + const subray = lightningStrike.currentSubray; + const period = lightningStrike.rayParameters.subrayPeriod; + const dutyCycle = lightningStrike.rayParameters.subrayDutyCycle; + const phase0 = lightningStrike.rayParameters.isEternal && subray.recursion == 0 ? - random1() * period : THREE.MathUtils.lerp( subray.birthTime, subray.endPropagationTime, segment.fraction0 ) - random1() * period; + const phase = lightningStrike.time - phase0; + const currentCycle = Math.floor( phase / period ); + const childSubraySeed = random1() * ( currentCycle + 1 ); + const isActive = phase % period <= dutyCycle * period; + let probability = 0; - v[ this.currentCoordinate ++ ] = p.x; - v[ this.currentCoordinate ++ ] = p.y; - v[ this.currentCoordinate ++ ] = p.z; + if ( isActive ) { - uv[ this.currentUVCoordinate ++ ] = u; - uv[ this.currentUVCoordinate ++ ] = 1; + probability = lightningStrike.subrayProbability; // Distribution test: probability *= segment.fraction0 > 0.5 && segment.fraction0 < 0.9 ? 1 / 0.4 : 0; - this.currentVertex += 3; + } -}; + if ( subray.recursion < lightningStrike.maxSubrayRecursion && lightningStrike.numSubrays < lightningStrike.maxSubrays && random1() < probability ) { -THREE.LightningStrike.prototype.createPrismFaces = function ( vertex/*, index*/ ) { + const childSubray = lightningStrike.addNewSubray(); + const parentSeed = lightningStrike.randomGenerator.getSeed(); + childSubray.seed = childSubraySeed; + lightningStrike.randomGenerator.setSeed( childSubraySeed ); + childSubray.recursion = subray.recursion + 1; + childSubray.maxIterations = Math.max( 1, subray.maxIterations - 1 ); + childSubray.linPos0.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); + childSubray.linPos1.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); + childSubray.up0.copy( subray.up0 ); + childSubray.up1.copy( subray.up1 ); + childSubray.radius0 = segment.radius0 * lightningStrike.rayParameters.radius0Factor; + childSubray.radius1 = Math.min( lightningStrike.rayParameters.minRadius, segment.radius1 * lightningStrike.rayParameters.radius1Factor ); + childSubray.birthTime = phase0 + currentCycle * period; + childSubray.deathTime = childSubray.birthTime + period * dutyCycle; - var indices = this.indices; - var vertex = this.currentVertex - 6; + if ( ! lightningStrike.rayParameters.isEternal && subray.recursion == 0 ) { - indices[ this.currentIndex ++ ] = vertex + 1; - indices[ this.currentIndex ++ ] = vertex + 2; - indices[ this.currentIndex ++ ] = vertex + 5; - indices[ this.currentIndex ++ ] = vertex + 1; - indices[ this.currentIndex ++ ] = vertex + 5; - indices[ this.currentIndex ++ ] = vertex + 4; - indices[ this.currentIndex ++ ] = vertex + 0; - indices[ this.currentIndex ++ ] = vertex + 1; - indices[ this.currentIndex ++ ] = vertex + 4; - indices[ this.currentIndex ++ ] = vertex + 0; - indices[ this.currentIndex ++ ] = vertex + 4; - indices[ this.currentIndex ++ ] = vertex + 3; - indices[ this.currentIndex ++ ] = vertex + 2; - indices[ this.currentIndex ++ ] = vertex + 0; - indices[ this.currentIndex ++ ] = vertex + 3; - indices[ this.currentIndex ++ ] = vertex + 2; - indices[ this.currentIndex ++ ] = vertex + 3; - indices[ this.currentIndex ++ ] = vertex + 5; + childSubray.birthTime = Math.max( childSubray.birthTime, subray.birthTime ); + childSubray.deathTime = Math.min( childSubray.deathTime, subray.deathTime ); -}; + } -THREE.LightningStrike.prototype.createDefaultSubrayCreationCallbacks = function () { + childSubray.timeScale = subray.timeScale * 2; + childSubray.roughness = subray.roughness; + childSubray.straightness = subray.straightness; + childSubray.propagationTimeFactor = subray.propagationTimeFactor; + childSubray.vanishingTimeFactor = subray.vanishingTimeFactor; + lightningStrike.onSubrayCreation( segment, subray, childSubray, lightningStrike ); + lightningStrike.randomGenerator.setSeed( parentSeed ); - var random1 = this.randomGenerator.random; + } - this.onDecideSubrayCreation = function ( segment, lightningStrike ) { + }; - // Decide subrays creation at parent (sub)ray segment + const vec1Pos = new THREE.Vector3(); + const vec2Forward = new THREE.Vector3(); + const vec3Side = new THREE.Vector3(); + const vec4Up = new THREE.Vector3(); - var subray = lightningStrike.currentSubray; + this.onSubrayCreation = function ( segment, parentSubray, childSubray, lightningStrike ) { - var period = lightningStrike.rayParameters.subrayPeriod; - var dutyCycle = lightningStrike.rayParameters.subrayDutyCycle; + // Decide childSubray origin and destination positions (pos0 and pos1) and possibly other properties of childSubray + // Just use the default cone position generator + lightningStrike.subrayCylinderPosition( segment, parentSubray, childSubray, 0.5, 0.6, 0.2 ); - var phase0 = ( lightningStrike.rayParameters.isEternal && subray.recursion == 0 ) ? - random1() * period : THREE.MathUtils.lerp( subray.birthTime, subray.endPropagationTime, segment.fraction0 ) - random1() * period; + }; - var phase = lightningStrike.time - phase0; - var currentCycle = Math.floor( phase / period ); + this.subrayConePosition = function ( segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor ) { - var childSubraySeed = random1() * ( currentCycle + 1 ); + // Sets childSubray pos0 and pos1 in a cone + childSubray.pos0.copy( segment.pos0 ); + vec1Pos.subVectors( parentSubray.pos1, parentSubray.pos0 ); + vec2Forward.copy( vec1Pos ).normalize(); + vec1Pos.multiplyScalar( segment.fraction0 + ( 1 - segment.fraction0 ) * ( random1() * heightFactor ) ); + const length = vec1Pos.length(); + vec3Side.crossVectors( parentSubray.up0, vec2Forward ); + const angle = 2 * Math.PI * random1(); + vec3Side.multiplyScalar( Math.cos( angle ) ); + vec4Up.copy( parentSubray.up0 ).multiplyScalar( Math.sin( angle ) ); + childSubray.pos1.copy( vec3Side ).add( vec4Up ).multiplyScalar( length * sideWidthFactor * ( minSideWidthFactor + random1() * ( 1 - minSideWidthFactor ) ) ).add( vec1Pos ).add( parentSubray.pos0 ); - var isActive = phase % period <= dutyCycle * period; + }; - var probability = 0; + this.subrayCylinderPosition = function ( segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor ) { - if ( isActive ) { + // Sets childSubray pos0 and pos1 in a cylinder + childSubray.pos0.copy( segment.pos0 ); + vec1Pos.subVectors( parentSubray.pos1, parentSubray.pos0 ); + vec2Forward.copy( vec1Pos ).normalize(); + vec1Pos.multiplyScalar( segment.fraction0 + ( 1 - segment.fraction0 ) * ( ( 2 * random1() - 1 ) * heightFactor ) ); + const length = vec1Pos.length(); + vec3Side.crossVectors( parentSubray.up0, vec2Forward ); + const angle = 2 * Math.PI * random1(); + vec3Side.multiplyScalar( Math.cos( angle ) ); + vec4Up.copy( parentSubray.up0 ).multiplyScalar( Math.sin( angle ) ); + childSubray.pos1.copy( vec3Side ).add( vec4Up ).multiplyScalar( length * sideWidthFactor * ( minSideWidthFactor + random1() * ( 1 - minSideWidthFactor ) ) ).add( vec1Pos ).add( parentSubray.pos0 ); - probability = lightningStrike.subrayProbability; - // Distribution test: probability *= segment.fraction0 > 0.5 && segment.fraction0 < 0.9 ? 1 / 0.4 : 0; + }; } - if ( subray.recursion < lightningStrike.maxSubrayRecursion && lightningStrike.numSubrays < lightningStrike.maxSubrays && random1() < probability ) { - - var childSubray = lightningStrike.addNewSubray(); - - var parentSeed = lightningStrike.randomGenerator.getSeed(); - childSubray.seed = childSubraySeed; - lightningStrike.randomGenerator.setSeed( childSubraySeed ); - - childSubray.recursion = subray.recursion + 1; - childSubray.maxIterations = Math.max( 1, subray.maxIterations - 1 ); - - childSubray.linPos0.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); - childSubray.linPos1.set( random1(), random1(), random1() ).multiplyScalar( 1000 ); - childSubray.up0.copy( subray.up0 ); - childSubray.up1.copy( subray.up1 ); - childSubray.radius0 = segment.radius0 * lightningStrike.rayParameters.radius0Factor; - childSubray.radius1 = Math.min( lightningStrike.rayParameters.minRadius, segment.radius1 * lightningStrike.rayParameters.radius1Factor ); - - childSubray.birthTime = phase0 + ( currentCycle ) * period; - childSubray.deathTime = childSubray.birthTime + period * dutyCycle; - - if ( ! lightningStrike.rayParameters.isEternal && subray.recursion == 0 ) { - - childSubray.birthTime = Math.max( childSubray.birthTime, subray.birthTime ); - childSubray.deathTime = Math.min( childSubray.deathTime, subray.deathTime ); - - } - - childSubray.timeScale = subray.timeScale * 2; - childSubray.roughness = subray.roughness; - childSubray.straightness = subray.straightness; - childSubray.propagationTimeFactor = subray.propagationTimeFactor; - childSubray.vanishingTimeFactor = subray.vanishingTimeFactor; - - lightningStrike.onSubrayCreation( segment, subray, childSubray, lightningStrike ); - - lightningStrike.randomGenerator.setSeed( parentSeed ); + createSubray() { + + return { + seed: 0, + maxIterations: 0, + recursion: 0, + pos0: new THREE.Vector3(), + pos1: new THREE.Vector3(), + linPos0: new THREE.Vector3(), + linPos1: new THREE.Vector3(), + up0: new THREE.Vector3(), + up1: new THREE.Vector3(), + radius0: 0, + radius1: 0, + birthTime: 0, + deathTime: 0, + timeScale: 0, + roughness: 0, + straightness: 0, + propagationTimeFactor: 0, + vanishingTimeFactor: 0, + endPropagationTime: 0, + beginVanishingTime: 0 + }; } - }; - - var vec1Pos = new THREE.Vector3(); - var vec2Forward = new THREE.Vector3(); - var vec3Side = new THREE.Vector3(); - var vec4Up = new THREE.Vector3(); - - this.onSubrayCreation = function ( segment, parentSubray, childSubray, lightningStrike ) { - - // Decide childSubray origin and destination positions (pos0 and pos1) and possibly other properties of childSubray - - // Just use the default cone position generator - lightningStrike.subrayCylinderPosition( segment, parentSubray, childSubray, 0.5, 0.6, 0.2 ); - - }; - - this.subrayConePosition = function ( segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor ) { - - // Sets childSubray pos0 and pos1 in a cone - - childSubray.pos0.copy( segment.pos0 ); - - vec1Pos.subVectors( parentSubray.pos1, parentSubray.pos0 ); - vec2Forward.copy( vec1Pos ).normalize(); - vec1Pos.multiplyScalar( segment.fraction0 + ( 1 - segment.fraction0 ) * ( random1() * heightFactor ) ); - var length = vec1Pos.length(); - vec3Side.crossVectors( parentSubray.up0, vec2Forward ); - var angle = 2 * Math.PI * random1(); - vec3Side.multiplyScalar( Math.cos( angle ) ); - vec4Up.copy( parentSubray.up0 ).multiplyScalar( Math.sin( angle ) ); + createSegment() { + + return { + iteration: 0, + pos0: new THREE.Vector3(), + pos1: new THREE.Vector3(), + linPos0: new THREE.Vector3(), + linPos1: new THREE.Vector3(), + up0: new THREE.Vector3(), + up1: new THREE.Vector3(), + radius0: 0, + radius1: 0, + fraction0: 0, + fraction1: 0, + positionVariationFactor: 0 + }; - childSubray.pos1.copy( vec3Side ).add( vec4Up ).multiplyScalar( length * sideWidthFactor * ( minSideWidthFactor + random1() * ( 1 - minSideWidthFactor ) ) ).add( vec1Pos ).add( parentSubray.pos0 ); - - }; - - this.subrayCylinderPosition = function ( segment, parentSubray, childSubray, heightFactor, sideWidthFactor, minSideWidthFactor ) { - - // Sets childSubray pos0 and pos1 in a cylinder - - childSubray.pos0.copy( segment.pos0 ); - - vec1Pos.subVectors( parentSubray.pos1, parentSubray.pos0 ); - vec2Forward.copy( vec1Pos ).normalize(); - vec1Pos.multiplyScalar( segment.fraction0 + ( 1 - segment.fraction0 ) * ( ( 2 * random1() - 1 ) * heightFactor ) ); - var length = vec1Pos.length(); - vec3Side.crossVectors( parentSubray.up0, vec2Forward ); - var angle = 2 * Math.PI * random1(); - vec3Side.multiplyScalar( Math.cos( angle ) ); - vec4Up.copy( parentSubray.up0 ).multiplyScalar( Math.sin( angle ) ); - - childSubray.pos1.copy( vec3Side ).add( vec4Up ).multiplyScalar( length * sideWidthFactor * ( minSideWidthFactor + random1() * ( 1 - minSideWidthFactor ) ) ).add( vec1Pos ).add( parentSubray.pos0 ); - - }; - -}; - -THREE.LightningStrike.prototype.createSubray = function () { - - return { - - seed: 0, - maxIterations: 0, - recursion: 0, - pos0: new THREE.Vector3(), - pos1: new THREE.Vector3(), - linPos0: new THREE.Vector3(), - linPos1: new THREE.Vector3(), - up0: new THREE.Vector3(), - up1: new THREE.Vector3(), - radius0: 0, - radius1: 0, - birthTime: 0, - deathTime: 0, - timeScale: 0, - roughness: 0, - straightness: 0, - propagationTimeFactor: 0, - vanishingTimeFactor: 0, - endPropagationTime: 0, - beginVanishingTime: 0 - - }; - -}; + } -THREE.LightningStrike.prototype.createSegment = function () { + getNewSegment() { - return { - iteration: 0, - pos0: new THREE.Vector3(), - pos1: new THREE.Vector3(), - linPos0: new THREE.Vector3(), - linPos1: new THREE.Vector3(), - up0: new THREE.Vector3(), - up1: new THREE.Vector3(), - radius0: 0, - radius1: 0, - fraction0: 0, - fraction1: 0, - positionVariationFactor: 0 - }; + return this.raySegments[ this.currentSegmentIndex ++ ]; -}; + } -THREE.LightningStrike.prototype.getNewSegment = function () { + copy( source ) { - return this.raySegments[ this.currentSegmentIndex ++ ]; + super.copy( source ); + this.init( LightningStrike.copyParameters( {}, source.rayParameters ) ); + return this; -}; + } -THREE.LightningStrike.prototype.copy = function ( source ) { + clone() { - THREE.BufferGeometry.prototype.copy.call( this, source ); + return new this.constructor( LightningStrike.copyParameters( {}, this.rayParameters ) ); - this.init( THREE.LightningStrike.copyParameters( {}, source.rayParameters ) ); + } - return this; + } -}; + LightningStrike.prototype.isLightningStrike = true; // Ray states -THREE.LightningStrike.prototype.clone = function () { + LightningStrike.RAY_INITIALIZED = 0; + LightningStrike.RAY_UNBORN = 1; + LightningStrike.RAY_PROPAGATING = 2; + LightningStrike.RAY_STEADY = 3; + LightningStrike.RAY_VANISHING = 4; + LightningStrike.RAY_EXTINGUISHED = 5; + LightningStrike.COS30DEG = Math.cos( 30 * Math.PI / 180 ); + LightningStrike.SIN30DEG = Math.sin( 30 * Math.PI / 180 ); - return new this.constructor( THREE.LightningStrike.copyParameters( {}, this.rayParameters ) ); + THREE.LightningStrike = LightningStrike; -}; +} )(); diff --git a/examples/js/geometries/ParametricGeometries.js b/examples/js/geometries/ParametricGeometries.js index 2bbf854068c614..7a06f416917b5f 100644 --- a/examples/js/geometries/ParametricGeometries.js +++ b/examples/js/geometries/ParametricGeometries.js @@ -1,252 +1,215 @@ -/** +( function () { + + /** * Experimenting of primitive geometry creation using Surface Parametric equations */ -THREE.ParametricGeometries = { - - klein: function ( v, u, target ) { - - u *= Math.PI; - v *= 2 * Math.PI; - - u = u * 2; - var x, y, z; - if ( u < Math.PI ) { - - x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( u ) * Math.cos( v ); - z = - 8 * Math.sin( u ) - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( u ) * Math.cos( v ); - - } else { - - x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( v + Math.PI ); - z = - 8 * Math.sin( u ); + const ParametricGeometries = { + klein: function ( v, u, target ) { - } - - y = - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( v ); + u *= Math.PI; + v *= 2 * Math.PI; + u = u * 2; + let x, z; - target.set( x, y, z ); + if ( u < Math.PI ) { - }, + x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + 2 * ( 1 - Math.cos( u ) / 2 ) * Math.cos( u ) * Math.cos( v ); + z = - 8 * Math.sin( u ) - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( u ) * Math.cos( v ); - plane: function ( width, height ) { + } else { - return function ( u, v, target ) { + x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + 2 * ( 1 - Math.cos( u ) / 2 ) * Math.cos( v + Math.PI ); + z = - 8 * Math.sin( u ); - var x = u * width; - var y = 0; - var z = v * height; + } + const y = - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( v ); target.set( x, y, z ); - }; - - }, - - mobius: function ( u, t, target ) { - - // flat mobius strip - // http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations- - u = u - 0.5; - var v = 2 * Math.PI * t; - - var x, y, z; - - var a = 2; + }, + plane: function ( width, height ) { - x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) ); - y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) ); - z = u * Math.sin( v / 2 ); + return function ( u, v, target ) { - target.set( x, y, z ); + const x = u * width; + const y = 0; + const z = v * height; + target.set( x, y, z ); - }, + }; - mobius3d: function ( u, t, target ) { + }, + mobius: function ( u, t, target ) { - // volumetric mobius strip - - u *= Math.PI; - t *= 2 * Math.PI; - - u = u * 2; - var phi = u / 2; - var major = 2.25, a = 0.125, b = 0.65; - - var x, y, z; - - x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi ); - z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi ); - y = ( major + x ) * Math.sin( u ); - x = ( major + x ) * Math.cos( u ); - - target.set( x, y, z ); - - } - -}; + // flat mobius strip + // http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations- + u = u - 0.5; + const v = 2 * Math.PI * t; + const a = 2; + const x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) ); + const y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) ); + const z = u * Math.sin( v / 2 ); + target.set( x, y, z ); + }, + mobius3d: function ( u, t, target ) { + + // volumetric mobius strip + u *= Math.PI; + t *= 2 * Math.PI; + u = u * 2; + const phi = u / 2; + const major = 2.25, + a = 0.125, + b = 0.65; + let x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi ); + const z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi ); + const y = ( major + x ) * Math.sin( u ); + x = ( major + x ) * Math.cos( u ); + target.set( x, y, z ); -/********************************************* + } + }; + /********************************************* * * Parametric Replacement for TubeGeometry * *********************************************/ -THREE.ParametricGeometries.TubeGeometry = function ( path, segments, radius, segmentsRadius, closed ) { - - this.path = path; - this.segments = segments || 64; - this.radius = radius || 1; - this.segmentsRadius = segmentsRadius || 8; - this.closed = closed || false; - - var scope = this, numpoints = this.segments + 1; + ParametricGeometries.TubeGeometry = class TubeGeometry extends THREE.ParametricGeometry { - var frames = path.computeFrenetFrames( segments, closed ), - tangents = frames.tangents, - normals = frames.normals, - binormals = frames.binormals; + constructor( path, segments = 64, radius = 1, segmentsRadius = 8, closed = false ) { - // proxy internals + const numpoints = segments + 1; + const frames = path.computeFrenetFrames( segments, closed ), + tangents = frames.tangents, + normals = frames.normals, + binormals = frames.binormals; + const position = new THREE.Vector3(); - this.tangents = tangents; - this.normals = normals; - this.binormals = binormals; + function ParametricTube( u, v, target ) { - var position = new THREE.Vector3(); + v *= 2 * Math.PI; + const i = Math.floor( u * ( numpoints - 1 ) ); + path.getPointAt( u, position ); + const normal = normals[ i ]; + const binormal = binormals[ i ]; + const cx = - radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. - var ParametricTube = function ( u, v, target ) { + const cy = radius * Math.sin( v ); + position.x += cx * normal.x + cy * binormal.x; + position.y += cx * normal.y + cy * binormal.y; + position.z += cx * normal.z + cy * binormal.z; + target.copy( position ); - v *= 2 * Math.PI; + } - var i = u * ( numpoints - 1 ); - i = Math.floor( i ); + super( ParametricTube, segments, segmentsRadius ); // proxy internals - path.getPointAt( u, position ); + this.tangents = tangents; + this.normals = normals; + this.binormals = binormals; + this.path = path; + this.segments = segments; + this.radius = radius; + this.segmentsRadius = segmentsRadius; + this.closed = closed; - var normal = normals[ i ]; - var binormal = binormals[ i ]; - - var cx = - scope.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside. - var cy = scope.radius * Math.sin( v ); - - position.x += cx * normal.x + cy * binormal.x; - position.y += cx * normal.y + cy * binormal.y; - position.z += cx * normal.z + cy * binormal.z; - - target.copy( position ); + } }; - - THREE.ParametricGeometry.call( this, ParametricTube, segments, segmentsRadius ); - -}; - -THREE.ParametricGeometries.TubeGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.ParametricGeometries.TubeGeometry.prototype.constructor = THREE.ParametricGeometries.TubeGeometry; - - -/********************************************* + /********************************************* * * Parametric Replacement for TorusKnotGeometry * *********************************************/ -THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segmentsT, segmentsR, p, q ) { - - this.radius = radius || 200; - this.tube = tube || 40; - this.segmentsT = segmentsT || 64; - this.segmentsR = segmentsR || 8; - this.p = p || 2; - this.q = q || 3; - function TorusKnotCurve() { + ParametricGeometries.TorusKnotGeometry = class TorusKnotGeometry extends ParametricGeometries.TubeGeometry { - THREE.Curve.call( this ); + constructor( radius = 200, tube = 40, segmentsT = 64, segmentsR = 8, p = 2, q = 3 ) { - } + class TorusKnotCurve extends THREE.Curve { - TorusKnotCurve.prototype = Object.create( THREE.Curve.prototype ); - TorusKnotCurve.prototype.constructor = TorusKnotCurve; + getPoint( t, optionalTarget = new THREE.Vector3() ) { - TorusKnotCurve.prototype.getPoint = function ( t, optionalTarget ) { + const point = optionalTarget; + t *= Math.PI * 2; + const r = 0.5; + const x = ( 1 + r * Math.cos( q * t ) ) * Math.cos( p * t ); + const y = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t ); + const z = r * Math.sin( q * t ); + return point.set( x, y, z ).multiplyScalar( radius ); - var point = optionalTarget || new THREE.Vector3(); + } - t *= Math.PI * 2; + } - var r = 0.5; + const segments = segmentsT; + const radiusSegments = segmentsR; + const extrudePath = new TorusKnotCurve(); + super( extrudePath, segments, tube, radiusSegments, true, false ); + this.radius = radius; + this.tube = tube; + this.segmentsT = segmentsT; + this.segmentsR = segmentsR; + this.p = p; + this.q = q; - var x = ( 1 + r * Math.cos( q * t ) ) * Math.cos( p * t ); - var y = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t ); - var z = r * Math.sin( q * t ); - - return point.set( x, y, z ).multiplyScalar( radius ); + } }; - - var segments = segmentsT; - var radiusSegments = segmentsR; - var extrudePath = new TorusKnotCurve(); - - THREE.ParametricGeometries.TubeGeometry.call( this, extrudePath, segments, tube, radiusSegments, true, false ); - -}; - -THREE.ParametricGeometries.TorusKnotGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.ParametricGeometries.TorusKnotGeometry.prototype.constructor = THREE.ParametricGeometries.TorusKnotGeometry; - - -/********************************************* + /********************************************* * * Parametric Replacement for SphereGeometry * *********************************************/ -THREE.ParametricGeometries.SphereGeometry = function ( size, u, v ) { - - function sphere( u, v, target ) { - - u *= Math.PI; - v *= 2 * Math.PI; - var x = size * Math.sin( u ) * Math.cos( v ); - var y = size * Math.sin( u ) * Math.sin( v ); - var z = size * Math.cos( u ); + ParametricGeometries.SphereGeometry = class SphereGeometry extends THREE.ParametricGeometry { - target.set( x, y, z ); + constructor( size, u, v ) { - } + function sphere( u, v, target ) { - THREE.ParametricGeometry.call( this, sphere, u, v ); + u *= Math.PI; + v *= 2 * Math.PI; + var x = size * Math.sin( u ) * Math.cos( v ); + var y = size * Math.sin( u ) * Math.sin( v ); + var z = size * Math.cos( u ); + target.set( x, y, z ); -}; + } -THREE.ParametricGeometries.SphereGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.ParametricGeometries.SphereGeometry.prototype.constructor = THREE.ParametricGeometries.SphereGeometry; + super( sphere, u, v ); + } -/********************************************* + }; + /********************************************* * * Parametric Replacement for PlaneGeometry * *********************************************/ -THREE.ParametricGeometries.PlaneGeometry = function ( width, depth, segmentsWidth, segmentsDepth ) { + ParametricGeometries.PlaneGeometry = class PlaneGeometry extends THREE.ParametricGeometry { + + constructor( width, depth, segmentsWidth, segmentsDepth ) { - function plane( u, v, target ) { + function plane( u, v, target ) { - var x = u * width; - var y = 0; - var z = v * depth; + const x = u * width; + const y = 0; + const z = v * depth; + target.set( x, y, z ); - target.set( x, y, z ); + } - } + super( plane, segmentsWidth, segmentsDepth ); - THREE.ParametricGeometry.call( this, plane, segmentsWidth, segmentsDepth ); + } + + }; -}; + THREE.ParametricGeometries = ParametricGeometries; -THREE.ParametricGeometries.PlaneGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.ParametricGeometries.PlaneGeometry.prototype.constructor = THREE.ParametricGeometries.PlaneGeometry; +} )(); diff --git a/examples/js/geometries/RoundedBoxGeometry.js b/examples/js/geometries/RoundedBoxGeometry.js new file mode 100644 index 00000000000000..883cea47bc0041 --- /dev/null +++ b/examples/js/geometries/RoundedBoxGeometry.js @@ -0,0 +1,140 @@ +( function () { + + const _tempNormal = new THREE.Vector3(); + + function getUv( faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength ) { + + const totArcLength = 2 * Math.PI * radius / 4; // length of the planes between the arcs on each axis + + const centerLength = Math.max( sideLength - 2 * radius, 0 ); + const halfArc = Math.PI / 4; // Get the vector projected onto the Y plane + + _tempNormal.copy( normal ); + + _tempNormal[ projectionAxis ] = 0; + + _tempNormal.normalize(); // total amount of UV space alloted to a single arc + + + const arcUvRatio = 0.5 * totArcLength / ( totArcLength + centerLength ); // the distance along one arc the point is at + + const arcAngleRatio = 1.0 - _tempNormal.angleTo( faceDirVector ) / halfArc; + + if ( Math.sign( _tempNormal[ uvAxis ] ) === 1 ) { + + return arcAngleRatio * arcUvRatio; + + } else { + + // total amount of UV space alloted to the plane between the arcs + const lenUv = centerLength / ( totArcLength + centerLength ); + return lenUv + arcUvRatio + arcUvRatio * ( 1.0 - arcAngleRatio ); + + } + + } + + class RoundedBoxGeometry extends THREE.BoxGeometry { + + constructor( width = 1, height = 1, depth = 1, segments = 2, radius = 0.1 ) { + + // ensure segments is odd so we have a plane connecting the rounded corners + segments = segments * 2 + 1; // ensure radius isn't bigger than shortest side + + radius = Math.min( width / 2, height / 2, depth / 2, radius ); + super( 1, 1, 1, segments, segments, segments ); // if we just have one segment we're the same as a regular box + + if ( segments === 1 ) return; + const geometry2 = this.toNonIndexed(); + this.index = null; + this.attributes.position = geometry2.attributes.position; + this.attributes.normal = geometry2.attributes.normal; + this.attributes.uv = geometry2.attributes.uv; // + + const position = new THREE.Vector3(); + const normal = new THREE.Vector3(); + const box = new THREE.Vector3( width, height, depth ).divideScalar( 2 ).subScalar( radius ); + const positions = this.attributes.position.array; + const normals = this.attributes.normal.array; + const uvs = this.attributes.uv.array; + const faceTris = positions.length / 6; + const faceDirVector = new THREE.Vector3(); + const halfSegmentSize = 0.5 / segments; + + for ( let i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { + + position.fromArray( positions, i ); + normal.copy( position ); + normal.x -= Math.sign( normal.x ) * halfSegmentSize; + normal.y -= Math.sign( normal.y ) * halfSegmentSize; + normal.z -= Math.sign( normal.z ) * halfSegmentSize; + normal.normalize(); + positions[ i + 0 ] = box.x * Math.sign( position.x ) + normal.x * radius; + positions[ i + 1 ] = box.y * Math.sign( position.y ) + normal.y * radius; + positions[ i + 2 ] = box.z * Math.sign( position.z ) + normal.z * radius; + normals[ i + 0 ] = normal.x; + normals[ i + 1 ] = normal.y; + normals[ i + 2 ] = normal.z; + const side = Math.floor( i / faceTris ); + + switch ( side ) { + + case 0: + // right + // generate UVs along Z then Y + faceDirVector.set( 1, 0, 0 ); + uvs[ j + 0 ] = getUv( faceDirVector, normal, 'z', 'y', radius, depth ); + uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'z', radius, height ); + break; + + case 1: + // left + // generate UVs along Z then Y + faceDirVector.set( - 1, 0, 0 ); + uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'z', 'y', radius, depth ); + uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'z', radius, height ); + break; + + case 2: + // top + // generate UVs along X then Z + faceDirVector.set( 0, 1, 0 ); + uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'z', radius, width ); + uvs[ j + 1 ] = getUv( faceDirVector, normal, 'z', 'x', radius, depth ); + break; + + case 3: + // bottom + // generate UVs along X then Z + faceDirVector.set( 0, - 1, 0 ); + uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'z', radius, width ); + uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'z', 'x', radius, depth ); + break; + + case 4: + // front + // generate UVs along X then Y + faceDirVector.set( 0, 0, 1 ); + uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'y', radius, width ); + uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'x', radius, height ); + break; + + case 5: + // back + // generate UVs along X then Y + faceDirVector.set( 0, 0, - 1 ); + uvs[ j + 0 ] = getUv( faceDirVector, normal, 'x', 'y', radius, width ); + uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'x', radius, height ); + break; + + } + + } + + } + + } + + THREE.RoundedBoxGeometry = RoundedBoxGeometry; + +} )(); diff --git a/examples/js/geometries/TeapotGeometry.js b/examples/js/geometries/TeapotGeometry.js index c2de503bdc7009..05c7d6598a6c2f 100644 --- a/examples/js/geometries/TeapotGeometry.js +++ b/examples/js/geometries/TeapotGeometry.js @@ -1,4 +1,6 @@ -/** +( function () { + + /** * Tessellates the famous Utah teapot database by Martin Newell into triangles. * * Parameters: size = 50, segments = 10, bottom = true, lid = true, body = true, @@ -47,668 +49,284 @@ * */ -THREE.TeapotGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn ) { - - // 32 * 4 * 4 Bezier spline patches - var teapotPatches = [ - /*rim*/ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 3, 16, 17, 18, 7, 19, 20, 21, 11, 22, 23, 24, 15, 25, 26, 27, - 18, 28, 29, 30, 21, 31, 32, 33, 24, 34, 35, 36, 27, 37, 38, 39, - 30, 40, 41, 0, 33, 42, 43, 4, 36, 44, 45, 8, 39, 46, 47, 12, - /*body*/ - 12, 13, 14, 15, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 15, 25, 26, 27, 51, 60, 61, 62, 55, 63, 64, 65, 59, 66, 67, 68, - 27, 37, 38, 39, 62, 69, 70, 71, 65, 72, 73, 74, 68, 75, 76, 77, - 39, 46, 47, 12, 71, 78, 79, 48, 74, 80, 81, 52, 77, 82, 83, 56, - 56, 57, 58, 59, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 59, 66, 67, 68, 87, 96, 97, 98, 91, 99, 100, 101, 95, 102, 103, 104, - 68, 75, 76, 77, 98, 105, 106, 107, 101, 108, 109, 110, 104, 111, 112, 113, - 77, 82, 83, 56, 107, 114, 115, 84, 110, 116, 117, 88, 113, 118, 119, 92, - /*handle*/ - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 123, 136, 137, 120, 127, 138, 139, 124, 131, 140, 141, 128, 135, 142, 143, 132, - 132, 133, 134, 135, 144, 145, 146, 147, 148, 149, 150, 151, 68, 152, 153, 154, - 135, 142, 143, 132, 147, 155, 156, 144, 151, 157, 158, 148, 154, 159, 160, 68, - /*spout*/ - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 164, 177, 178, 161, 168, 179, 180, 165, 172, 181, 182, 169, 176, 183, 184, 173, - 173, 174, 175, 176, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 176, 183, 184, 173, 188, 197, 198, 185, 192, 199, 200, 189, 196, 201, 202, 193, - /*lid*/ - 203, 203, 203, 203, 204, 205, 206, 207, 208, 208, 208, 208, 209, 210, 211, 212, - 203, 203, 203, 203, 207, 213, 214, 215, 208, 208, 208, 208, 212, 216, 217, 218, - 203, 203, 203, 203, 215, 219, 220, 221, 208, 208, 208, 208, 218, 222, 223, 224, - 203, 203, 203, 203, 221, 225, 226, 204, 208, 208, 208, 208, 224, 227, 228, 209, - 209, 210, 211, 212, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, - 212, 216, 217, 218, 232, 241, 242, 243, 236, 244, 245, 246, 240, 247, 248, 249, - 218, 222, 223, 224, 243, 250, 251, 252, 246, 253, 254, 255, 249, 256, 257, 258, - 224, 227, 228, 209, 252, 259, 260, 229, 255, 261, 262, 233, 258, 263, 264, 237, - /*bottom*/ - 265, 265, 265, 265, 266, 267, 268, 269, 270, 271, 272, 273, 92, 119, 118, 113, - 265, 265, 265, 265, 269, 274, 275, 276, 273, 277, 278, 279, 113, 112, 111, 104, - 265, 265, 265, 265, 276, 280, 281, 282, 279, 283, 284, 285, 104, 103, 102, 95, - 265, 265, 265, 265, 282, 286, 287, 266, 285, 288, 289, 270, 95, 94, 93, 92 - ]; - - var teapotVertices = [ - 1.4, 0, 2.4, - 1.4, - 0.784, 2.4, - 0.784, - 1.4, 2.4, - 0, - 1.4, 2.4, - 1.3375, 0, 2.53125, - 1.3375, - 0.749, 2.53125, - 0.749, - 1.3375, 2.53125, - 0, - 1.3375, 2.53125, - 1.4375, 0, 2.53125, - 1.4375, - 0.805, 2.53125, - 0.805, - 1.4375, 2.53125, - 0, - 1.4375, 2.53125, - 1.5, 0, 2.4, - 1.5, - 0.84, 2.4, - 0.84, - 1.5, 2.4, - 0, - 1.5, 2.4, - - 0.784, - 1.4, 2.4, - - 1.4, - 0.784, 2.4, - - 1.4, 0, 2.4, - - 0.749, - 1.3375, 2.53125, - - 1.3375, - 0.749, 2.53125, - - 1.3375, 0, 2.53125, - - 0.805, - 1.4375, 2.53125, - - 1.4375, - 0.805, 2.53125, - - 1.4375, 0, 2.53125, - - 0.84, - 1.5, 2.4, - - 1.5, - 0.84, 2.4, - - 1.5, 0, 2.4, - - 1.4, 0.784, 2.4, - - 0.784, 1.4, 2.4, - 0, 1.4, 2.4, - - 1.3375, 0.749, 2.53125, - - 0.749, 1.3375, 2.53125, - 0, 1.3375, 2.53125, - - 1.4375, 0.805, 2.53125, - - 0.805, 1.4375, 2.53125, - 0, 1.4375, 2.53125, - - 1.5, 0.84, 2.4, - - 0.84, 1.5, 2.4, - 0, 1.5, 2.4, - 0.784, 1.4, 2.4, - 1.4, 0.784, 2.4, - 0.749, 1.3375, 2.53125, - 1.3375, 0.749, 2.53125, - 0.805, 1.4375, 2.53125, - 1.4375, 0.805, 2.53125, - 0.84, 1.5, 2.4, - 1.5, 0.84, 2.4, - 1.75, 0, 1.875, - 1.75, - 0.98, 1.875, - 0.98, - 1.75, 1.875, - 0, - 1.75, 1.875, - 2, 0, 1.35, - 2, - 1.12, 1.35, - 1.12, - 2, 1.35, - 0, - 2, 1.35, - 2, 0, 0.9, - 2, - 1.12, 0.9, - 1.12, - 2, 0.9, - 0, - 2, 0.9, - - 0.98, - 1.75, 1.875, - - 1.75, - 0.98, 1.875, - - 1.75, 0, 1.875, - - 1.12, - 2, 1.35, - - 2, - 1.12, 1.35, - - 2, 0, 1.35, - - 1.12, - 2, 0.9, - - 2, - 1.12, 0.9, - - 2, 0, 0.9, - - 1.75, 0.98, 1.875, - - 0.98, 1.75, 1.875, - 0, 1.75, 1.875, - - 2, 1.12, 1.35, - - 1.12, 2, 1.35, - 0, 2, 1.35, - - 2, 1.12, 0.9, - - 1.12, 2, 0.9, - 0, 2, 0.9, - 0.98, 1.75, 1.875, - 1.75, 0.98, 1.875, - 1.12, 2, 1.35, - 2, 1.12, 1.35, - 1.12, 2, 0.9, - 2, 1.12, 0.9, - 2, 0, 0.45, - 2, - 1.12, 0.45, - 1.12, - 2, 0.45, - 0, - 2, 0.45, - 1.5, 0, 0.225, - 1.5, - 0.84, 0.225, - 0.84, - 1.5, 0.225, - 0, - 1.5, 0.225, - 1.5, 0, 0.15, - 1.5, - 0.84, 0.15, - 0.84, - 1.5, 0.15, - 0, - 1.5, 0.15, - - 1.12, - 2, 0.45, - - 2, - 1.12, 0.45, - - 2, 0, 0.45, - - 0.84, - 1.5, 0.225, - - 1.5, - 0.84, 0.225, - - 1.5, 0, 0.225, - - 0.84, - 1.5, 0.15, - - 1.5, - 0.84, 0.15, - - 1.5, 0, 0.15, - - 2, 1.12, 0.45, - - 1.12, 2, 0.45, - 0, 2, 0.45, - - 1.5, 0.84, 0.225, - - 0.84, 1.5, 0.225, - 0, 1.5, 0.225, - - 1.5, 0.84, 0.15, - - 0.84, 1.5, 0.15, - 0, 1.5, 0.15, - 1.12, 2, 0.45, - 2, 1.12, 0.45, - 0.84, 1.5, 0.225, - 1.5, 0.84, 0.225, - 0.84, 1.5, 0.15, - 1.5, 0.84, 0.15, - - 1.6, 0, 2.025, - - 1.6, - 0.3, 2.025, - - 1.5, - 0.3, 2.25, - - 1.5, 0, 2.25, - - 2.3, 0, 2.025, - - 2.3, - 0.3, 2.025, - - 2.5, - 0.3, 2.25, - - 2.5, 0, 2.25, - - 2.7, 0, 2.025, - - 2.7, - 0.3, 2.025, - - 3, - 0.3, 2.25, - - 3, 0, 2.25, - - 2.7, 0, 1.8, - - 2.7, - 0.3, 1.8, - - 3, - 0.3, 1.8, - - 3, 0, 1.8, - - 1.5, 0.3, 2.25, - - 1.6, 0.3, 2.025, - - 2.5, 0.3, 2.25, - - 2.3, 0.3, 2.025, - - 3, 0.3, 2.25, - - 2.7, 0.3, 2.025, - - 3, 0.3, 1.8, - - 2.7, 0.3, 1.8, - - 2.7, 0, 1.575, - - 2.7, - 0.3, 1.575, - - 3, - 0.3, 1.35, - - 3, 0, 1.35, - - 2.5, 0, 1.125, - - 2.5, - 0.3, 1.125, - - 2.65, - 0.3, 0.9375, - - 2.65, 0, 0.9375, - - 2, - 0.3, 0.9, - - 1.9, - 0.3, 0.6, - - 1.9, 0, 0.6, - - 3, 0.3, 1.35, - - 2.7, 0.3, 1.575, - - 2.65, 0.3, 0.9375, - - 2.5, 0.3, 1.125, - - 1.9, 0.3, 0.6, - - 2, 0.3, 0.9, - 1.7, 0, 1.425, - 1.7, - 0.66, 1.425, - 1.7, - 0.66, 0.6, - 1.7, 0, 0.6, - 2.6, 0, 1.425, - 2.6, - 0.66, 1.425, - 3.1, - 0.66, 0.825, - 3.1, 0, 0.825, - 2.3, 0, 2.1, - 2.3, - 0.25, 2.1, - 2.4, - 0.25, 2.025, - 2.4, 0, 2.025, - 2.7, 0, 2.4, - 2.7, - 0.25, 2.4, - 3.3, - 0.25, 2.4, - 3.3, 0, 2.4, - 1.7, 0.66, 0.6, - 1.7, 0.66, 1.425, - 3.1, 0.66, 0.825, - 2.6, 0.66, 1.425, - 2.4, 0.25, 2.025, - 2.3, 0.25, 2.1, - 3.3, 0.25, 2.4, - 2.7, 0.25, 2.4, - 2.8, 0, 2.475, - 2.8, - 0.25, 2.475, - 3.525, - 0.25, 2.49375, - 3.525, 0, 2.49375, - 2.9, 0, 2.475, - 2.9, - 0.15, 2.475, - 3.45, - 0.15, 2.5125, - 3.45, 0, 2.5125, - 2.8, 0, 2.4, - 2.8, - 0.15, 2.4, - 3.2, - 0.15, 2.4, - 3.2, 0, 2.4, - 3.525, 0.25, 2.49375, - 2.8, 0.25, 2.475, - 3.45, 0.15, 2.5125, - 2.9, 0.15, 2.475, - 3.2, 0.15, 2.4, - 2.8, 0.15, 2.4, - 0, 0, 3.15, - 0.8, 0, 3.15, - 0.8, - 0.45, 3.15, - 0.45, - 0.8, 3.15, - 0, - 0.8, 3.15, - 0, 0, 2.85, - 0.2, 0, 2.7, - 0.2, - 0.112, 2.7, - 0.112, - 0.2, 2.7, - 0, - 0.2, 2.7, - - 0.45, - 0.8, 3.15, - - 0.8, - 0.45, 3.15, - - 0.8, 0, 3.15, - - 0.112, - 0.2, 2.7, - - 0.2, - 0.112, 2.7, - - 0.2, 0, 2.7, - - 0.8, 0.45, 3.15, - - 0.45, 0.8, 3.15, - 0, 0.8, 3.15, - - 0.2, 0.112, 2.7, - - 0.112, 0.2, 2.7, - 0, 0.2, 2.7, - 0.45, 0.8, 3.15, - 0.8, 0.45, 3.15, - 0.112, 0.2, 2.7, - 0.2, 0.112, 2.7, - 0.4, 0, 2.55, - 0.4, - 0.224, 2.55, - 0.224, - 0.4, 2.55, - 0, - 0.4, 2.55, - 1.3, 0, 2.55, - 1.3, - 0.728, 2.55, - 0.728, - 1.3, 2.55, - 0, - 1.3, 2.55, - 1.3, 0, 2.4, - 1.3, - 0.728, 2.4, - 0.728, - 1.3, 2.4, - 0, - 1.3, 2.4, - - 0.224, - 0.4, 2.55, - - 0.4, - 0.224, 2.55, - - 0.4, 0, 2.55, - - 0.728, - 1.3, 2.55, - - 1.3, - 0.728, 2.55, - - 1.3, 0, 2.55, - - 0.728, - 1.3, 2.4, - - 1.3, - 0.728, 2.4, - - 1.3, 0, 2.4, - - 0.4, 0.224, 2.55, - - 0.224, 0.4, 2.55, - 0, 0.4, 2.55, - - 1.3, 0.728, 2.55, - - 0.728, 1.3, 2.55, - 0, 1.3, 2.55, - - 1.3, 0.728, 2.4, - - 0.728, 1.3, 2.4, - 0, 1.3, 2.4, - 0.224, 0.4, 2.55, - 0.4, 0.224, 2.55, - 0.728, 1.3, 2.55, - 1.3, 0.728, 2.55, - 0.728, 1.3, 2.4, - 1.3, 0.728, 2.4, - 0, 0, 0, - 1.425, 0, 0, - 1.425, 0.798, 0, - 0.798, 1.425, 0, - 0, 1.425, 0, - 1.5, 0, 0.075, - 1.5, 0.84, 0.075, - 0.84, 1.5, 0.075, - 0, 1.5, 0.075, - - 0.798, 1.425, 0, - - 1.425, 0.798, 0, - - 1.425, 0, 0, - - 0.84, 1.5, 0.075, - - 1.5, 0.84, 0.075, - - 1.5, 0, 0.075, - - 1.425, - 0.798, 0, - - 0.798, - 1.425, 0, - 0, - 1.425, 0, - - 1.5, - 0.84, 0.075, - - 0.84, - 1.5, 0.075, - 0, - 1.5, 0.075, - 0.798, - 1.425, 0, - 1.425, - 0.798, 0, - 0.84, - 1.5, 0.075, - 1.5, - 0.84, 0.075 - ]; - - THREE.BufferGeometry.call( this ); - - size = size || 50; - - // number of segments per patch - segments = segments !== undefined ? Math.max( 2, Math.floor( segments ) || 10 ) : 10; - - // which parts should be visible - bottom = bottom === undefined ? true : bottom; - lid = lid === undefined ? true : lid; - body = body === undefined ? true : body; - - // Should the lid be snug? It's not traditional, but we make it snug by default - fitLid = fitLid === undefined ? true : fitLid; - - // Jim Blinn scaled the teapot down in size by about 1.3 for - // some rendering tests. He liked the new proportions that he kept - // the data in this form. The model was distributed with these new - // proportions and became the norm. Trivia: comparing images of the - // real teapot and the computer model, the ratio for the bowl of the - // real teapot is more like 1.25, but since 1.3 is the traditional - // value given, we use it here. - var blinnScale = 1.3; - blinn = blinn === undefined ? true : blinn; - - // scale the size to be the real scaling factor - var maxHeight = 3.15 * ( blinn ? 1 : blinnScale ); - - var maxHeight2 = maxHeight / 2; - var trueSize = size / maxHeight2; - - // Number of elements depends on what is needed. Subtract degenerate - // triangles at tip of bottom and lid out in advance. - var numTriangles = bottom ? ( 8 * segments - 4 ) * segments : 0; - numTriangles += lid ? ( 16 * segments - 4 ) * segments : 0; - numTriangles += body ? 40 * segments * segments : 0; - - var indices = new Uint32Array( numTriangles * 3 ); - - var numVertices = bottom ? 4 : 0; - numVertices += lid ? 8 : 0; - numVertices += body ? 20 : 0; - numVertices *= ( segments + 1 ) * ( segments + 1 ); - - var vertices = new Float32Array( numVertices * 3 ); - var normals = new Float32Array( numVertices * 3 ); - var uvs = new Float32Array( numVertices * 2 ); - - // Bezier form - var ms = new THREE.Matrix4(); - ms.set( - - 1.0, 3.0, - 3.0, 1.0, - 3.0, - 6.0, 3.0, 0.0, - - 3.0, 3.0, 0.0, 0.0, - 1.0, 0.0, 0.0, 0.0 ); - - var g = []; - var i, r, c; - - var sp = []; - var tp = []; - var dsp = []; - var dtp = []; - - // M * G * M matrix, sort of see - // http://www.cs.helsinki.fi/group/goa/mallinnus/curves/surfaces.html - var mgm = []; - - var vert = []; - var sdir = []; - var tdir = []; - - var norm = new THREE.Vector3(); - - var tcoord; - - var sstep, tstep; - var vertPerRow; - - var s, t, sval, tval, p; - var dsval = 0; - var dtval = 0; - - var normOut = new THREE.Vector3(); - var v1, v2, v3, v4; - - var gmx = new THREE.Matrix4(); - var tmtx = new THREE.Matrix4(); - - var vsp = new THREE.Vector4(); - var vtp = new THREE.Vector4(); - var vdsp = new THREE.Vector4(); - var vdtp = new THREE.Vector4(); - - var vsdir = new THREE.Vector3(); - var vtdir = new THREE.Vector3(); - - var mst = ms.clone(); - mst.transpose(); - - // internal function: test if triangle has any matching vertices; - // if so, don't save triangle, since it won't display anything. - var notDegenerate = function ( vtx1, vtx2, vtx3 ) { - - // if any vertex matches, return false - return ! ( ( ( vertices[ vtx1 * 3 ] === vertices[ vtx2 * 3 ] ) && - ( vertices[ vtx1 * 3 + 1 ] === vertices[ vtx2 * 3 + 1 ] ) && - ( vertices[ vtx1 * 3 + 2 ] === vertices[ vtx2 * 3 + 2 ] ) ) || - ( ( vertices[ vtx1 * 3 ] === vertices[ vtx3 * 3 ] ) && - ( vertices[ vtx1 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] ) && - ( vertices[ vtx1 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ) ) || - ( ( vertices[ vtx2 * 3 ] === vertices[ vtx3 * 3 ] ) && - ( vertices[ vtx2 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] ) && - ( vertices[ vtx2 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ) ) ); - - }; + class TeapotGeometry extends THREE.BufferGeometry { + + constructor( size = 50, segments = 10, bottom = true, lid = true, body = true, fitLid = true, blinn = true ) { + + // 32 * 4 * 4 Bezier spline patches + const teapotPatches = [ + /*rim*/ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 3, 16, 17, 18, 7, 19, 20, 21, 11, 22, 23, 24, 15, 25, 26, 27, 18, 28, 29, 30, 21, 31, 32, 33, 24, 34, 35, 36, 27, 37, 38, 39, 30, 40, 41, 0, 33, 42, 43, 4, 36, 44, 45, 8, 39, 46, 47, 12, + /*body*/ + 12, 13, 14, 15, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 15, 25, 26, 27, 51, 60, 61, 62, 55, 63, 64, 65, 59, 66, 67, 68, 27, 37, 38, 39, 62, 69, 70, 71, 65, 72, 73, 74, 68, 75, 76, 77, 39, 46, 47, 12, 71, 78, 79, 48, 74, 80, 81, 52, 77, 82, 83, 56, 56, 57, 58, 59, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 59, 66, 67, 68, 87, 96, 97, 98, 91, 99, 100, 101, 95, 102, 103, 104, 68, 75, 76, 77, 98, 105, 106, 107, 101, 108, 109, 110, 104, 111, 112, 113, 77, 82, 83, 56, 107, 114, 115, 84, 110, 116, 117, 88, 113, 118, 119, 92, + /*handle*/ + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 123, 136, 137, 120, 127, 138, 139, 124, 131, 140, 141, 128, 135, 142, 143, 132, 132, 133, 134, 135, 144, 145, 146, 147, 148, 149, 150, 151, 68, 152, 153, 154, 135, 142, 143, 132, 147, 155, 156, 144, 151, 157, 158, 148, 154, 159, 160, 68, + /*spout*/ + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 164, 177, 178, 161, 168, 179, 180, 165, 172, 181, 182, 169, 176, 183, 184, 173, 173, 174, 175, 176, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 176, 183, 184, 173, 188, 197, 198, 185, 192, 199, 200, 189, 196, 201, 202, 193, + /*lid*/ + 203, 203, 203, 203, 204, 205, 206, 207, 208, 208, 208, 208, 209, 210, 211, 212, 203, 203, 203, 203, 207, 213, 214, 215, 208, 208, 208, 208, 212, 216, 217, 218, 203, 203, 203, 203, 215, 219, 220, 221, 208, 208, 208, 208, 218, 222, 223, 224, 203, 203, 203, 203, 221, 225, 226, 204, 208, 208, 208, 208, 224, 227, 228, 209, 209, 210, 211, 212, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 212, 216, 217, 218, 232, 241, 242, 243, 236, 244, 245, 246, 240, 247, 248, 249, 218, 222, 223, 224, 243, 250, 251, 252, 246, 253, 254, 255, 249, 256, 257, 258, 224, 227, 228, 209, 252, 259, 260, 229, 255, 261, 262, 233, 258, 263, 264, 237, + /*bottom*/ + 265, 265, 265, 265, 266, 267, 268, 269, 270, 271, 272, 273, 92, 119, 118, 113, 265, 265, 265, 265, 269, 274, 275, 276, 273, 277, 278, 279, 113, 112, 111, 104, 265, 265, 265, 265, 276, 280, 281, 282, 279, 283, 284, 285, 104, 103, 102, 95, 265, 265, 265, 265, 282, 286, 287, 266, 285, 288, 289, 270, 95, 94, 93, 92 ]; + const teapotVertices = [ 1.4, 0, 2.4, 1.4, - 0.784, 2.4, 0.784, - 1.4, 2.4, 0, - 1.4, 2.4, 1.3375, 0, 2.53125, 1.3375, - 0.749, 2.53125, 0.749, - 1.3375, 2.53125, 0, - 1.3375, 2.53125, 1.4375, 0, 2.53125, 1.4375, - 0.805, 2.53125, 0.805, - 1.4375, 2.53125, 0, - 1.4375, 2.53125, 1.5, 0, 2.4, 1.5, - 0.84, 2.4, 0.84, - 1.5, 2.4, 0, - 1.5, 2.4, - 0.784, - 1.4, 2.4, - 1.4, - 0.784, 2.4, - 1.4, 0, 2.4, - 0.749, - 1.3375, 2.53125, - 1.3375, - 0.749, 2.53125, - 1.3375, 0, 2.53125, - 0.805, - 1.4375, 2.53125, - 1.4375, - 0.805, 2.53125, - 1.4375, 0, 2.53125, - 0.84, - 1.5, 2.4, - 1.5, - 0.84, 2.4, - 1.5, 0, 2.4, - 1.4, 0.784, 2.4, - 0.784, 1.4, 2.4, 0, 1.4, 2.4, - 1.3375, 0.749, 2.53125, - 0.749, 1.3375, 2.53125, 0, 1.3375, 2.53125, - 1.4375, 0.805, 2.53125, - 0.805, 1.4375, 2.53125, 0, 1.4375, 2.53125, - 1.5, 0.84, 2.4, - 0.84, 1.5, 2.4, 0, 1.5, 2.4, 0.784, 1.4, 2.4, 1.4, 0.784, 2.4, 0.749, 1.3375, 2.53125, 1.3375, 0.749, 2.53125, 0.805, 1.4375, 2.53125, 1.4375, 0.805, 2.53125, 0.84, 1.5, 2.4, 1.5, 0.84, 2.4, 1.75, 0, 1.875, 1.75, - 0.98, 1.875, 0.98, - 1.75, 1.875, 0, - 1.75, 1.875, 2, 0, 1.35, 2, - 1.12, 1.35, 1.12, - 2, 1.35, 0, - 2, 1.35, 2, 0, 0.9, 2, - 1.12, 0.9, 1.12, - 2, 0.9, 0, - 2, 0.9, - 0.98, - 1.75, 1.875, - 1.75, - 0.98, 1.875, - 1.75, 0, 1.875, - 1.12, - 2, 1.35, - 2, - 1.12, 1.35, - 2, 0, 1.35, - 1.12, - 2, 0.9, - 2, - 1.12, 0.9, - 2, 0, 0.9, - 1.75, 0.98, 1.875, - 0.98, 1.75, 1.875, 0, 1.75, 1.875, - 2, 1.12, 1.35, - 1.12, 2, 1.35, 0, 2, 1.35, - 2, 1.12, 0.9, - 1.12, 2, 0.9, 0, 2, 0.9, 0.98, 1.75, 1.875, 1.75, 0.98, 1.875, 1.12, 2, 1.35, 2, 1.12, 1.35, 1.12, 2, 0.9, 2, 1.12, 0.9, 2, 0, 0.45, 2, - 1.12, 0.45, 1.12, - 2, 0.45, 0, - 2, 0.45, 1.5, 0, 0.225, 1.5, - 0.84, 0.225, 0.84, - 1.5, 0.225, 0, - 1.5, 0.225, 1.5, 0, 0.15, 1.5, - 0.84, 0.15, 0.84, - 1.5, 0.15, 0, - 1.5, 0.15, - 1.12, - 2, 0.45, - 2, - 1.12, 0.45, - 2, 0, 0.45, - 0.84, - 1.5, 0.225, - 1.5, - 0.84, 0.225, - 1.5, 0, 0.225, - 0.84, - 1.5, 0.15, - 1.5, - 0.84, 0.15, - 1.5, 0, 0.15, - 2, 1.12, 0.45, - 1.12, 2, 0.45, 0, 2, 0.45, - 1.5, 0.84, 0.225, - 0.84, 1.5, 0.225, 0, 1.5, 0.225, - 1.5, 0.84, 0.15, - 0.84, 1.5, 0.15, 0, 1.5, 0.15, 1.12, 2, 0.45, 2, 1.12, 0.45, 0.84, 1.5, 0.225, 1.5, 0.84, 0.225, 0.84, 1.5, 0.15, 1.5, 0.84, 0.15, - 1.6, 0, 2.025, - 1.6, - 0.3, 2.025, - 1.5, - 0.3, 2.25, - 1.5, 0, 2.25, - 2.3, 0, 2.025, - 2.3, - 0.3, 2.025, - 2.5, - 0.3, 2.25, - 2.5, 0, 2.25, - 2.7, 0, 2.025, - 2.7, - 0.3, 2.025, - 3, - 0.3, 2.25, - 3, 0, 2.25, - 2.7, 0, 1.8, - 2.7, - 0.3, 1.8, - 3, - 0.3, 1.8, - 3, 0, 1.8, - 1.5, 0.3, 2.25, - 1.6, 0.3, 2.025, - 2.5, 0.3, 2.25, - 2.3, 0.3, 2.025, - 3, 0.3, 2.25, - 2.7, 0.3, 2.025, - 3, 0.3, 1.8, - 2.7, 0.3, 1.8, - 2.7, 0, 1.575, - 2.7, - 0.3, 1.575, - 3, - 0.3, 1.35, - 3, 0, 1.35, - 2.5, 0, 1.125, - 2.5, - 0.3, 1.125, - 2.65, - 0.3, 0.9375, - 2.65, 0, 0.9375, - 2, - 0.3, 0.9, - 1.9, - 0.3, 0.6, - 1.9, 0, 0.6, - 3, 0.3, 1.35, - 2.7, 0.3, 1.575, - 2.65, 0.3, 0.9375, - 2.5, 0.3, 1.125, - 1.9, 0.3, 0.6, - 2, 0.3, 0.9, 1.7, 0, 1.425, 1.7, - 0.66, 1.425, 1.7, - 0.66, 0.6, 1.7, 0, 0.6, 2.6, 0, 1.425, 2.6, - 0.66, 1.425, 3.1, - 0.66, 0.825, 3.1, 0, 0.825, 2.3, 0, 2.1, 2.3, - 0.25, 2.1, 2.4, - 0.25, 2.025, 2.4, 0, 2.025, 2.7, 0, 2.4, 2.7, - 0.25, 2.4, 3.3, - 0.25, 2.4, 3.3, 0, 2.4, 1.7, 0.66, 0.6, 1.7, 0.66, 1.425, 3.1, 0.66, 0.825, 2.6, 0.66, 1.425, 2.4, 0.25, 2.025, 2.3, 0.25, 2.1, 3.3, 0.25, 2.4, 2.7, 0.25, 2.4, 2.8, 0, 2.475, 2.8, - 0.25, 2.475, 3.525, - 0.25, 2.49375, 3.525, 0, 2.49375, 2.9, 0, 2.475, 2.9, - 0.15, 2.475, 3.45, - 0.15, 2.5125, 3.45, 0, 2.5125, 2.8, 0, 2.4, 2.8, - 0.15, 2.4, 3.2, - 0.15, 2.4, 3.2, 0, 2.4, 3.525, 0.25, 2.49375, 2.8, 0.25, 2.475, 3.45, 0.15, 2.5125, 2.9, 0.15, 2.475, 3.2, 0.15, 2.4, 2.8, 0.15, 2.4, 0, 0, 3.15, 0.8, 0, 3.15, 0.8, - 0.45, 3.15, 0.45, - 0.8, 3.15, 0, - 0.8, 3.15, 0, 0, 2.85, 0.2, 0, 2.7, 0.2, - 0.112, 2.7, 0.112, - 0.2, 2.7, 0, - 0.2, 2.7, - 0.45, - 0.8, 3.15, - 0.8, - 0.45, 3.15, - 0.8, 0, 3.15, - 0.112, - 0.2, 2.7, - 0.2, - 0.112, 2.7, - 0.2, 0, 2.7, - 0.8, 0.45, 3.15, - 0.45, 0.8, 3.15, 0, 0.8, 3.15, - 0.2, 0.112, 2.7, - 0.112, 0.2, 2.7, 0, 0.2, 2.7, 0.45, 0.8, 3.15, 0.8, 0.45, 3.15, 0.112, 0.2, 2.7, 0.2, 0.112, 2.7, 0.4, 0, 2.55, 0.4, - 0.224, 2.55, 0.224, - 0.4, 2.55, 0, - 0.4, 2.55, 1.3, 0, 2.55, 1.3, - 0.728, 2.55, 0.728, - 1.3, 2.55, 0, - 1.3, 2.55, 1.3, 0, 2.4, 1.3, - 0.728, 2.4, 0.728, - 1.3, 2.4, 0, - 1.3, 2.4, - 0.224, - 0.4, 2.55, - 0.4, - 0.224, 2.55, - 0.4, 0, 2.55, - 0.728, - 1.3, 2.55, - 1.3, - 0.728, 2.55, - 1.3, 0, 2.55, - 0.728, - 1.3, 2.4, - 1.3, - 0.728, 2.4, - 1.3, 0, 2.4, - 0.4, 0.224, 2.55, - 0.224, 0.4, 2.55, 0, 0.4, 2.55, - 1.3, 0.728, 2.55, - 0.728, 1.3, 2.55, 0, 1.3, 2.55, - 1.3, 0.728, 2.4, - 0.728, 1.3, 2.4, 0, 1.3, 2.4, 0.224, 0.4, 2.55, 0.4, 0.224, 2.55, 0.728, 1.3, 2.55, 1.3, 0.728, 2.55, 0.728, 1.3, 2.4, 1.3, 0.728, 2.4, 0, 0, 0, 1.425, 0, 0, 1.425, 0.798, 0, 0.798, 1.425, 0, 0, 1.425, 0, 1.5, 0, 0.075, 1.5, 0.84, 0.075, 0.84, 1.5, 0.075, 0, 1.5, 0.075, - 0.798, 1.425, 0, - 1.425, 0.798, 0, - 1.425, 0, 0, - 0.84, 1.5, 0.075, - 1.5, 0.84, 0.075, - 1.5, 0, 0.075, - 1.425, - 0.798, 0, - 0.798, - 1.425, 0, 0, - 1.425, 0, - 1.5, - 0.84, 0.075, - 0.84, - 1.5, 0.075, 0, - 1.5, 0.075, 0.798, - 1.425, 0, 1.425, - 0.798, 0, 0.84, - 1.5, 0.075, 1.5, - 0.84, 0.075 ]; + super(); // number of segments per patch + + segments = Math.max( 2, Math.floor( segments ) ); // Jim Blinn scaled the teapot down in size by about 1.3 for + // some rendering tests. He liked the new proportions that he kept + // the data in this form. The model was distributed with these new + // proportions and became the norm. Trivia: comparing images of the + // real teapot and the computer model, the ratio for the bowl of the + // real teapot is more like 1.25, but since 1.3 is the traditional + // value given, we use it here. + + const blinnScale = 1.3; // scale the size to be the real scaling factor + + const maxHeight = 3.15 * ( blinn ? 1 : blinnScale ); + const maxHeight2 = maxHeight / 2; + const trueSize = size / maxHeight2; // Number of elements depends on what is needed. Subtract degenerate + // triangles at tip of bottom and lid out in advance. + + let numTriangles = bottom ? ( 8 * segments - 4 ) * segments : 0; + numTriangles += lid ? ( 16 * segments - 4 ) * segments : 0; + numTriangles += body ? 40 * segments * segments : 0; + const indices = new Uint32Array( numTriangles * 3 ); + let numVertices = bottom ? 4 : 0; + numVertices += lid ? 8 : 0; + numVertices += body ? 20 : 0; + numVertices *= ( segments + 1 ) * ( segments + 1 ); + const vertices = new Float32Array( numVertices * 3 ); + const normals = new Float32Array( numVertices * 3 ); + const uvs = new Float32Array( numVertices * 2 ); // Bezier form + + const ms = new THREE.Matrix4(); + ms.set( - 1.0, 3.0, - 3.0, 1.0, 3.0, - 6.0, 3.0, 0.0, - 3.0, 3.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 ); + const g = []; + const sp = []; + const tp = []; + const dsp = []; + const dtp = []; // M * G * M matrix, sort of see + // http://www.cs.helsinki.fi/group/goa/mallinnus/curves/surfaces.html + + const mgm = []; + const vert = []; + const sdir = []; + const tdir = []; + const norm = new THREE.Vector3(); + let tcoord; + let sval; + let tval; + let p; + let dsval = 0; + let dtval = 0; + const normOut = new THREE.Vector3(); + const gmx = new THREE.Matrix4(); + const tmtx = new THREE.Matrix4(); + const vsp = new THREE.Vector4(); + const vtp = new THREE.Vector4(); + const vdsp = new THREE.Vector4(); + const vdtp = new THREE.Vector4(); + const vsdir = new THREE.Vector3(); + const vtdir = new THREE.Vector3(); + const mst = ms.clone(); + mst.transpose(); // internal function: test if triangle has any matching vertices; + // if so, don't save triangle, since it won't display anything. + + const notDegenerate = ( vtx1, vtx2, vtx3 ) => // if any vertex matches, return false + ! ( vertices[ vtx1 * 3 ] === vertices[ vtx2 * 3 ] && vertices[ vtx1 * 3 + 1 ] === vertices[ vtx2 * 3 + 1 ] && vertices[ vtx1 * 3 + 2 ] === vertices[ vtx2 * 3 + 2 ] || vertices[ vtx1 * 3 ] === vertices[ vtx3 * 3 ] && vertices[ vtx1 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] && vertices[ vtx1 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] || vertices[ vtx2 * 3 ] === vertices[ vtx3 * 3 ] && vertices[ vtx2 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] && vertices[ vtx2 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ); + + for ( let i = 0; i < 3; i ++ ) { + + mgm[ i ] = new THREE.Matrix4(); + } - for ( i = 0; i < 3; i ++ ) { + const minPatches = body ? 0 : 20; + const maxPatches = bottom ? 32 : 28; + const vertPerRow = segments + 1; + let surfCount = 0; + let vertCount = 0; + let normCount = 0; + let uvCount = 0; + let indexCount = 0; - mgm[ i ] = new THREE.Matrix4(); + for ( let surf = minPatches; surf < maxPatches; surf ++ ) { - } + // lid is in the middle of the data, patches 20-27, + // so ignore it for this part of the loop if the lid is not desired + if ( lid || surf < 20 || surf >= 28 ) { - var minPatches = body ? 0 : 20; - var maxPatches = bottom ? 32 : 28; + // get M * G * M matrix for x,y,z + for ( let i = 0; i < 3; i ++ ) { - vertPerRow = segments + 1; + // get control patches + for ( let r = 0; r < 4; r ++ ) { - var surfCount = 0; + for ( let c = 0; c < 4; c ++ ) { - var vertCount = 0; - var normCount = 0; - var uvCount = 0; + // transposed + g[ c * 4 + r ] = teapotVertices[ teapotPatches[ surf * 16 + r * 4 + c ] * 3 + i ]; // is the lid to be made larger, and is this a point on the lid + // that is X or Y? - var indexCount = 0; + if ( fitLid && surf >= 20 && surf < 28 && i !== 2 ) { - for ( var surf = minPatches; surf < maxPatches; surf ++ ) { + // increase XY size by 7.7%, found empirically. I don't + // increase Z so that the teapot will continue to fit in the + // space -1 to 1 for Y (Y is up for the final model). + g[ c * 4 + r ] *= 1.077; - // lid is in the middle of the data, patches 20-27, - // so ignore it for this part of the loop if the lid is not desired - if ( lid || ( surf < 20 || surf >= 28 ) ) { + } // Blinn "fixed" the teapot by dividing Z by blinnScale, and that's the + // data we now use. The original teapot is taller. Fix it: - // get M * G * M matrix for x,y,z - for ( i = 0; i < 3; i ++ ) { - // get control patches - for ( r = 0; r < 4; r ++ ) { + if ( ! blinn && i === 2 ) { - for ( c = 0; c < 4; c ++ ) { + g[ c * 4 + r ] *= blinnScale; - // transposed - g[ c * 4 + r ] = teapotVertices[ teapotPatches[ surf * 16 + r * 4 + c ] * 3 + i ]; + } - // is the lid to be made larger, and is this a point on the lid - // that is X or Y? - if ( fitLid && ( surf >= 20 && surf < 28 ) && ( i !== 2 ) ) { - - // increase XY size by 7.7%, found empirically. I don't - // increase Z so that the teapot will continue to fit in the - // space -1 to 1 for Y (Y is up for the final model). - g[ c * 4 + r ] *= 1.077; + } } - // Blinn "fixed" the teapot by dividing Z by blinnScale, and that's the - // data we now use. The original teapot is taller. Fix it: - if ( ! blinn && ( i === 2 ) ) { - - g[ c * 4 + r ] *= blinnScale; + gmx.set( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ], g[ 4 ], g[ 5 ], g[ 6 ], g[ 7 ], g[ 8 ], g[ 9 ], g[ 10 ], g[ 11 ], g[ 12 ], g[ 13 ], g[ 14 ], g[ 15 ] ); + tmtx.multiplyMatrices( gmx, ms ); + mgm[ i ].multiplyMatrices( mst, tmtx ); - } + } // step along, get points, and output - } - } + for ( let sstep = 0; sstep <= segments; sstep ++ ) { - gmx.set( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ], g[ 4 ], g[ 5 ], g[ 6 ], g[ 7 ], g[ 8 ], g[ 9 ], g[ 10 ], g[ 11 ], g[ 12 ], g[ 13 ], g[ 14 ], g[ 15 ] ); + const s = sstep / segments; - tmtx.multiplyMatrices( gmx, ms ); - mgm[ i ].multiplyMatrices( mst, tmtx ); + for ( let tstep = 0; tstep <= segments; tstep ++ ) { - } + const t = tstep / segments; // point from basis + // get power vectors and their derivatives - // step along, get points, and output - for ( sstep = 0; sstep <= segments; sstep ++ ) { + for ( p = 4, sval = tval = 1.0; p --; ) { - s = sstep / segments; + sp[ p ] = sval; + tp[ p ] = tval; + sval *= s; + tval *= t; - for ( tstep = 0; tstep <= segments; tstep ++ ) { + if ( p === 3 ) { - t = tstep / segments; + dsp[ p ] = dtp[ p ] = 0.0; + dsval = dtval = 1.0; - // point from basis - // get power vectors and their derivatives - for ( p = 4, sval = tval = 1.0; p --; ) { + } else { - sp[ p ] = sval; - tp[ p ] = tval; - sval *= s; - tval *= t; + dsp[ p ] = dsval * ( 3 - p ); + dtp[ p ] = dtval * ( 3 - p ); + dsval *= s; + dtval *= t; - if ( p === 3 ) { + } - dsp[ p ] = dtp[ p ] = 0.0; - dsval = dtval = 1.0; + } - } else { + vsp.fromArray( sp ); + vtp.fromArray( tp ); + vdsp.fromArray( dsp ); + vdtp.fromArray( dtp ); // do for x,y,z - dsp[ p ] = dsval * ( 3 - p ); - dtp[ p ] = dtval * ( 3 - p ); - dsval *= s; - dtval *= t; + for ( let i = 0; i < 3; i ++ ) { - } + // multiply power vectors times matrix to get value + tcoord = vsp.clone(); + tcoord.applyMatrix4( mgm[ i ] ); + vert[ i ] = tcoord.dot( vtp ); // get s and t tangent vectors - } + tcoord = vdsp.clone(); + tcoord.applyMatrix4( mgm[ i ] ); + sdir[ i ] = tcoord.dot( vtp ); + tcoord = vsp.clone(); + tcoord.applyMatrix4( mgm[ i ] ); + tdir[ i ] = tcoord.dot( vdtp ); - vsp.fromArray( sp ); - vtp.fromArray( tp ); - vdsp.fromArray( dsp ); - vdtp.fromArray( dtp ); + } // find normal - // do for x,y,z - for ( i = 0; i < 3; i ++ ) { - // multiply power vectors times matrix to get value - tcoord = vsp.clone(); - tcoord.applyMatrix4( mgm[ i ] ); - vert[ i ] = tcoord.dot( vtp ); + vsdir.fromArray( sdir ); + vtdir.fromArray( tdir ); + norm.crossVectors( vtdir, vsdir ); + norm.normalize(); // if X and Z length is 0, at the cusp, so point the normal up or down, depending on patch number - // get s and t tangent vectors - tcoord = vdsp.clone(); - tcoord.applyMatrix4( mgm[ i ] ); - sdir[ i ] = tcoord.dot( vtp ); + if ( vert[ 0 ] === 0 && vert[ 1 ] === 0 ) { - tcoord = vsp.clone(); - tcoord.applyMatrix4( mgm[ i ] ); - tdir[ i ] = tcoord.dot( vdtp ); + // if above the middle of the teapot, normal points up, else down + normOut.set( 0, vert[ 2 ] > maxHeight2 ? 1 : - 1, 0 ); - } + } else { - // find normal - vsdir.fromArray( sdir ); - vtdir.fromArray( tdir ); - norm.crossVectors( vtdir, vsdir ); - norm.normalize(); + // standard output: rotate on X axis + normOut.set( norm.x, norm.z, - norm.y ); - // if X and Z length is 0, at the cusp, so point the normal up or down, depending on patch number - if ( vert[ 0 ] === 0 && vert[ 1 ] === 0 ) { + } // store it all - // if above the middle of the teapot, normal points up, else down - normOut.set( 0, vert[ 2 ] > maxHeight2 ? 1 : - 1, 0 ); - } else { + vertices[ vertCount ++ ] = trueSize * vert[ 0 ]; + vertices[ vertCount ++ ] = trueSize * ( vert[ 2 ] - maxHeight2 ); + vertices[ vertCount ++ ] = - trueSize * vert[ 1 ]; + normals[ normCount ++ ] = normOut.x; + normals[ normCount ++ ] = normOut.y; + normals[ normCount ++ ] = normOut.z; + uvs[ uvCount ++ ] = 1 - t; + uvs[ uvCount ++ ] = 1 - s; - // standard output: rotate on X axis - normOut.set( norm.x, norm.z, - norm.y ); + } - } + } // save the faces - // store it all - vertices[ vertCount ++ ] = trueSize * vert[ 0 ]; - vertices[ vertCount ++ ] = trueSize * ( vert[ 2 ] - maxHeight2 ); - vertices[ vertCount ++ ] = - trueSize * vert[ 1 ]; - normals[ normCount ++ ] = normOut.x; - normals[ normCount ++ ] = normOut.y; - normals[ normCount ++ ] = normOut.z; + for ( let sstep = 0; sstep < segments; sstep ++ ) { - uvs[ uvCount ++ ] = 1 - t; - uvs[ uvCount ++ ] = 1 - s; + for ( let tstep = 0; tstep < segments; tstep ++ ) { - } + const v1 = surfCount * vertPerRow * vertPerRow + sstep * vertPerRow + tstep; + const v2 = v1 + 1; + const v3 = v2 + vertPerRow; + const v4 = v1 + vertPerRow; // Normals and UVs cannot be shared. Without clone(), you can see the consequences + // of sharing if you call geometry.applyMatrix4( matrix ). - } + if ( notDegenerate( v1, v2, v3 ) ) { - // save the faces - for ( sstep = 0; sstep < segments; sstep ++ ) { + indices[ indexCount ++ ] = v1; + indices[ indexCount ++ ] = v2; + indices[ indexCount ++ ] = v3; - for ( tstep = 0; tstep < segments; tstep ++ ) { + } - v1 = surfCount * vertPerRow * vertPerRow + sstep * vertPerRow + tstep; - v2 = v1 + 1; - v3 = v2 + vertPerRow; - v4 = v1 + vertPerRow; + if ( notDegenerate( v1, v3, v4 ) ) { - // Normals and UVs cannot be shared. Without clone(), you can see the consequences - // of sharing if you call geometry.applyMatrix4( matrix ). - if ( notDegenerate( v1, v2, v3 ) ) { + indices[ indexCount ++ ] = v1; + indices[ indexCount ++ ] = v3; + indices[ indexCount ++ ] = v4; - indices[ indexCount ++ ] = v1; - indices[ indexCount ++ ] = v2; - indices[ indexCount ++ ] = v3; + } - } + } - if ( notDegenerate( v1, v3, v4 ) ) { + } // increment only if a surface was used - indices[ indexCount ++ ] = v1; - indices[ indexCount ++ ] = v3; - indices[ indexCount ++ ] = v4; - } + surfCount ++; } } - // increment only if a surface was used - surfCount ++; + this.setIndex( new THREE.BufferAttribute( indices, 1 ) ); + this.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) ); + this.computeBoundingSphere(); } } - this.setIndex( new THREE.BufferAttribute( indices, 1 ) ); - this.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); - this.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) ); - this.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) ); - - this.computeBoundingSphere(); - -}; - + THREE.TeapotGeometry = TeapotGeometry; -THREE.TeapotGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); -THREE.TeapotGeometry.prototype.constructor = THREE.TeapotGeometry; +} )(); diff --git a/examples/js/helpers/LightProbeHelper.js b/examples/js/helpers/LightProbeHelper.js new file mode 100644 index 00000000000000..e3e9cbeef10155 --- /dev/null +++ b/examples/js/helpers/LightProbeHelper.js @@ -0,0 +1,49 @@ +( function () { + + class LightProbeHelper extends THREE.Mesh { + + constructor( lightProbe, size ) { + + const material = new THREE.ShaderMaterial( { + type: 'LightProbeHelperMaterial', + uniforms: { + sh: { + value: lightProbe.sh.coefficients + }, + // by reference + intensity: { + value: lightProbe.intensity + } + }, + vertexShader: [ 'varying vec3 vNormal;', 'void main() {', ' vNormal = normalize( normalMatrix * normal );', ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', '}' ].join( '\n' ), + fragmentShader: [ '#define RECIPROCAL_PI 0.318309886', 'vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {', ' // matrix is assumed to be orthogonal', ' return normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );', '}', '// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf', 'vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {', ' // normal is assumed to have unit length', ' float x = normal.x, y = normal.y, z = normal.z;', ' // band 0', ' vec3 result = shCoefficients[ 0 ] * 0.886227;', ' // band 1', ' result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;', ' result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;', ' result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;', ' // band 2', ' result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;', ' result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;', ' result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );', ' result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;', ' result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );', ' return result;', '}', 'uniform vec3 sh[ 9 ]; // sh coefficients', 'uniform float intensity; // light probe intensity', 'varying vec3 vNormal;', 'void main() {', ' vec3 normal = normalize( vNormal );', ' vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );', ' vec3 irradiance = shGetIrradianceAt( worldNormal, sh );', ' vec3 outgoingLight = RECIPROCAL_PI * irradiance * intensity;', ' gl_FragColor = linearToOutputTexel( vec4( outgoingLight, 1.0 ) );', '}' ].join( '\n' ) + } ); + const geometry = new THREE.SphereGeometry( 1, 32, 16 ); + super( geometry, material ); + this.lightProbe = lightProbe; + this.size = size; + this.type = 'LightProbeHelper'; + this.onBeforeRender(); + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + + onBeforeRender() { + + this.position.copy( this.lightProbe.position ); + this.scale.set( 1, 1, 1 ).multiplyScalar( this.size ); + this.material.uniforms.intensity.value = this.lightProbe.intensity; + + } + + } + + THREE.LightProbeHelper = LightProbeHelper; + +} )(); diff --git a/examples/js/helpers/PositionalAudioHelper.js b/examples/js/helpers/PositionalAudioHelper.js new file mode 100644 index 00000000000000..a89d61561b5356 --- /dev/null +++ b/examples/js/helpers/PositionalAudioHelper.js @@ -0,0 +1,89 @@ +( function () { + + class PositionalAudioHelper extends THREE.Line { + + constructor( audio, range = 1, divisionsInnerAngle = 16, divisionsOuterAngle = 2 ) { + + const geometry = new THREE.BufferGeometry(); + const divisions = divisionsInnerAngle + divisionsOuterAngle * 2; + const positions = new Float32Array( ( divisions * 3 + 3 ) * 3 ); + geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); + const materialInnerAngle = new THREE.LineBasicMaterial( { + color: 0x00ff00 + } ); + const materialOuterAngle = new THREE.LineBasicMaterial( { + color: 0xffff00 + } ); + super( geometry, [ materialOuterAngle, materialInnerAngle ] ); + this.audio = audio; + this.range = range; + this.divisionsInnerAngle = divisionsInnerAngle; + this.divisionsOuterAngle = divisionsOuterAngle; + this.type = 'PositionalAudioHelper'; + this.update(); + + } + + update() { + + const audio = this.audio; + const range = this.range; + const divisionsInnerAngle = this.divisionsInnerAngle; + const divisionsOuterAngle = this.divisionsOuterAngle; + const coneInnerAngle = THREE.MathUtils.degToRad( audio.panner.coneInnerAngle ); + const coneOuterAngle = THREE.MathUtils.degToRad( audio.panner.coneOuterAngle ); + const halfConeInnerAngle = coneInnerAngle / 2; + const halfConeOuterAngle = coneOuterAngle / 2; + let start = 0; + let count = 0; + let i; + let stride; + const geometry = this.geometry; + const positionAttribute = geometry.attributes.position; + geometry.clearGroups(); // + + function generateSegment( from, to, divisions, materialIndex ) { + + const step = ( to - from ) / divisions; + positionAttribute.setXYZ( start, 0, 0, 0 ); + count ++; + + for ( i = from; i < to; i += step ) { + + stride = start + count; + positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range ); + positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range ); + positionAttribute.setXYZ( stride + 2, 0, 0, 0 ); + count += 3; + + } + + geometry.addGroup( start, count, materialIndex ); + start += count; + count = 0; + + } // + + + generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 ); + generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 ); + generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 ); // + + positionAttribute.needsUpdate = true; + if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false; + + } + + dispose() { + + this.geometry.dispose(); + this.material[ 0 ].dispose(); + this.material[ 1 ].dispose(); + + } + + } + + THREE.PositionalAudioHelper = PositionalAudioHelper; + +} )(); diff --git a/examples/js/helpers/RectAreaLightHelper.js b/examples/js/helpers/RectAreaLightHelper.js new file mode 100644 index 00000000000000..c9d9269de9da76 --- /dev/null +++ b/examples/js/helpers/RectAreaLightHelper.js @@ -0,0 +1,73 @@ +( function () { + + /** + * This helper must be added as a child of the light + */ + + class RectAreaLightHelper extends THREE.Line { + + constructor( light, color ) { + + const positions = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ]; + const geometry = new THREE.BufferGeometry(); + geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); + geometry.computeBoundingSphere(); + const material = new THREE.LineBasicMaterial( { + fog: false + } ); + super( geometry, material ); + this.light = light; + this.color = color; // optional hardwired color for the helper + + this.type = 'RectAreaLightHelper'; // + + const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; + const geometry2 = new THREE.BufferGeometry(); + geometry2.setAttribute( 'position', new THREE.Float32BufferAttribute( positions2, 3 ) ); + geometry2.computeBoundingSphere(); + this.add( new THREE.Mesh( geometry2, new THREE.MeshBasicMaterial( { + side: THREE.BackSide, + fog: false + } ) ) ); + + } + + updateMatrixWorld() { + + this.scale.set( 0.5 * this.light.width, 0.5 * this.light.height, 1 ); + + if ( this.color !== undefined ) { + + this.material.color.set( this.color ); + this.children[ 0 ].material.color.set( this.color ); + + } else { + + this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity ); // prevent hue shift + + const c = this.material.color; + const max = Math.max( c.r, c.g, c.b ); + if ( max > 1 ) c.multiplyScalar( 1 / max ); + this.children[ 0 ].material.color.copy( this.material.color ); + + } + + this.matrixWorld.copy( this.light.matrixWorld ).scale( this.scale ); + this.children[ 0 ].matrixWorld.copy( this.matrixWorld ); + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + this.children[ 0 ].geometry.dispose(); + this.children[ 0 ].material.dispose(); + + } + + } + + THREE.RectAreaLightHelper = RectAreaLightHelper; + +} )(); diff --git a/examples/js/helpers/VertexNormalsHelper.js b/examples/js/helpers/VertexNormalsHelper.js new file mode 100644 index 00000000000000..18681e64ed6b82 --- /dev/null +++ b/examples/js/helpers/VertexNormalsHelper.js @@ -0,0 +1,91 @@ +( function () { + + const _v1 = new THREE.Vector3(); + + const _v2 = new THREE.Vector3(); + + const _normalMatrix = new THREE.Matrix3(); + + class VertexNormalsHelper extends THREE.LineSegments { + + constructor( object, size = 1, color = 0xff0000 ) { + + let nNormals = 0; + const objGeometry = object.geometry; + + if ( objGeometry && objGeometry.isGeometry ) { + + console.error( 'THREE.VertexNormalsHelper no longer supports Geometry. Use THREE.BufferGeometry instead.' ); + return; + + } else if ( objGeometry && objGeometry.isBufferGeometry ) { + + nNormals = objGeometry.attributes.normal.count; + + } // + + + const geometry = new THREE.BufferGeometry(); + const positions = new THREE.Float32BufferAttribute( nNormals * 2 * 3, 3 ); + geometry.setAttribute( 'position', positions ); + super( geometry, new THREE.LineBasicMaterial( { + color, + toneMapped: false + } ) ); + this.object = object; + this.size = size; + this.type = 'VertexNormalsHelper'; // + + this.matrixAutoUpdate = false; + this.update(); + + } + + update() { + + this.object.updateMatrixWorld( true ); + + _normalMatrix.getNormalMatrix( this.object.matrixWorld ); + + const matrixWorld = this.object.matrixWorld; + const position = this.geometry.attributes.position; // + + const objGeometry = this.object.geometry; + + if ( objGeometry && objGeometry.isGeometry ) { + + console.error( 'THREE.VertexNormalsHelper no longer supports Geometry. Use THREE.BufferGeometry instead.' ); + return; + + } else if ( objGeometry && objGeometry.isBufferGeometry ) { + + const objPos = objGeometry.attributes.position; + const objNorm = objGeometry.attributes.normal; + let idx = 0; // for simplicity, ignore index and drawcalls, and render every normal + + for ( let j = 0, jl = objPos.count; j < jl; j ++ ) { + + _v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); + + _v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) ); + + _v2.applyMatrix3( _normalMatrix ).normalize().multiplyScalar( this.size ).add( _v1 ); + + position.setXYZ( idx, _v1.x, _v1.y, _v1.z ); + idx = idx + 1; + position.setXYZ( idx, _v2.x, _v2.y, _v2.z ); + idx = idx + 1; + + } + + } + + position.needsUpdate = true; + + } + + } + + THREE.VertexNormalsHelper = VertexNormalsHelper; + +} )(); diff --git a/examples/js/helpers/VertexTangentsHelper.js b/examples/js/helpers/VertexTangentsHelper.js new file mode 100644 index 00000000000000..9fa1e2cb01f41b --- /dev/null +++ b/examples/js/helpers/VertexTangentsHelper.js @@ -0,0 +1,72 @@ +( function () { + + const _v1 = new THREE.Vector3(); + + const _v2 = new THREE.Vector3(); + + class VertexTangentsHelper extends THREE.LineSegments { + + constructor( object, size = 1, color = 0x00ffff ) { + + const objGeometry = object.geometry; + + if ( ! ( objGeometry && objGeometry.isBufferGeometry ) ) { + + console.error( 'THREE.VertexTangentsHelper: geometry not an instance of THREE.BufferGeometry.', objGeometry ); + return; + + } + + const nTangents = objGeometry.attributes.tangent.count; // + + const geometry = new THREE.BufferGeometry(); + const positions = new THREE.Float32BufferAttribute( nTangents * 2 * 3, 3 ); + geometry.setAttribute( 'position', positions ); + super( geometry, new THREE.LineBasicMaterial( { + color, + toneMapped: false + } ) ); + this.object = object; + this.size = size; + this.type = 'VertexTangentsHelper'; // + + this.matrixAutoUpdate = false; + this.update(); + + } + + update() { + + this.object.updateMatrixWorld( true ); + const matrixWorld = this.object.matrixWorld; + const position = this.geometry.attributes.position; // + + const objGeometry = this.object.geometry; + const objPos = objGeometry.attributes.position; + const objTan = objGeometry.attributes.tangent; + let idx = 0; // for simplicity, ignore index and drawcalls, and render every tangent + + for ( let j = 0, jl = objPos.count; j < jl; j ++ ) { + + _v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); + + _v2.set( objTan.getX( j ), objTan.getY( j ), objTan.getZ( j ) ); + + _v2.transformDirection( matrixWorld ).multiplyScalar( this.size ).add( _v1 ); + + position.setXYZ( idx, _v1.x, _v1.y, _v1.z ); + idx = idx + 1; + position.setXYZ( idx, _v2.x, _v2.y, _v2.z ); + idx = idx + 1; + + } + + position.needsUpdate = true; + + } + + } + + THREE.VertexTangentsHelper = VertexTangentsHelper; + +} )(); diff --git a/examples/js/interactive/HTMLMesh.js b/examples/js/interactive/HTMLMesh.js new file mode 100644 index 00000000000000..d4d1476abe8607 --- /dev/null +++ b/examples/js/interactive/HTMLMesh.js @@ -0,0 +1,291 @@ +( function () { + + class HTMLMesh extends THREE.Mesh { + + constructor( dom ) { + + const texture = new HTMLTexture( dom ); + const geometry = new THREE.PlaneGeometry( texture.image.width * 0.001, texture.image.height * 0.001 ); + const material = new THREE.MeshBasicMaterial( { + map: texture, + toneMapped: false + } ); + super( geometry, material ); + + function onEvent( event ) { + + material.map.dispatchEvent( event ); + + } + + this.addEventListener( 'mousedown', onEvent ); + this.addEventListener( 'mousemove', onEvent ); + this.addEventListener( 'mouseup', onEvent ); + this.addEventListener( 'click', onEvent ); + + } + + } + + class HTMLTexture extends THREE.CanvasTexture { + + constructor( dom ) { + + super( html2canvas( dom ) ); + this.dom = dom; + this.anisotropy = 16; + this.encoding = THREE.sRGBEncoding; + this.minFilter = THREE.LinearFilter; + this.magFilter = THREE.LinearFilter; + + } + + dispatchEvent( event ) { + + htmlevent( this.dom, event.type, event.data.x, event.data.y ); + this.update(); + + } + + update() { + + this.image = html2canvas( this.dom ); + this.needsUpdate = true; + + } + + } // + + + function html2canvas( element ) { + + var range = document.createRange(); + + function Clipper( context ) { + + var clips = []; + var isClipping = false; + + function doClip() { + + if ( isClipping ) { + + isClipping = false; + context.restore(); + + } + + if ( clips.length === 0 ) return; + var minX = - Infinity, + minY = - Infinity; + var maxX = Infinity, + maxY = Infinity; + + for ( var i = 0; i < clips.length; i ++ ) { + + var clip = clips[ i ]; + minX = Math.max( minX, clip.x ); + minY = Math.max( minY, clip.y ); + maxX = Math.min( maxX, clip.x + clip.width ); + maxY = Math.min( maxY, clip.y + clip.height ); + + } + + context.save(); + context.beginPath(); + context.rect( minX, minY, maxX - minX, maxY - minY ); + context.clip(); + isClipping = true; + + } + + return { + add: function ( clip ) { + + clips.push( clip ); + doClip(); + + }, + remove: function () { + + clips.pop(); + doClip(); + + } + }; + + } + + function drawText( style, x, y, string ) { + + if ( string !== '' ) { + + if ( style.textTransform === 'uppercase' ) { + + string = string.toUpperCase(); + + } + + context.font = style.fontSize + ' ' + style.fontFamily; + context.textBaseline = 'top'; + context.fillStyle = style.color; + context.fillText( string, x, y ); + + } + + } + + function drawBorder( style, which, x, y, width, height ) { + + var borderWidth = style[ which + 'Width' ]; + var borderStyle = style[ which + 'Style' ]; + var borderColor = style[ which + 'Color' ]; + + if ( borderWidth !== '0px' && borderStyle !== 'none' && borderColor !== 'transparent' && borderColor !== 'rgba(0, 0, 0, 0)' ) { + + context.strokeStyle = borderColor; + context.beginPath(); + context.moveTo( x, y ); + context.lineTo( x + width, y + height ); + context.stroke(); + + } + + } + + function drawElement( element, style ) { + + var x = 0, + y = 0, + width = 0, + height = 0; + + if ( element.nodeType === 3 ) { + + // text + range.selectNode( element ); + var rect = range.getBoundingClientRect(); + x = rect.left - offset.left - 0.5; + y = rect.top - offset.top - 0.5; + width = rect.width; + height = rect.height; + drawText( style, x, y, element.nodeValue.trim() ); + + } else { + + if ( element.style.display === 'none' ) return; + var rect = element.getBoundingClientRect(); + x = rect.left - offset.left - 0.5; + y = rect.top - offset.top - 0.5; + width = rect.width; + height = rect.height; + style = window.getComputedStyle( element ); + var backgroundColor = style.backgroundColor; + + if ( backgroundColor !== 'transparent' && backgroundColor !== 'rgba(0, 0, 0, 0)' ) { + + context.fillStyle = backgroundColor; + context.fillRect( x, y, width, height ); + + } + + drawBorder( style, 'borderTop', x, y, width, 0 ); + drawBorder( style, 'borderLeft', x, y, 0, height ); + drawBorder( style, 'borderBottom', x, y + height, width, 0 ); + drawBorder( style, 'borderRight', x + width, y, 0, height ); + + if ( element.type === 'color' || element.type === 'text' ) { + + clipper.add( { + x: x, + y: y, + width: width, + height: height + } ); + drawText( style, x + parseInt( style.paddingLeft ), y + parseInt( style.paddingTop ), element.value ); + clipper.remove(); + + } + + } + /* + // debug + context.strokeStyle = '#' + Math.random().toString( 16 ).slice( - 3 ); + context.strokeRect( x - 0.5, y - 0.5, width + 1, height + 1 ); + */ + + + var isClipping = style.overflow === 'auto' || style.overflow === 'hidden'; + if ( isClipping ) clipper.add( { + x: x, + y: y, + width: width, + height: height + } ); + + for ( var i = 0; i < element.childNodes.length; i ++ ) { + + drawElement( element.childNodes[ i ], style ); + + } + + if ( isClipping ) clipper.remove(); + + } + + var offset = element.getBoundingClientRect(); + var canvas = document.createElement( 'canvas' ); + canvas.width = offset.width; + canvas.height = offset.height; + var context = canvas.getContext( '2d' + /*, { alpha: false }*/ + ); + var clipper = new Clipper( context ); // console.time( 'drawElement' ); + + drawElement( element ); // console.timeEnd( 'drawElement' ); + + return canvas; + + } + + function htmlevent( element, event, x, y ) { + + const mouseEventInit = { + clientX: x * element.offsetWidth + element.offsetLeft, + clientY: y * element.offsetHeight + element.offsetTop, + view: element.ownerDocument.defaultView + }; + window.dispatchEvent( new MouseEvent( event, mouseEventInit ) ); + const rect = element.getBoundingClientRect(); + x = x * rect.width + rect.left; + y = y * rect.height + rect.top; + + function traverse( element ) { + + if ( element.nodeType !== 3 ) { + + const rect = element.getBoundingClientRect(); + + if ( x > rect.left && x < rect.right && y > rect.top && y < rect.bottom ) { + + element.dispatchEvent( new MouseEvent( event, mouseEventInit ) ); + + } + + for ( var i = 0; i < element.childNodes.length; i ++ ) { + + traverse( element.childNodes[ i ] ); + + } + + } + + } + + traverse( element ); + + } + + THREE.HTMLMesh = HTMLMesh; + +} )(); diff --git a/examples/js/interactive/InteractiveGroup.js b/examples/js/interactive/InteractiveGroup.js new file mode 100644 index 00000000000000..7b6691dbb4dfff --- /dev/null +++ b/examples/js/interactive/InteractiveGroup.js @@ -0,0 +1,100 @@ +( function () { + + const _pointer = new THREE.Vector2(); + + const _event = { + type: '', + data: _pointer + }; + + class InteractiveGroup extends THREE.Group { + + constructor( renderer, camera ) { + + super(); + const scope = this; + const raycaster = new THREE.Raycaster(); + const tempMatrix = new THREE.Matrix4(); // Pointer Events + + const element = renderer.domElement; + + function onPointerEvent( event ) { + + event.stopPropagation(); + _pointer.x = event.clientX / element.clientWidth * 2 - 1; + _pointer.y = - ( event.clientY / element.clientHeight ) * 2 + 1; + raycaster.setFromCamera( _pointer, camera ); + const intersects = raycaster.intersectObjects( scope.children ); + + if ( intersects.length > 0 ) { + + const intersection = intersects[ 0 ]; + const object = intersection.object; + const uv = intersection.uv; + _event.type = event.type; + + _event.data.set( uv.x, 1 - uv.y ); + + object.dispatchEvent( _event ); + + } + + } + + element.addEventListener( 'pointerdown', onPointerEvent ); + element.addEventListener( 'pointerup', onPointerEvent ); + element.addEventListener( 'pointermove', onPointerEvent ); + element.addEventListener( 'mousedown', onPointerEvent ); + element.addEventListener( 'mouseup', onPointerEvent ); + element.addEventListener( 'mousemove', onPointerEvent ); + element.addEventListener( 'click', onPointerEvent ); // WebXR Controller Events + // TODO: Dispatch pointerevents too + + const events = { + 'move': 'mousemove', + 'select': 'click', + 'selectstart': 'mousedown', + 'selectend': 'mouseup' + }; + + function onXRControllerEvent( event ) { + + const controller = event.target; + tempMatrix.identity().extractRotation( controller.matrixWorld ); + raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix ); + const intersections = raycaster.intersectObjects( scope.children ); + + if ( intersections.length > 0 ) { + + const intersection = intersections[ 0 ]; + const object = intersection.object; + const uv = intersection.uv; + _event.type = events[ event.type ]; + + _event.data.set( uv.x, 1 - uv.y ); + + object.dispatchEvent( _event ); + + } + + } + + const controller1 = renderer.xr.getController( 0 ); + controller1.addEventListener( 'move', onXRControllerEvent ); + controller1.addEventListener( 'select', onXRControllerEvent ); + controller1.addEventListener( 'selectstart', onXRControllerEvent ); + controller1.addEventListener( 'selectend', onXRControllerEvent ); + const controller2 = renderer.xr.getController( 1 ); + controller2.addEventListener( 'move', onXRControllerEvent ); + controller2.addEventListener( 'select', onXRControllerEvent ); + controller2.addEventListener( 'selectstart', onXRControllerEvent ); + controller2.addEventListener( 'selectend', onXRControllerEvent ); + + } + + } + + THREE.InteractiveGroup = InteractiveGroup; + +} )(); diff --git a/examples/js/interactive/SelectionBox.js b/examples/js/interactive/SelectionBox.js index 2170118ad42a02..90a19c83b858e9 100644 --- a/examples/js/interactive/SelectionBox.js +++ b/examples/js/interactive/SelectionBox.js @@ -1,197 +1,235 @@ -/** +( function () { + + /** * This is a class to check whether objects are in a selection area in 3D space */ -THREE.SelectionBox = ( function () { - - var frustum = new THREE.Frustum(); - var center = new THREE.Vector3(); + const _frustum = new THREE.Frustum(); - var tmpPoint = new THREE.Vector3(); + const _center = new THREE.Vector3(); - var vecNear = new THREE.Vector3(); - var vecTopLeft = new THREE.Vector3(); - var vecTopRight = new THREE.Vector3(); - var vecDownRight = new THREE.Vector3(); - var vecDownLeft = new THREE.Vector3(); + const _tmpPoint = new THREE.Vector3(); - var vecFarTopLeft = new THREE.Vector3(); - var vecFarTopRight = new THREE.Vector3(); - var vecFarDownRight = new THREE.Vector3(); - var vecFarDownLeft = new THREE.Vector3(); + const _vecNear = new THREE.Vector3(); - var vectemp1 = new THREE.Vector3(); - var vectemp2 = new THREE.Vector3(); - var vectemp3 = new THREE.Vector3(); + const _vecTopLeft = new THREE.Vector3(); - function SelectionBox( camera, scene, deep ) { + const _vecTopRight = new THREE.Vector3(); - this.camera = camera; - this.scene = scene; - this.startPoint = new THREE.Vector3(); - this.endPoint = new THREE.Vector3(); - this.collection = []; - this.deep = deep || Number.MAX_VALUE; + const _vecDownRight = new THREE.Vector3(); - } + const _vecDownLeft = new THREE.Vector3(); - SelectionBox.prototype.select = function ( startPoint, endPoint ) { + const _vecFarTopLeft = new THREE.Vector3(); - this.startPoint = startPoint || this.startPoint; - this.endPoint = endPoint || this.endPoint; - this.collection = []; + const _vecFarTopRight = new THREE.Vector3(); - this.updateFrustum( this.startPoint, this.endPoint ); - this.searchChildInFrustum( frustum, this.scene ); + const _vecFarDownRight = new THREE.Vector3(); - return this.collection; + const _vecFarDownLeft = new THREE.Vector3(); - }; + const _vectemp1 = new THREE.Vector3(); - SelectionBox.prototype.updateFrustum = function ( startPoint, endPoint ) { + const _vectemp2 = new THREE.Vector3(); - startPoint = startPoint || this.startPoint; - endPoint = endPoint || this.endPoint; + const _vectemp3 = new THREE.Vector3(); - // Avoid invalid frustum + class SelectionBox { - if ( startPoint.x === endPoint.x ) { + constructor( camera, scene, deep = Number.MAX_VALUE ) { - endPoint.x += Number.EPSILON; + this.camera = camera; + this.scene = scene; + this.startPoint = new THREE.Vector3(); + this.endPoint = new THREE.Vector3(); + this.collection = []; + this.deep = deep; } - if ( startPoint.y === endPoint.y ) { + select( startPoint, endPoint ) { - endPoint.y += Number.EPSILON; + this.startPoint = startPoint || this.startPoint; + this.endPoint = endPoint || this.endPoint; + this.collection = []; + this.updateFrustum( this.startPoint, this.endPoint ); + this.searchChildInFrustum( _frustum, this.scene ); + return this.collection; } - this.camera.updateProjectionMatrix(); - this.camera.updateMatrixWorld(); - - if ( this.camera.isPerspectiveCamera ) { - - tmpPoint.copy( startPoint ); - tmpPoint.x = Math.min( startPoint.x, endPoint.x ); - tmpPoint.y = Math.max( startPoint.y, endPoint.y ); - endPoint.x = Math.max( startPoint.x, endPoint.x ); - endPoint.y = Math.min( startPoint.y, endPoint.y ); - - vecNear.setFromMatrixPosition( this.camera.matrixWorld ); - vecTopLeft.copy( tmpPoint ); - vecTopRight.set( endPoint.x, tmpPoint.y, 0 ); - vecDownRight.copy( endPoint ); - vecDownLeft.set( tmpPoint.x, endPoint.y, 0 ); - - vecTopLeft.unproject( this.camera ); - vecTopRight.unproject( this.camera ); - vecDownRight.unproject( this.camera ); - vecDownLeft.unproject( this.camera ); - - vectemp1.copy( vecTopLeft ).sub( vecNear ); - vectemp2.copy( vecTopRight ).sub( vecNear ); - vectemp3.copy( vecDownRight ).sub( vecNear ); - vectemp1.normalize(); - vectemp2.normalize(); - vectemp3.normalize(); - - vectemp1.multiplyScalar( this.deep ); - vectemp2.multiplyScalar( this.deep ); - vectemp3.multiplyScalar( this.deep ); - vectemp1.add( vecNear ); - vectemp2.add( vecNear ); - vectemp3.add( vecNear ); - - var planes = frustum.planes; - - planes[ 0 ].setFromCoplanarPoints( vecNear, vecTopLeft, vecTopRight ); - planes[ 1 ].setFromCoplanarPoints( vecNear, vecTopRight, vecDownRight ); - planes[ 2 ].setFromCoplanarPoints( vecDownRight, vecDownLeft, vecNear ); - planes[ 3 ].setFromCoplanarPoints( vecDownLeft, vecTopLeft, vecNear ); - planes[ 4 ].setFromCoplanarPoints( vecTopRight, vecDownRight, vecDownLeft ); - planes[ 5 ].setFromCoplanarPoints( vectemp3, vectemp2, vectemp1 ); - planes[ 5 ].normal.multiplyScalar( - 1 ); - - } else if ( this.camera.isOrthographicCamera ) { - - var left = Math.min( startPoint.x, endPoint.x ); - var top = Math.max( startPoint.y, endPoint.y ); - var right = Math.max( startPoint.x, endPoint.x ); - var down = Math.min( startPoint.y, endPoint.y ); - - vecTopLeft.set( left, top, - 1 ); - vecTopRight.set( right, top, - 1 ); - vecDownRight.set( right, down, - 1 ); - vecDownLeft.set( left, down, - 1 ); - - vecFarTopLeft.set( left, top, 1 ); - vecFarTopRight.set( right, top, 1 ); - vecFarDownRight.set( right, down, 1 ); - vecFarDownLeft.set( left, down, 1 ); - - vecTopLeft.unproject( this.camera ); - vecTopRight.unproject( this.camera ); - vecDownRight.unproject( this.camera ); - vecDownLeft.unproject( this.camera ); - - vecFarTopLeft.unproject( this.camera ); - vecFarTopRight.unproject( this.camera ); - vecFarDownRight.unproject( this.camera ); - vecFarDownLeft.unproject( this.camera ); - - var planes = frustum.planes; - - planes[ 0 ].setFromCoplanarPoints( vecTopLeft, vecFarTopLeft, vecFarTopRight ); - planes[ 1 ].setFromCoplanarPoints( vecTopRight, vecFarTopRight, vecFarDownRight ); - planes[ 2 ].setFromCoplanarPoints( vecFarDownRight, vecFarDownLeft, vecDownLeft ); - planes[ 3 ].setFromCoplanarPoints( vecFarDownLeft, vecFarTopLeft, vecTopLeft ); - planes[ 4 ].setFromCoplanarPoints( vecTopRight, vecDownRight, vecDownLeft ); - planes[ 5 ].setFromCoplanarPoints( vecFarDownRight, vecFarTopRight, vecFarTopLeft ); - planes[ 5 ].normal.multiplyScalar( - 1 ); - - } else { - - console.error( 'THREE.SelectionBox: Unsupported camera type.' ); + updateFrustum( startPoint, endPoint ) { + + startPoint = startPoint || this.startPoint; + endPoint = endPoint || this.endPoint; // Avoid invalid frustum + + if ( startPoint.x === endPoint.x ) { + + endPoint.x += Number.EPSILON; + + } + + if ( startPoint.y === endPoint.y ) { + + endPoint.y += Number.EPSILON; + + } + + this.camera.updateProjectionMatrix(); + this.camera.updateMatrixWorld(); + + if ( this.camera.isPerspectiveCamera ) { + + _tmpPoint.copy( startPoint ); + + _tmpPoint.x = Math.min( startPoint.x, endPoint.x ); + _tmpPoint.y = Math.max( startPoint.y, endPoint.y ); + endPoint.x = Math.max( startPoint.x, endPoint.x ); + endPoint.y = Math.min( startPoint.y, endPoint.y ); + + _vecNear.setFromMatrixPosition( this.camera.matrixWorld ); + + _vecTopLeft.copy( _tmpPoint ); + + _vecTopRight.set( endPoint.x, _tmpPoint.y, 0 ); + + _vecDownRight.copy( endPoint ); + + _vecDownLeft.set( _tmpPoint.x, endPoint.y, 0 ); + + _vecTopLeft.unproject( this.camera ); + + _vecTopRight.unproject( this.camera ); + + _vecDownRight.unproject( this.camera ); + + _vecDownLeft.unproject( this.camera ); + + _vectemp1.copy( _vecTopLeft ).sub( _vecNear ); + + _vectemp2.copy( _vecTopRight ).sub( _vecNear ); + + _vectemp3.copy( _vecDownRight ).sub( _vecNear ); + + _vectemp1.normalize(); + + _vectemp2.normalize(); + + _vectemp3.normalize(); + + _vectemp1.multiplyScalar( this.deep ); + + _vectemp2.multiplyScalar( this.deep ); + + _vectemp3.multiplyScalar( this.deep ); + + _vectemp1.add( _vecNear ); + + _vectemp2.add( _vecNear ); + + _vectemp3.add( _vecNear ); + + const planes = _frustum.planes; + planes[ 0 ].setFromCoplanarPoints( _vecNear, _vecTopLeft, _vecTopRight ); + planes[ 1 ].setFromCoplanarPoints( _vecNear, _vecTopRight, _vecDownRight ); + planes[ 2 ].setFromCoplanarPoints( _vecDownRight, _vecDownLeft, _vecNear ); + planes[ 3 ].setFromCoplanarPoints( _vecDownLeft, _vecTopLeft, _vecNear ); + planes[ 4 ].setFromCoplanarPoints( _vecTopRight, _vecDownRight, _vecDownLeft ); + planes[ 5 ].setFromCoplanarPoints( _vectemp3, _vectemp2, _vectemp1 ); + planes[ 5 ].normal.multiplyScalar( - 1 ); + + } else if ( this.camera.isOrthographicCamera ) { + + const left = Math.min( startPoint.x, endPoint.x ); + const top = Math.max( startPoint.y, endPoint.y ); + const right = Math.max( startPoint.x, endPoint.x ); + const down = Math.min( startPoint.y, endPoint.y ); + + _vecTopLeft.set( left, top, - 1 ); + + _vecTopRight.set( right, top, - 1 ); + + _vecDownRight.set( right, down, - 1 ); + + _vecDownLeft.set( left, down, - 1 ); + + _vecFarTopLeft.set( left, top, 1 ); + + _vecFarTopRight.set( right, top, 1 ); + + _vecFarDownRight.set( right, down, 1 ); + + _vecFarDownLeft.set( left, down, 1 ); + + _vecTopLeft.unproject( this.camera ); + + _vecTopRight.unproject( this.camera ); + + _vecDownRight.unproject( this.camera ); + + _vecDownLeft.unproject( this.camera ); + + _vecFarTopLeft.unproject( this.camera ); + + _vecFarTopRight.unproject( this.camera ); + + _vecFarDownRight.unproject( this.camera ); + + _vecFarDownLeft.unproject( this.camera ); + + const planes = _frustum.planes; + planes[ 0 ].setFromCoplanarPoints( _vecTopLeft, _vecFarTopLeft, _vecFarTopRight ); + planes[ 1 ].setFromCoplanarPoints( _vecTopRight, _vecFarTopRight, _vecFarDownRight ); + planes[ 2 ].setFromCoplanarPoints( _vecFarDownRight, _vecFarDownLeft, _vecDownLeft ); + planes[ 3 ].setFromCoplanarPoints( _vecFarDownLeft, _vecFarTopLeft, _vecTopLeft ); + planes[ 4 ].setFromCoplanarPoints( _vecTopRight, _vecDownRight, _vecDownLeft ); + planes[ 5 ].setFromCoplanarPoints( _vecFarDownRight, _vecFarTopRight, _vecFarTopLeft ); + planes[ 5 ].normal.multiplyScalar( - 1 ); + + } else { + + console.error( 'THREE.SelectionBox: Unsupported camera type.' ); + + } } - }; + searchChildInFrustum( frustum, object ) { - SelectionBox.prototype.searchChildInFrustum = function ( frustum, object ) { + if ( object.isMesh || object.isLine || object.isPoints ) { - if ( object.isMesh || object.isLine || object.isPoints ) { + if ( object.material !== undefined ) { - if ( object.material !== undefined ) { + if ( object.geometry.boundingSphere === null ) object.geometry.computeBoundingSphere(); - if ( object.geometry.boundingSphere === null ) object.geometry.computeBoundingSphere(); + _center.copy( object.geometry.boundingSphere.center ); - center.copy( object.geometry.boundingSphere.center ); + _center.applyMatrix4( object.matrixWorld ); - center.applyMatrix4( object.matrixWorld ); + if ( frustum.containsPoint( _center ) ) { - if ( frustum.containsPoint( center ) ) { + this.collection.push( object ); - this.collection.push( object ); + } } } - } + if ( object.children.length > 0 ) { - if ( object.children.length > 0 ) { + for ( let x = 0; x < object.children.length; x ++ ) { - for ( var x = 0; x < object.children.length; x ++ ) { + this.searchChildInFrustum( frustum, object.children[ x ] ); - this.searchChildInFrustum( frustum, object.children[ x ] ); + } } } - }; + } - return SelectionBox; + THREE.SelectionBox = SelectionBox; } )(); diff --git a/examples/js/interactive/SelectionHelper.js b/examples/js/interactive/SelectionHelper.js index cbed617cf023e7..0cbcc5ec02c19e 100644 --- a/examples/js/interactive/SelectionHelper.js +++ b/examples/js/interactive/SelectionHelper.js @@ -1,79 +1,74 @@ -THREE.SelectionHelper = ( function () { +( function () { - function SelectionHelper( selectionBox, renderer, cssClassName ) { + class SelectionHelper { - this.element = document.createElement( 'div' ); - this.element.classList.add( cssClassName ); - this.element.style.pointerEvents = 'none'; + constructor( selectionBox, renderer, cssClassName ) { - this.renderer = renderer; - - this.startPoint = new THREE.Vector2(); - this.pointTopLeft = new THREE.Vector2(); - this.pointBottomRight = new THREE.Vector2(); - - this.isDown = false; - - this.renderer.domElement.addEventListener( 'pointerdown', function ( event ) { - - this.isDown = true; - this.onSelectStart( event ); - - }.bind( this ) ); - - this.renderer.domElement.addEventListener( 'pointermove', function ( event ) { + this.element = document.createElement( 'div' ); + this.element.classList.add( cssClassName ); + this.element.style.pointerEvents = 'none'; + this.renderer = renderer; + this.startPoint = new THREE.Vector2(); + this.pointTopLeft = new THREE.Vector2(); + this.pointBottomRight = new THREE.Vector2(); + this.isDown = false; + this.renderer.domElement.addEventListener( 'pointerdown', function ( event ) { - if ( this.isDown ) { + this.isDown = true; + this.onSelectStart( event ); - this.onSelectMove( event ); + }.bind( this ) ); + this.renderer.domElement.addEventListener( 'pointermove', function ( event ) { - } + if ( this.isDown ) { - }.bind( this ) ); + this.onSelectMove( event ); - this.renderer.domElement.addEventListener( 'pointerup', function ( event ) { + } - this.isDown = false; - this.onSelectOver( event ); + }.bind( this ) ); + this.renderer.domElement.addEventListener( 'pointerup', function ( event ) { - }.bind( this ) ); + this.isDown = false; + this.onSelectOver( event ); - } + }.bind( this ) ); - SelectionHelper.prototype.onSelectStart = function ( event ) { + } - this.renderer.domElement.parentElement.appendChild( this.element ); + onSelectStart( event ) { - this.element.style.left = event.clientX + 'px'; - this.element.style.top = event.clientY + 'px'; - this.element.style.width = '0px'; - this.element.style.height = '0px'; + this.renderer.domElement.parentElement.appendChild( this.element ); + this.element.style.left = event.clientX + 'px'; + this.element.style.top = event.clientY + 'px'; + this.element.style.width = '0px'; + this.element.style.height = '0px'; + this.startPoint.x = event.clientX; + this.startPoint.y = event.clientY; - this.startPoint.x = event.clientX; - this.startPoint.y = event.clientY; + } - }; + onSelectMove( event ) { - SelectionHelper.prototype.onSelectMove = function ( event ) { + this.pointBottomRight.x = Math.max( this.startPoint.x, event.clientX ); + this.pointBottomRight.y = Math.max( this.startPoint.y, event.clientY ); + this.pointTopLeft.x = Math.min( this.startPoint.x, event.clientX ); + this.pointTopLeft.y = Math.min( this.startPoint.y, event.clientY ); + this.element.style.left = this.pointTopLeft.x + 'px'; + this.element.style.top = this.pointTopLeft.y + 'px'; + this.element.style.width = this.pointBottomRight.x - this.pointTopLeft.x + 'px'; + this.element.style.height = this.pointBottomRight.y - this.pointTopLeft.y + 'px'; - this.pointBottomRight.x = Math.max( this.startPoint.x, event.clientX ); - this.pointBottomRight.y = Math.max( this.startPoint.y, event.clientY ); - this.pointTopLeft.x = Math.min( this.startPoint.x, event.clientX ); - this.pointTopLeft.y = Math.min( this.startPoint.y, event.clientY ); + } - this.element.style.left = this.pointTopLeft.x + 'px'; - this.element.style.top = this.pointTopLeft.y + 'px'; - this.element.style.width = ( this.pointBottomRight.x - this.pointTopLeft.x ) + 'px'; - this.element.style.height = ( this.pointBottomRight.y - this.pointTopLeft.y ) + 'px'; + onSelectOver() { - }; + this.element.parentElement.removeChild( this.element ); - SelectionHelper.prototype.onSelectOver = function () { + } - this.element.parentElement.removeChild( this.element ); - - }; + } - return SelectionHelper; + THREE.SelectionHelper = SelectionHelper; } )(); diff --git a/examples/js/libs/chevrotain.min.js b/examples/js/libs/chevrotain.min.js index b13f38de01c1f9..ea22f5989a8e9f 100644 --- a/examples/js/libs/chevrotain.min.js +++ b/examples/js/libs/chevrotain.min.js @@ -1,2 +1,3 @@ -/*! chevrotain - v4.6.0 */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("chevrotain",[],e):"object"==typeof exports?exports.chevrotain=e():t.chevrotain=e()}("undefined"!=typeof self?self:this,function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=18)}([function(t,e,n){"use strict";function r(t){return t&&0===t.length}function i(t){return null==t?[]:Object.keys(t)}function o(t){for(var e=[],n=Object.keys(t),r=0;r0})},e.expandCategories=a,e.assignTokenDefaultProps=s,e.assignCategoriesTokensProp=u,e.assignCategoriesMapProp=c,e.singleAssignCategoriesToksMap=p,e.hasShortKeyProperty=l,e.hasCategoriesProperty=h,e.hasExtendingTokensTypesProperty=f,e.hasExtendingTokensTypesMapProperty=d,e.hasTokenNameProperty=E,e.isTokenType=function(t){return r.has(t,"tokenTypeIdx")}},function(t,e,n){"use strict";var r,i=this&&this.__extends||(r=function(t,e){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)},function(t,e){function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)});Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),a=n(1),s=n(5),u=n(2);e.isSequenceProd=function(t){return t instanceof a.Flat||t instanceof a.Option||t instanceof a.Repetition||t instanceof a.RepetitionMandatory||t instanceof a.RepetitionMandatoryWithSeparator||t instanceof a.RepetitionWithSeparator||t instanceof a.Terminal||t instanceof a.Rule},e.isOptionalProd=function t(e,n){return void 0===n&&(n=[]),!!(e instanceof a.Option||e instanceof a.Repetition||e instanceof a.RepetitionWithSeparator)||(e instanceof a.Alternation?o.some(e.definition,function(e){return t(e,n)}):!(e instanceof a.NonTerminal&&o.contains(n,e))&&e instanceof a.AbstractProduction&&(e instanceof a.NonTerminal&&n.push(e),o.every(e.definition,function(e){return t(e,n)})))},e.isBranchingProd=function(t){return t instanceof a.Alternation},e.getProductionDslName=function(t){if(t instanceof a.NonTerminal)return"SUBRULE";if(t instanceof a.Option)return"OPTION";if(t instanceof a.Alternation)return"OR";if(t instanceof a.RepetitionMandatory)return"AT_LEAST_ONE";if(t instanceof a.RepetitionMandatoryWithSeparator)return"AT_LEAST_ONE_SEP";if(t instanceof a.RepetitionWithSeparator)return"MANY_SEP";if(t instanceof a.Repetition)return"MANY";if(t instanceof a.Terminal)return"CONSUME";throw Error("non exhaustive match")};var c=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.separator="-",e.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]},e}return i(e,t),e.prototype.visitTerminal=function(t){var e=u.tokenName(t.terminalType)+this.separator+"Terminal";o.has(this.dslMethods,e)||(this.dslMethods[e]=[]),this.dslMethods[e].push(t)},e.prototype.visitNonTerminal=function(t){var e=t.nonTerminalName+this.separator+"Terminal";o.has(this.dslMethods,e)||(this.dslMethods[e]=[]),this.dslMethods[e].push(t)},e.prototype.visitOption=function(t){this.dslMethods.option.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.dslMethods.repetitionWithSeparator.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.dslMethods.repetitionMandatory.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.dslMethods.repetitionMandatoryWithSeparator.push(t)},e.prototype.visitRepetition=function(t){this.dslMethods.repetition.push(t)},e.prototype.visitAlternation=function(t){this.dslMethods.alternation.push(t)},e}(s.GAstVisitor);e.DslMethodsCollectorVisitor=c},function(t,e,n){"use strict";function r(t,e,n){return n|e|t}Object.defineProperty(e,"__esModule",{value:!0}),e.BITS_FOR_METHOD_IDX=4,e.BITS_FOR_OCCURRENCE_IDX=4,e.BITS_FOR_RULE_IDX=24,e.BITS_FOR_ALT_IDX=8,e.OR_IDX=1<")+a}},Object.freeze(e.defaultParserErrorProvider),e.defaultGrammarResolverErrorProvider={buildRuleNotFoundError:function(t,e){return"Invalid grammar, reference to a rule which is not defined: ->"+e.nonTerminalName+"<-\ninside top level rule: ->"+t.name+"<-"}},e.defaultGrammarValidatorErrorProvider={buildDuplicateFoundError:function(t,e){var n,i=t.name,u=o.first(e),c=u.idx,p=s.getProductionDslName(u),l=(n=u)instanceof a.Terminal?r.tokenName(n.terminalType):n instanceof a.NonTerminal?n.nonTerminalName:"",h="->"+p+"<- with numerical suffix: ->"+c+"<-\n "+(l?"and argument: ->"+l+"<-":"")+"\n appears more than once ("+e.length+" times) in the top level rule: ->"+i+"<-.\n "+(0===c?"Also note that numerical suffix 0 means "+p+" without any suffix.":"")+"\n To fix this make sure each usage of "+p+" "+(l?"with the argument: ->"+l+"<-":"")+"\n in the rule ->"+i+"<- has a different occurrence index (0-5), as that combination acts as a unique\n position key in the grammar, which is needed by the parsing engine.\n \n For further details see: https://sap.github.io/chevrotain/docs/FAQ.html#NUMERICAL_SUFFIXES \n ";return h=(h=h.replace(/[ \t]+/g," ")).replace(/\s\s+/g,"\n")},buildInvalidNestedRuleNameError:function(t,e){return"Invalid nested rule name: ->"+e.name+"<- inside rule: ->"+t.name+"<-\nit must match the pattern: ->"+u.validNestedRuleName.toString()+"<-.\nNote that this means a nested rule name must start with the '$'(dollar) sign."},buildDuplicateNestedRuleNameError:function(t,e){return"Duplicate nested rule name: ->"+o.first(e).name+"<- inside rule: ->"+t.name+"<-\nA nested name must be unique in the scope of a top level grammar rule."},buildNamespaceConflictError:function(t){return"Namespace conflict found in grammar.\nThe grammar has both a Terminal(Token) and a Non-Terminal(Rule) named: <"+t.name+">.\nTo resolve this make sure each Terminal and Non-Terminal names are unique\nThis is easy to accomplish by using the convention that Terminal names start with an uppercase letter\nand Non-Terminal names start with a lower case letter."},buildAlternationPrefixAmbiguityError:function(t){var e=o.map(t.prefixPath,function(t){return r.tokenLabel(t)}).join(", "),n=0===t.alternation.idx?"":t.alternation.idx;return"Ambiguous alternatives: <"+t.ambiguityIndices.join(" ,")+"> due to common lookahead prefix\nin inside <"+t.topLevelRule.name+"> Rule,\n<"+e+"> may appears as a prefix path in all these alternatives.\nhttps://sap.github.io/chevrotain/docs/guide/resolving_grammar_errors.html#COMMON_PREFIX\nFor Further details."},buildAlternationAmbiguityError:function(t){var e=o.map(t.prefixPath,function(t){return r.tokenLabel(t)}).join(", "),n=0===t.alternation.idx?"":t.alternation.idx,i="Ambiguous alternatives: <"+t.ambiguityIndices.join(" ,")+"> in inside <"+t.topLevelRule.name+"> Rule,\n<"+e+"> may appears as a prefix path in all these alternatives.\n",a=c.VERSION.replace(/\./g,"_");return i=i+"To Resolve this, try one of of the following: \n1. Refactor your grammar to be LL(K) for the current value of k (by default k="+p.DEFAULT_PARSER_CONFIG.maxLookahead+"})\n2. Increase the value of K for your grammar by providing a larger 'maxLookahead' value in the parser's config\n3. This issue can be ignored (if you know what you are doing...), see https://sap.github.io/chevrotain/documentation/"+a+"/interfaces/iparserconfig.html#ignoredissues for more details\n"},buildEmptyRepetitionError:function(t){var e=s.getProductionDslName(t.repetition);return 0!==t.repetition.idx&&(e+=t.repetition.idx),"The repetition <"+e+"> within Rule <"+t.topLevelRule.name+"> can never consume any tokens.\nThis could lead to an infinite loop."},buildTokenNameError:function(t){return"Invalid Grammar Token name: ->"+r.tokenName(t.tokenType)+"<- it must match the pattern: ->"+t.expectedPattern.toString()+"<-"},buildEmptyAlternationError:function(t){return"Ambiguous empty alternative: <"+(t.emptyChoiceIdx+1)+"> in inside <"+t.topLevelRule.name+"> Rule.\nOnly the last alternative may be an empty alternative."},buildTooManyAlternativesError:function(t){return"An Alternation cannot have more than 256 alternatives:\n inside <"+t.topLevelRule.name+"> Rule.\n has "+(t.alternation.definition.length+1)+" alternatives."},buildLeftRecursionError:function(t){var e=t.topLevelRule.name;return"Left Recursion found in grammar.\nrule: <"+e+"> can be invoked from itself (directly or indirectly)\nwithout consuming any Tokens. The grammar path that causes this is: \n "+(e+" --\x3e "+i.map(t.leftRecursionPath,function(t){return t.name}).concat([e]).join(" --\x3e "))+"\n To fix this refactor your grammar to remove the left recursion.\nsee: https://en.wikipedia.org/wiki/LL_parser#Left_Factoring."},buildInvalidRuleNameError:function(t){return"Invalid grammar rule name: ->"+t.topLevelRule.name+"<- it must match the pattern: ->"+t.expectedPattern.toString()+"<-"},buildDuplicateRuleNameError:function(t){return"Duplicate definition, rule: ->"+(t.topLevelRule instanceof a.Rule?t.topLevelRule.name:t.topLevelRule)+"<- is already defined in the grammar: ->"+t.grammarName+"<-"}}},function(t,e,n){"use strict";var r,i=this&&this.__extends||(r=function(t,e){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)},function(t,e){function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)});Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),a=n(0),s=n(3),u=n(8),c=n(2),p=n(12),l=n(16),h=n(13),f=n(1),d=n(5);function E(t){return u.getProductionDslName(t)+"_#_"+t.idx+"_#_"+m(t)}function m(t){return t instanceof f.Terminal?c.tokenName(t.terminalType):t instanceof f.NonTerminal?t.nonTerminalName:""}e.validateGrammar=function(t,e,n,r,i,p){var h=o.map(t,function(t){return function(t,e){var n=new y;t.accept(n);var r=n.allProductions,i=o.groupBy(r,E),a=o.pick(i,function(t){return t.length>1});return o.map(o.values(a),function(n){var r=o.first(n),i=e.buildDuplicateFoundError(t,n),a=u.getProductionDslName(r),c={message:i,type:s.ParserDefinitionErrorType.DUPLICATE_PRODUCTIONS,ruleName:t.name,dslName:a,occurrence:r.idx},p=m(r);return p&&(c.parameter=p),c})}(t,i)}),f=o.map(t,function(t){return R(t,t,i)}),d=[],A=[],N=[];a.every(f,a.isEmpty)&&(d=a.map(t,function(t){return O(t,i)}),A=a.map(t,function(t){return S(t,e,r,i)}),N=k(t,e,i));var I=function(t,e,n){var r=[],i=a.map(e,function(t){return c.tokenName(t)});return a.forEach(t,function(t){var e=t.name;if(a.contains(i,e)){var o=n.buildNamespaceConflictError(t);r.push({message:o,type:s.ParserDefinitionErrorType.CONFLICT_TOKENS_RULES_NAMESPACE,ruleName:e})}}),r}(t,n,i),P=o.map(n,function(t){return g(t,i)}),x=function(t,e){var n=[];return a.forEach(t,function(t){var r=new l.NamedDSLMethodsCollectorVisitor("");t.accept(r);var i=a.map(r.result,function(t){return t.orgProd});n.push(a.map(i,function(n){return v(t,n,e)}))}),a.flatten(n)}(t,i),C=function(t,e){var n=[];return a.forEach(t,function(t){var r=new l.NamedDSLMethodsCollectorVisitor("");t.accept(r);var i=a.groupBy(r.result,function(t){return t.name}),o=a.pick(i,function(t){return t.length>1});a.forEach(a.values(o),function(r){var i=a.map(r,function(t){return t.orgProd}),o=e.buildDuplicateNestedRuleNameError(t,i);n.push({message:o,type:s.ParserDefinitionErrorType.DUPLICATE_NESTED_NAME,ruleName:t.name})})}),n}(t,i),M=a.map(t,function(t){return L(t,i)}),F=a.map(t,function(t){return T(t,i)}),b=a.map(t,function(e){return _(e,t,p,i)});return o.flatten(h.concat(P,x,C,N,f,d,A,I,M,F,b))},e.identifyProductionForDuplicates=E;var y=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.allProductions=[],e}return i(e,t),e.prototype.visitNonTerminal=function(t){this.allProductions.push(t)},e.prototype.visitOption=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e.prototype.visitAlternation=function(t){this.allProductions.push(t)},e.prototype.visitTerminal=function(t){this.allProductions.push(t)},e}(d.GAstVisitor);function T(t,n){var r=[],i=t.name;return i.match(e.validTermsPattern)||r.push({message:n.buildInvalidRuleNameError({topLevelRule:t,expectedPattern:e.validTermsPattern}),type:s.ParserDefinitionErrorType.INVALID_RULE_NAME,ruleName:i}),r}function v(t,n,r){var i,o=[];return n.name.match(e.validNestedRuleName)||(i=r.buildInvalidNestedRuleNameError(t,n),o.push({message:i,type:s.ParserDefinitionErrorType.INVALID_NESTED_RULE_NAME,ruleName:t.name})),o}function g(t,n){var r=[];return c.tokenName(t).match(e.validTermsPattern)||r.push({message:n.buildTokenNameError({tokenType:t,expectedPattern:e.validTermsPattern}),type:s.ParserDefinitionErrorType.INVALID_TOKEN_NAME}),r}function _(t,e,n,r){var i=[];if(a.reduce(e,function(e,n){return n.name===t.name?e+1:e},0)>1){var o=r.buildDuplicateRuleNameError({topLevelRule:t,grammarName:n});i.push({message:o,type:s.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:t.name})}return i}function R(t,e,n,r){void 0===r&&(r=[]);var i=[],a=A(e.definition);if(o.isEmpty(a))return[];var u=t.name;o.contains(a,t)&&i.push({message:n.buildLeftRecursionError({topLevelRule:t,leftRecursionPath:r}),type:s.ParserDefinitionErrorType.LEFT_RECURSION,ruleName:u});var c=o.difference(a,r.concat([t])),p=o.map(c,function(e){var i=o.cloneArr(r);return i.push(e),R(t,e,n,i)});return i.concat(o.flatten(p))}function A(t){var e=[];if(o.isEmpty(t))return e;var n=o.first(t);if(n instanceof f.NonTerminal)e.push(n.referencedRule);else if(n instanceof f.Flat||n instanceof f.Option||n instanceof f.RepetitionMandatory||n instanceof f.RepetitionMandatoryWithSeparator||n instanceof f.RepetitionWithSeparator||n instanceof f.Repetition)e=e.concat(A(n.definition));else if(n instanceof f.Alternation)e=o.flatten(o.map(n.definition,function(t){return A(t.definition)}));else if(!(n instanceof f.Terminal))throw Error("non exhaustive match");var r=u.isOptionalProd(n),i=t.length>1;if(r&&i){var a=o.drop(t);return e.concat(A(a))}return e}e.OccurrenceValidationCollector=y,e.validTermsPattern=/^[a-zA-Z_]\w*$/,e.validNestedRuleName=new RegExp(e.validTermsPattern.source.replace("^","^\\$")),e.validateRuleName=T,e.validateNestedRuleName=v,e.validateTokenName=g,e.validateRuleDoesNotAlreadyExist=_,e.validateRuleIsOverridden=function(t,e,n){var r,i=[];return o.contains(e,t)||(r="Invalid rule override, rule: ->"+t+"<- cannot be overridden in the grammar: ->"+n+"<-as it is not defined in any of the super grammars ",i.push({message:r,type:s.ParserDefinitionErrorType.INVALID_RULE_OVERRIDE,ruleName:t})),i},e.validateNoLeftRecursion=R,e.getFirstNoneTerminal=A;var N=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.alternations=[],e}return i(e,t),e.prototype.visitAlternation=function(t){this.alternations.push(t)},e}(d.GAstVisitor);function O(t,e){var n=new N;t.accept(n);var r=n.alternations;return o.reduce(r,function(n,r){var i=o.dropRight(r.definition),a=o.map(i,function(n,i){var a=h.nextPossibleTokensAfter([n],[],null,1);return o.isEmpty(a)?{message:e.buildEmptyAlternationError({topLevelRule:t,alternation:r,emptyChoiceIdx:i}),type:s.ParserDefinitionErrorType.NONE_LAST_EMPTY_ALT,ruleName:t.name,occurrence:r.idx,alternative:i+1}:null});return n.concat(o.compact(a))},[])}function S(t,e,n,r){var i=new N;t.accept(i);var c=i.alternations,l=n[t.name];return l&&(c=a.reject(c,function(t){return l[u.getProductionDslName(t)+(0===t.idx?"":t.idx)]})),o.reduce(c,function(n,i){var u=i.idx,c=p.getLookaheadPathsForOr(u,t,e),l=function(t,e,n,r){var i=[],u=a.reduce(t,function(e,n,r){return a.forEach(n,function(n){var o=[r];a.forEach(t,function(t,e){r!==e&&p.containsPath(t,n)&&o.push(e)}),o.length>1&&!p.containsPath(i,n)&&(i.push(n),e.push({alts:o,path:n}))}),e},[]);return o.map(u,function(t){var i=a.map(t.alts,function(t){return t+1}),o=r.buildAlternationAmbiguityError({topLevelRule:n,alternation:e,ambiguityIndices:i,prefixPath:t.path});return{message:o,type:s.ParserDefinitionErrorType.AMBIGUOUS_ALTS,ruleName:n.name,occurrence:e.idx,alternatives:[t.alts]}})}(c,i,t,r),h=P(c,i,t,r);return n.concat(l,h)},[])}e.validateEmptyOrAlternative=O,e.validateAmbiguousAlternationAlternatives=S;var I=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.allProductions=[],e}return i(e,t),e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e}(d.GAstVisitor);function L(t,e){var n=new N;t.accept(n);var r=n.alternations;return o.reduce(r,function(n,r){return r.definition.length>255&&n.push({message:e.buildTooManyAlternativesError({topLevelRule:t,alternation:r}),type:s.ParserDefinitionErrorType.TOO_MANY_ALTS,ruleName:t.name,occurrence:r.idx}),n},[])}function k(t,e,n){var r=[];return a.forEach(t,function(t){var i=new I;t.accept(i);var o=i.allProductions;a.forEach(o,function(i){var o=p.getProdType(i),u=i.idx,c=p.getLookaheadPathsForOptionalProd(u,t,o,e)[0];if(a.isEmpty(a.flatten(c))){var l=n.buildEmptyRepetitionError({topLevelRule:t,repetition:i});r.push({message:l,type:s.ParserDefinitionErrorType.NO_NON_EMPTY_LOOKAHEAD,ruleName:t.name})}})}),r}function P(t,e,n,r){var i=[],o=a.reduce(t,function(t,e,n){var r=a.map(e,function(t){return{idx:n,path:t}});return t.concat(r)},[]);return a.forEach(o,function(t){var u=t.idx,c=t.path,l=a.findAll(o,function(t){return t.idx=0;L--){var k={idx:d,def:T.definition[L].definition.concat(a.drop(f)),ruleStack:E,occurrenceStack:m};l.push(k),l.push("EXIT_ALTERNATIVE")}else if(T instanceof c.Flat)l.push({idx:d,def:T.definition.concat(a.drop(f)),ruleStack:E,occurrenceStack:m});else{if(!(T instanceof c.Rule))throw Error("non exhaustive match");l.push(y(T,d,E,m))}}}else o&&a.last(l).idx<=u&&l.pop()}return p}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),i=n(1),o=function(){function t(){}return t.prototype.walk=function(t,e){var n=this;void 0===e&&(e=[]),r.forEach(t.definition,function(o,a){var s=r.drop(t.definition,a+1);if(o instanceof i.NonTerminal)n.walkProdRef(o,s,e);else if(o instanceof i.Terminal)n.walkTerminal(o,s,e);else if(o instanceof i.Flat)n.walkFlat(o,s,e);else if(o instanceof i.Option)n.walkOption(o,s,e);else if(o instanceof i.RepetitionMandatory)n.walkAtLeastOne(o,s,e);else if(o instanceof i.RepetitionMandatoryWithSeparator)n.walkAtLeastOneSep(o,s,e);else if(o instanceof i.RepetitionWithSeparator)n.walkManySep(o,s,e);else if(o instanceof i.Repetition)n.walkMany(o,s,e);else{if(!(o instanceof i.Alternation))throw Error("non exhaustive match");n.walkOr(o,s,e)}})},t.prototype.walkTerminal=function(t,e,n){},t.prototype.walkProdRef=function(t,e,n){},t.prototype.walkFlat=function(t,e,n){var r=e.concat(n);this.walk(t,r)},t.prototype.walkOption=function(t,e,n){var r=e.concat(n);this.walk(t,r)},t.prototype.walkAtLeastOne=function(t,e,n){var r=[new i.Option({definition:t.definition})].concat(e,n);this.walk(t,r)},t.prototype.walkAtLeastOneSep=function(t,e,n){var r=a(t,e,n);this.walk(t,r)},t.prototype.walkMany=function(t,e,n){var r=[new i.Option({definition:t.definition})].concat(e,n);this.walk(t,r)},t.prototype.walkManySep=function(t,e,n){var r=a(t,e,n);this.walk(t,r)},t.prototype.walkOr=function(t,e,n){var o=this,a=e.concat(n);r.forEach(t.definition,function(t){var e=new i.Flat({definition:[t]});o.walk(e,a)})},t}();function a(t,e,n){return[new i.Option({definition:[new i.Terminal({terminalType:t.separator})].concat(t.definition)})].concat(e,n)}e.RestWalker=o},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(27),i=n(0),o=n(7),a=n(20);!function(t){t[t.MISSING_PATTERN=0]="MISSING_PATTERN",t[t.INVALID_PATTERN=1]="INVALID_PATTERN",t[t.EOI_ANCHOR_FOUND=2]="EOI_ANCHOR_FOUND",t[t.UNSUPPORTED_FLAGS_FOUND=3]="UNSUPPORTED_FLAGS_FOUND",t[t.DUPLICATE_PATTERNS_FOUND=4]="DUPLICATE_PATTERNS_FOUND",t[t.INVALID_GROUP_TYPE_FOUND=5]="INVALID_GROUP_TYPE_FOUND",t[t.PUSH_MODE_DOES_NOT_EXIST=6]="PUSH_MODE_DOES_NOT_EXIST",t[t.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE=7]="MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE",t[t.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY=8]="MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY",t[t.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST=9]="MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST",t[t.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED=10]="LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED",t[t.SOI_ANCHOR_FOUND=11]="SOI_ANCHOR_FOUND",t[t.EMPTY_MATCH_PATTERN=12]="EMPTY_MATCH_PATTERN",t[t.NO_LINE_BREAKS_FLAGS=13]="NO_LINE_BREAKS_FLAGS",t[t.UNREACHABLE_PATTERN=14]="UNREACHABLE_PATTERN",t[t.IDENTIFY_TERMINATOR=15]="IDENTIFY_TERMINATOR",t[t.CUSTOM_LINE_BREAK=16]="CUSTOM_LINE_BREAK"}(e.LexerDefinitionErrorType||(e.LexerDefinitionErrorType={}));var s={deferDefinitionErrorsHandling:!1,positionTracking:"full",lineTerminatorsPattern:/\n|\r\n?/g,lineTerminatorCharacters:["\n","\r"],ensureOptimizations:!1,safeMode:!1,errorMessageProvider:a.defaultLexerErrorProvider};Object.freeze(s);var u=function(){function t(t,e){var n=this;if(void 0===e&&(e=s),this.lexerDefinition=t,this.lexerDefinitionErrors=[],this.lexerDefinitionWarning=[],this.patternIdxToConfig={},this.charCodeToPatternIdxToConfig={},this.modes=[],this.emptyGroups={},this.config=void 0,this.trackStartLines=!0,this.trackEndLines=!0,this.hasCustom=!1,this.canModeBeOptimized={},"boolean"==typeof e)throw Error("The second argument to the Lexer constructor is now an ILexerConfig Object.\na boolean 2nd argument is no longer supported");if(this.config=i.merge(s,e),this.config.lineTerminatorsPattern===s.lineTerminatorsPattern)this.config.lineTerminatorsPattern=r.LineTerminatorOptimizedTester;else if(this.config.lineTerminatorCharacters===s.lineTerminatorCharacters)throw Error("Error: Missing property on the Lexer config.\n\tFor details See: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#MISSING_LINE_TERM_CHARS");if(e.safeMode&&e.ensureOptimizations)throw Error('"safeMode" and "ensureOptimizations" flags are mutually exclusive.');this.trackStartLines=/full|onlyStart/i.test(this.config.positionTracking),this.trackEndLines=/full/i.test(this.config.positionTracking);var a,u=!0;i.isArray(t)?((a={modes:{}}).modes[r.DEFAULT_MODE]=i.cloneArr(t),a[r.DEFAULT_MODE]=r.DEFAULT_MODE):(u=!1,a=i.cloneObj(t)),this.lexerDefinitionErrors=this.lexerDefinitionErrors.concat(r.performRuntimeChecks(a,this.trackStartLines,this.config.lineTerminatorCharacters)),this.lexerDefinitionWarning=this.lexerDefinitionWarning.concat(r.performWarningRuntimeChecks(a,this.trackStartLines,this.config.lineTerminatorCharacters)),a.modes=a.modes?a.modes:{},i.forEach(a.modes,function(t,e){a.modes[e]=i.reject(t,function(t){return i.isUndefined(t)})});var c=i.keys(a.modes);if(i.forEach(a.modes,function(t,a){if(n.modes.push(a),n.lexerDefinitionErrors=n.lexerDefinitionErrors.concat(r.validatePatterns(t,c)),i.isEmpty(n.lexerDefinitionErrors)){o.augmentTokenTypes(t);var s=r.analyzeTokenTypes(t,{lineTerminatorCharacters:n.config.lineTerminatorCharacters,positionTracking:e.positionTracking,ensureOptimizations:e.ensureOptimizations,safeMode:e.safeMode});n.patternIdxToConfig[a]=s.patternIdxToConfig,n.charCodeToPatternIdxToConfig[a]=s.charCodeToPatternIdxToConfig,n.emptyGroups=i.merge(n.emptyGroups,s.emptyGroups),n.hasCustom=s.hasCustom||n.hasCustom,n.canModeBeOptimized[a]=s.canBeOptimized}}),this.defaultMode=a.defaultMode,!i.isEmpty(this.lexerDefinitionErrors)&&!this.config.deferDefinitionErrorsHandling){var p=i.map(this.lexerDefinitionErrors,function(t){return t.message}).join("-----------------------\n");throw new Error("Errors detected in definition of Lexer:\n"+p)}if(i.forEach(this.lexerDefinitionWarning,function(t){i.PRINT_WARNING(t.message)}),r.SUPPORT_STICKY?(this.chopInput=i.IDENTITY,this.match=this.matchWithTest):(this.updateLastIndex=i.NOOP,this.match=this.matchWithExec),u&&(this.handleModes=i.NOOP),!1===this.trackStartLines&&(this.computeNewColumn=i.IDENTITY),!1===this.trackEndLines&&(this.updateTokenEndLineColumnLocation=i.NOOP),/full/i.test(this.config.positionTracking))this.createTokenInstance=this.createFullToken;else if(/onlyStart/i.test(this.config.positionTracking))this.createTokenInstance=this.createStartOnlyToken;else{if(!/onlyOffset/i.test(this.config.positionTracking))throw Error('Invalid config option: "'+this.config.positionTracking+'"');this.createTokenInstance=this.createOffsetOnlyToken}this.hasCustom?this.addToken=this.addTokenUsingPush:this.addToken=this.addTokenUsingMemberAccess;var l=i.reduce(this.canModeBeOptimized,function(t,e,n){return!1===e&&t.push(n),t},[]);if(e.ensureOptimizations&&!i.isEmpty(l))throw Error("Lexer Modes: < "+l.join(", ")+' > cannot be optimized.\n\t Disable the "ensureOptimizations" lexer config flag to silently ignore this and run the lexer in an un-optimized mode.\n\t Or inspect the console log for details on how to resolve these issues.')}return t.prototype.tokenize=function(t,e){if(void 0===e&&(e=this.defaultMode),!i.isEmpty(this.lexerDefinitionErrors)){var n=i.map(this.lexerDefinitionErrors,function(t){return t.message}).join("-----------------------\n");throw new Error("Unable to Tokenize because Errors detected in definition of Lexer:\n"+n)}return this.tokenizeInternal(t,e)},t.prototype.tokenizeInternal=function(t,e){var n,o,a,s,u,c,p,l,h,f,d,E,m=this,y=t,T=y.length,v=0,g=0,_=this.hasCustom?0:Math.floor(t.length/10),R=new Array(_),A=[],N=this.trackStartLines?1:void 0,O=this.trackStartLines?1:void 0,S=r.cloneEmptyGroups(this.emptyGroups),I=this.trackStartLines,L=this.config.lineTerminatorsPattern,k=0,P=[],x=[],C=[],M=[];Object.freeze(M);var F,b=void 0,D=function(t){if(1===C.length&&void 0===t.tokenType.PUSH_MODE){var e=m.config.errorMessageProvider.buildUnableToPopLexerModeMessage(t);A.push({offset:t.startOffset,line:void 0!==t.startLine?t.startLine:void 0,column:void 0!==t.startColumn?t.startColumn:void 0,length:t.image.length,message:e})}else{C.pop();var n=i.last(C);P=m.patternIdxToConfig[n],x=m.charCodeToPatternIdxToConfig[n],k=P.length;var r=m.canModeBeOptimized[n]&&!1===m.config.safeMode;b=x&&r?function(t){var e=x[t];return void 0===e?M:e}:function(){return P}}};function w(t){C.push(t),x=this.charCodeToPatternIdxToConfig[t],P=this.patternIdxToConfig[t],k=P.length,k=P.length;var e=this.canModeBeOptimized[t]&&!1===this.config.safeMode;b=x&&e?function(t){var e=x[t];return void 0===e?M:e}:function(){return P}}for(w.call(this,e);vu.length&&(u=a,F=W)}break}}if(null!==u){if(c=u.length,void 0!==(p=F.group)&&(l=F.tokenTypeIdx,h=this.createTokenInstance(u,v,l,F.tokenType,N,O,c),!1===p?g=this.addToken(R,g,h):S[p].push(h)),t=this.chopInput(t,c),v+=c,O=this.computeNewColumn(O,c),!0===I&&!0===F.canLineTerminator){var V=0,Y=void 0,H=void 0;L.lastIndex=0;do{!0===(Y=L.test(u))&&(H=L.lastIndex-1,V++)}while(Y);0!==V&&(N+=V,O=c-H,this.updateTokenEndLineColumnLocation(h,p,H,V,N,O,c))}this.handleModes(F,D,w,h)}else{for(var X=v,z=N,q=O,$=!1;!$&&v1;o.forEach(t.definition,function(r,i){if(!o.isUndefined(r.name)){var a=r.definition;a=n?[new u.Option({definition:r.definition})]:r.definition;var c=s.getKeyForAltIndex(e.ruleIdx,s.OR_IDX,t.idx,i);e.result.push({def:a,key:c,name:r.name,orgProd:r})}})},e}(c.GAstVisitor);e.NamedDSLMethodsCollectorVisitor=p,e.analyzeCst=function(t,e){var n={dictDef:new a.HashTable,allRuleNames:[]};return o.forEach(t,function(t){var r=e.get(t.name);n.allRuleNames.push(t.name);var i=new p(r);t.accept(i),o.forEach(i.result,function(e){e.def,e.key;var r=e.name;n.allRuleNames.push(t.name+r)})}),n}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.VERSION="4.6.0"},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=n(15),o=n(2),a=n(6),s=n(17),u=n(10),c=n(39),p=n(5),l=n(1),h=n(24),f=n(40),d=n(20),E={};E.VERSION=s.VERSION,E.Parser=r.Parser,E.CstParser=r.CstParser,E.EmbeddedActionsParser=r.EmbeddedActionsParser;E.ParserDefinitionErrorType=r.ParserDefinitionErrorType,E.Lexer=i.Lexer,E.LexerDefinitionErrorType=i.LexerDefinitionErrorType,E.EOF=o.EOF,E.tokenName=o.tokenName,E.tokenLabel=o.tokenLabel,E.tokenMatcher=o.tokenMatcher,E.createToken=o.createToken,E.createTokenInstance=o.createTokenInstance,E.EMPTY_ALT=r.EMPTY_ALT,E.defaultParserErrorProvider=u.defaultParserErrorProvider,E.isRecognitionException=a.isRecognitionException,E.EarlyExitException=a.EarlyExitException,E.MismatchedTokenException=a.MismatchedTokenException,E.NotAllInputParsedException=a.NotAllInputParsedException,E.NoViableAltException=a.NoViableAltException,E.defaultLexerErrorProvider=d.defaultLexerErrorProvider,E.Flat=l.Flat,E.Repetition=l.Repetition,E.RepetitionWithSeparator=l.RepetitionWithSeparator,E.RepetitionMandatory=l.RepetitionMandatory,E.RepetitionMandatoryWithSeparator=l.RepetitionMandatoryWithSeparator,E.Option=l.Option,E.Alternation=l.Alternation,E.NonTerminal=l.NonTerminal,E.Terminal=l.Terminal,E.Rule=l.Rule,E.GAstVisitor=p.GAstVisitor,E.serializeGrammar=l.serializeGrammar,E.serializeProduction=l.serializeProduction,E.resolveGrammar=h.resolveGrammar,E.defaultGrammarResolverErrorProvider=u.defaultGrammarResolverErrorProvider,E.validateGrammar=h.validateGrammar,E.defaultGrammarValidatorErrorProvider=u.defaultGrammarValidatorErrorProvider,E.assignOccurrenceIndices=h.assignOccurrenceIndices,E.clearCache=function(){console.warn("The clearCache function was 'soft' removed from the Chevrotain API.\n\t It performs no action other than printing this message.\n\t Please avoid using it as it will be completely removed in the future")},E.createSyntaxDiagramsCode=c.createSyntaxDiagramsCode,E.generateParserFactory=f.generateParserFactory,E.generateParserModule=f.generateParserModule,t.exports=E},function(t,e,n){var r,i,o;"undefined"!=typeof self&&self,i=[],void 0===(o="function"==typeof(r=function(){function t(){}t.prototype.saveState=function(){return{idx:this.idx,input:this.input,groupIdx:this.groupIdx}},t.prototype.restoreState=function(t){this.idx=t.idx,this.input=t.input,this.groupIdx=t.groupIdx},t.prototype.pattern=function(t){this.idx=0,this.input=t,this.groupIdx=0,this.consumeChar("/");var e=this.disjunction();this.consumeChar("/");for(var n={type:"Flags",global:!1,ignoreCase:!1,multiLine:!1,unicode:!1,sticky:!1};this.isRegExpFlag();)switch(this.popChar()){case"g":s(n,"global");break;case"i":s(n,"ignoreCase");break;case"m":s(n,"multiLine");break;case"u":s(n,"unicode");break;case"y":s(n,"sticky")}if(this.idx!==this.input.length)throw Error("Redundant input: "+this.input.substring(this.idx));return{type:"Pattern",flags:n,value:e}},t.prototype.disjunction=function(){var t=[];for(t.push(this.alternative());"|"===this.peekChar();)this.consumeChar("|"),t.push(this.alternative());return{type:"Disjunction",value:t}},t.prototype.alternative=function(){for(var t=[];this.isTerm();)t.push(this.term());return{type:"Alternative",value:t}},t.prototype.term=function(){return this.isAssertion()?this.assertion():this.atom()},t.prototype.assertion=function(){switch(this.popChar()){case"^":return{type:"StartAnchor"};case"$":return{type:"EndAnchor"};case"\\":switch(this.popChar()){case"b":return{type:"WordBoundary"};case"B":return{type:"NonWordBoundary"}}throw Error("Invalid Assertion Escape");case"(":var t;switch(this.consumeChar("?"),this.popChar()){case"=":t="Lookahead";break;case"!":t="NegativeLookahead"}u(t);var e=this.disjunction();return this.consumeChar(")"),{type:t,value:e}}!function(){throw Error("Internal Error - Should never get here!")}()},t.prototype.quantifier=function(t){var e;switch(this.popChar()){case"*":e={atLeast:0,atMost:1/0};break;case"+":e={atLeast:1,atMost:1/0};break;case"?":e={atLeast:0,atMost:1};break;case"{":var n=this.integerIncludingZero();switch(this.popChar()){case"}":e={atLeast:n,atMost:n};break;case",":var r;this.isDigit()?(r=this.integerIncludingZero(),e={atLeast:n,atMost:r}):e={atLeast:n,atMost:1/0},this.consumeChar("}")}if(!0===t&&void 0===e)return;u(e)}if(!0!==t||void 0!==e)return u(e),"?"===this.peekChar(0)?(this.consumeChar("?"),e.greedy=!1):e.greedy=!0,e.type="Quantifier",e},t.prototype.atom=function(){var t;switch(this.peekChar()){case".":t=this.dotAll();break;case"\\":t=this.atomEscape();break;case"[":t=this.characterClass();break;case"(":t=this.group()}return void 0===t&&this.isPatternCharacter()&&(t=this.patternCharacter()),u(t),this.isQuantifier()&&(t.quantifier=this.quantifier()),t},t.prototype.dotAll=function(){return this.consumeChar("."),{type:"Set",complement:!0,value:[o("\n"),o("\r"),o("\u2028"),o("\u2029")]}},t.prototype.atomEscape=function(){switch(this.consumeChar("\\"),this.peekChar()){case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":return this.decimalEscapeAtom();case"d":case"D":case"s":case"S":case"w":case"W":return this.characterClassEscape();case"f":case"n":case"r":case"t":case"v":return this.controlEscapeAtom();case"c":return this.controlLetterEscapeAtom();case"0":return this.nulCharacterAtom();case"x":return this.hexEscapeSequenceAtom();case"u":return this.regExpUnicodeEscapeSequenceAtom();default:return this.identityEscapeAtom()}},t.prototype.decimalEscapeAtom=function(){var t=this.positiveInteger();return{type:"GroupBackReference",value:t}},t.prototype.characterClassEscape=function(){var t,e=!1;switch(this.popChar()){case"d":t=c;break;case"D":t=c,e=!0;break;case"s":t=l;break;case"S":t=l,e=!0;break;case"w":t=p;break;case"W":t=p,e=!0}return u(t),{type:"Set",value:t,complement:e}},t.prototype.controlEscapeAtom=function(){var t;switch(this.popChar()){case"f":t=o("\f");break;case"n":t=o("\n");break;case"r":t=o("\r");break;case"t":t=o("\t");break;case"v":t=o("\v")}return u(t),{type:"Character",value:t}},t.prototype.controlLetterEscapeAtom=function(){this.consumeChar("c");var t=this.popChar();if(!1===/[a-zA-Z]/.test(t))throw Error("Invalid ");var e=t.toUpperCase().charCodeAt(0)-64;return{type:"Character",value:e}},t.prototype.nulCharacterAtom=function(){return this.consumeChar("0"),{type:"Character",value:o("\0")}},t.prototype.hexEscapeSequenceAtom=function(){return this.consumeChar("x"),this.parseHexDigits(2)},t.prototype.regExpUnicodeEscapeSequenceAtom=function(){return this.consumeChar("u"),this.parseHexDigits(4)},t.prototype.identityEscapeAtom=function(){var t=this.popChar();return{type:"Character",value:o(t)}},t.prototype.classPatternCharacterAtom=function(){switch(this.peekChar()){case"\n":case"\r":case"\u2028":case"\u2029":case"\\":case"]":throw Error("TBD");default:var t=this.popChar();return{type:"Character",value:o(t)}}},t.prototype.characterClass=function(){var t=[],e=!1;for(this.consumeChar("["),"^"===this.peekChar(0)&&(this.consumeChar("^"),e=!0);this.isClassAtom();){var n=this.classAtom(),r="Character"===n.type;if(r&&this.isRangeDash()){this.consumeChar("-");var i=this.classAtom(),s="Character"===i.type;if(s){if(i.value=this.input.length)throw Error("Unexpected end of input");this.idx++};var e,n=/[0-9a-fA-F]/,r=/[0-9]/,i=/[1-9]/;function o(t){return t.charCodeAt(0)}function a(t,e){void 0!==t.length?t.forEach(function(t){e.push(t)}):e.push(t)}function s(t,e){if(!0===t[e])throw"duplicate flag "+e;t[e]=!0}function u(t){if(void 0===t)throw Error("Internal Error - Should never get here!")}var c=[];for(e=o("0");e<=o("9");e++)c.push(e);var p=[o("_")].concat(c);for(e=o("a");e<=o("z");e++)p.push(e);for(e=o("A");e<=o("Z");e++)p.push(e);var l=[o(" "),o("\f"),o("\n"),o("\r"),o("\t"),o("\v"),o("\t"),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o(" "),o("\u2028"),o("\u2029"),o(" "),o(" "),o(" "),o("\ufeff")];function h(){}return h.prototype.visitChildren=function(t){for(var e in t){var n=t[e];t.hasOwnProperty(e)&&(void 0!==n.type?this.visit(n):Array.isArray(n)&&n.forEach(function(t){this.visit(t)},this))}},h.prototype.visit=function(t){switch(t.type){case"Pattern":this.visitPattern(t);break;case"Flags":this.visitFlags(t);break;case"Disjunction":this.visitDisjunction(t);break;case"Alternative":this.visitAlternative(t);break;case"StartAnchor":this.visitStartAnchor(t);break;case"EndAnchor":this.visitEndAnchor(t);break;case"WordBoundary":this.visitWordBoundary(t);break;case"NonWordBoundary":this.visitNonWordBoundary(t);break;case"Lookahead":this.visitLookahead(t);break;case"NegativeLookahead":this.visitNegativeLookahead(t);break;case"Character":this.visitCharacter(t);break;case"Set":this.visitSet(t);break;case"Group":this.visitGroup(t);break;case"GroupBackReference":this.visitGroupBackReference(t);break;case"Quantifier":this.visitQuantifier(t)}this.visitChildren(t)},h.prototype.visitPattern=function(t){},h.prototype.visitFlags=function(t){},h.prototype.visitDisjunction=function(t){},h.prototype.visitAlternative=function(t){},h.prototype.visitStartAnchor=function(t){},h.prototype.visitEndAnchor=function(t){},h.prototype.visitWordBoundary=function(t){},h.prototype.visitNonWordBoundary=function(t){},h.prototype.visitLookahead=function(t){},h.prototype.visitNegativeLookahead=function(t){},h.prototype.visitCharacter=function(t){},h.prototype.visitSet=function(t){},h.prototype.visitGroup=function(t){},h.prototype.visitGroupBackReference=function(t){},h.prototype.visitQuantifier=function(t){},{RegExpParser:t,BaseRegExpVisitor:h,VERSION:"0.4.0"}})?r.apply(e,i):r)||(t.exports=o)},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.defaultLexerErrorProvider={buildUnableToPopLexerModeMessage:function(t){return"Unable to pop Lexer Mode after encountering Token ->"+t.image+"<- The Mode Stack is empty"},buildUnexpectedCharactersMessage:function(t,e,n,r,i){return"unexpected character: ->"+t.charAt(e)+"<- at offset: "+e+", skipped "+n+" characters."}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),i=n(1),o=n(8);function a(t){if(t instanceof i.NonTerminal)return a(t.referencedRule);if(t instanceof i.Terminal)return c(t);if(o.isSequenceProd(t))return s(t);if(o.isBranchingProd(t))return u(t);throw Error("non exhaustive match")}function s(t){for(var e,n=[],i=t.definition,s=0,u=i.length>s,c=!0;u&&c;)e=i[s],c=o.isOptionalProd(e),n=n.concat(a(e)),s+=1,u=i.length>s;return r.uniq(n)}function u(t){var e=r.map(t.definition,function(t){return a(t)});return r.uniq(r.flatten(e))}function c(t){return[t.terminalType]}e.first=a,e.firstForSequence=s,e.firstForBranching=u,e.firstForTerminal=c},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.IN="_~IN~_"},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r,i=n(29),o=n(0),a=n(1);!function(t){t[t.OPTION=0]="OPTION",t[t.OR=1]="OR",t[t.MANY=2]="MANY",t[t.MANY_SEP=3]="MANY_SEP",t[t.AT_LEAST_ONE=4]="AT_LEAST_ONE",t[t.AT_LEAST_ONE_SEP=5]="AT_LEAST_ONE_SEP",t[t.REF=6]="REF",t[t.TERMINAL=7]="TERMINAL",t[t.FLAT=8]="FLAT"}(r=e.ProdType||(e.ProdType={}));var s=/(?:\s*{\s*NAME\s*:\s*["'`]([\w$]*)["'`])?/,u=new RegExp(s.source.replace("{","").replace(")?","\\s*,)?")),c=/\.\s*CONSUME(\d+)?\s*\(\s*(?:[a-zA-Z_$]\w*\s*\.\s*)*([a-zA-Z_$]\w*)/,p=new RegExp(c.source,"g"),l=/\.\s*SUBRULE(\d+)?\s*\(\s*(?:[a-zA-Z_$]\w*\s*\.\s*)*([a-zA-Z_$]\w*)/,h=new RegExp(l.source,"g"),f=/\.\s*OPTION(\d+)?\s*\(/,d=new RegExp(f.source+s.source),E=new RegExp(f.source,"g"),m=/\.\s*MANY(\d+)?\s*\(/,y=new RegExp(m.source+s.source),T=new RegExp(m.source,"g"),v=/\s*SEP\s*:\s*(?:[a-zA-Z_$]\w*\s*\.\s*)*([a-zA-Z_$]\w*)/,g=new RegExp(/\.\s*MANY_SEP(\d+)?\s*\(\s*{/.source+u.source+v.source),_=new RegExp(g.source,"g"),R=new RegExp(/\.\s*AT_LEAST_ONE_SEP(\d+)?\s*\(\s*{/.source+u.source+v.source),A=new RegExp(R.source,"g"),N=/\.\s*AT_LEAST_ONE(\d+)?\s*\(/,O=new RegExp(N.source+s.source),S=new RegExp(N.source,"g"),I=/\.\s*OR(\d+)?\s*\(/,L=new RegExp(I.source+s.source),k=new RegExp(I.source,"g"),P=new RegExp(u.source+/\s*(ALT)\s*:/.source),x=new RegExp(P.source,"g");function C(t,n,i){switch(t.type){case r.AT_LEAST_ONE:return function(t,e,n){return M(O,new a.RepetitionMandatory({definition:[]}),t,e,n)}(t,n,i);case r.AT_LEAST_ONE_SEP:return function(t,e,n){return F(t,e,a.RepetitionMandatoryWithSeparator,R,n)}(t,n,i);case r.MANY_SEP:return function(t,e,n){return F(t,e,a.RepetitionWithSeparator,g,n)}(t,n,i);case r.MANY:return function(t,e,n){return M(y,new a.Repetition({definition:[]}),t,e,n)}(t,n,i);case r.OPTION:return function(t,e,n){return M(d,new a.Option({definition:[]}),t,e,n)}(t,n,i);case r.OR:return function(t,e,n){return M(L,new a.Alternation({definition:[]}),t,e,n)}(t,n,i);case r.FLAT:return function(t,e,n){var r=new a.Flat({definition:[]}),i=P.exec(t.text)[1];o.isUndefined(i)||(r.name=i);return b(r,t.range,e,n)}(t,n,i);case r.REF:return function(t){var e=l.exec(t.text),n=void 0===e[1]?0:parseInt(e[1],10),r=e[2];return new a.NonTerminal({nonTerminalName:r,idx:n})}(t);case r.TERMINAL:return function(t,n){var r=c.exec(t.text),i=void 0===r[1]?0:parseInt(r[1],10),o=r[2],s=e.terminalNameToConstructor[o];if(!s)throw Error("Terminal Token name: <"+o+"> not found in rule: <"+n+"> \n\tSee: https://sap.github.io/chevrotain/docs/guide/resolving_grammar_errors.html#TERMINAL_NAME_NOT_FOUND\n\tFor Further details.");return new a.Terminal({terminalType:s,idx:i})}(t,i);default:throw Error("non exhaustive match")}}function M(t,e,n,r,i){var a=t.exec(n.text),s=void 0===a[1];e.idx=s?0:parseInt(a[1],10);var u=a[2];return o.isUndefined(u)||(e.name=u),b(e,n.range,r,i)}function F(t,n,r,i,a){var s=i.exec(t.text),u=void 0===s[1]?0:parseInt(s[1],10),c=s[3],p=e.terminalNameToConstructor[c];if(!p)throw Error("Separator Terminal Token name: "+c+" not found");var l=new r({definition:[],separator:p,idx:u}),h=s[2];return o.isUndefined(h)||(l.name=h),b(l,t.range,n,a)}function b(t,e,n,r){var i=D(e,n),a=o.sortBy(i,function(t){return t.range.start}),s=[];return o.forEach(a,function(t){s.push(C(t,n,r))}),t.definition=s,t}function D(t,e){return o.filter(e,function(n){var r=t.strictlyContainsRange(n.range),i=o.every(e,function(e){var r=e.range.strictlyContainsRange(n.range),i=e.range.isStrictlyContainedInRange(t);return!(r&&i)});return r&&i})}e.terminalNameToConstructor={},e.buildTopProduction=function(t,n,r){e.terminalNameToConstructor=r;var o=V(j(K(" "+t)));return function(t,e,n,r){return b(new a.Rule({name:t,definition:[],orgText:r}),e,n,t)}(n,new i.Range(0,t.length+2),o,t)},e.buildProdGast=C,e.getDirectlyContainedRanges=D;var w=/\/\/.*/g,U=/\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\//g,G=/(NAME\s*:\s*)?"([^\\"]|\\([bfnrtv"\\\/]|u[0-9a-fA-F]{4}))*"/g,B=/(NAME\s*:\s*)?'([^\\']|\\([bfnrtv'\\\/]|u[0-9a-fA-F]{4}))*'/g;function K(t){return t.replace(w,"").replace(U,"")}function W(t,e){return void 0!==e?t:""}function j(t){return t.replace(G,W).replace(B,W)}function V(t){var e=Y(t),n=H(t),r=X(t),i=z(t),o=q(t),a=$(t),s=Z(t),u=Q(t);return[].concat(e,n,r,i,o,a,s,u)}function Y(t){return nt(t,r.TERMINAL,p)}function H(t){return nt(t,r.REF,h)}function X(t){return rt(t,r.AT_LEAST_ONE,S)}function z(t){return rt(t,r.AT_LEAST_ONE_SEP,A)}function q(t){return rt(t,r.MANY,T)}function $(t){return rt(t,r.MANY_SEP,_)}function Z(t){return rt(t,r.OPTION,E)}function Q(t){var e=rt(t,r.OR,k),n=et(e);return e.concat(n)}e.removeComments=K,e.removeStringLiterals=j,e.createRanges=V,e.createTerminalRanges=Y,e.createRefsRanges=H,e.createAtLeastOneRanges=X,e.createAtLeastOneSepRanges=z,e.createManyRanges=q,e.createManySepRanges=$,e.createOptionRanges=Z,e.createOrRanges=Q;var J=o.partial(ot,"{","}"),tt=o.partial(ot,"(",")");function et(t){var e=[];return o.forEach(t,function(t){var n=it(t.text,r.FLAT,x,J),i=t.range.start;o.forEach(n,function(t){t.range.start+=i,t.range.end+=i}),e=e.concat(n)}),o.uniq(e,function(t){return t.type+"~"+t.range.start+"~"+t.range.end+"~"+t.text})}function nt(t,e,n){for(var r,o=[];r=n.exec(t);){var a=r.index,s=n.lastIndex,u=new i.Range(a,s),c=r[0];o.push({range:u,text:c,type:e})}return o}function rt(t,e,n){return it(t,e,n,tt)}function it(t,e,n,r){for(var o,a=[];o=n.exec(t);){var s=o.index,u=r(s+o[0].length,t),c=new i.Range(s,u),p=t.substr(s,u-s+1);a.push({range:c,text:p,type:e})}return a}function ot(t,e,n,r){for(var i=[1],a=-1;!o.isEmpty(i)&&a+n"+a.tokenName(t)+"<- missing static 'PATTERN' property",type:s.LexerDefinitionErrorType.MISSING_PATTERN,tokenTypes:[t]}}),valid:u.difference(t,e)}}function f(t){var e=u.filter(t,function(t){var e=t[l];return!(u.isRegExp(e)||u.isFunction(e)||u.has(e,"exec")||u.isString(e))});return{errors:u.map(e,function(t){return{message:"Token Type: ->"+a.tokenName(t)+"<- static 'PATTERN' can only be a RegExp, a Function matching the {CustomPatternMatcherFunc} type or an Object matching the {ICustomPattern} interface.",type:s.LexerDefinitionErrorType.INVALID_PATTERN,tokenTypes:[t]}}),valid:u.difference(t,e)}}e.DEFAULT_MODE="defaultMode",e.MODES="modes",e.SUPPORT_STICKY="boolean"==typeof new RegExp("(?:)").sticky,e.disableSticky=function(){e.SUPPORT_STICKY=!1},e.enableSticky=function(){e.SUPPORT_STICKY=!0},e.analyzeTokenTypes=function(t,n){n=u.defaults(n,{useSticky:e.SUPPORT_STICKY,debug:!1,safeMode:!1,positionTracking:"full",lineTerminatorCharacters:["\r","\n"]});var r=u.reject(t,function(t){return t[l]===s.Lexer.NA}),i=!1,o=u.map(r,function(t){var e=t[l];if(u.isRegExp(e)){var r=e.source;return 1===r.length&&"^"!==r&&"$"!==r&&"."!==r?r:2!==r.length||"\\"!==r[0]||u.contains(["d","D","s","S","t","r","n","t","0","c","b","B","f","v","w","W"],r[1])?n.useSticky?O(e):N(e):r[1]}if(u.isFunction(e))return i=!0,{exec:e};if(u.has(e,"exec"))return i=!0,e;if("string"==typeof e){if(1===e.length)return e;var o=e.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&"),a=new RegExp(o);return n.useSticky?O(a):N(a)}throw Error("non exhaustive match")}),p=u.map(r,function(t){return t.tokenTypeIdx}),h=u.map(r,function(t){var e=t.GROUP;if(e!==s.Lexer.SKIPPED){if(u.isString(e))return e;if(u.isUndefined(e))return!1;throw Error("non exhaustive match")}}),f=u.map(r,function(t){var e=t.LONGER_ALT;if(e)return u.indexOf(r,e)}),d=u.map(r,function(t){return t.PUSH_MODE}),E=u.map(r,function(t){return u.has(t,"POP_MODE")}),m=P(n.lineTerminatorCharacters),y=u.map(r,function(t){return!1});"onlyOffset"!==n.positionTracking&&(y=u.map(r,function(t){return u.has(t,"LINE_BREAKS")?t.LINE_BREAKS:!1===L(t,m)?c.canMatchCharCode(m,t.PATTERN):void 0}));var T=u.map(r,S),v=u.map(o,I),g=u.reduce(r,function(t,e){var n=e.GROUP;return u.isString(n)&&n!==s.Lexer.SKIPPED&&(t[n]=[]),t},{}),_=u.map(o,function(t,e){return{pattern:o[e],longerAlt:f[e],canLineTerminator:y[e],isCustom:T[e],short:v[e],group:h[e],push:d[e],pop:E[e],tokenTypeIdx:p[e],tokenType:r[e]}});function R(t,e,n){void 0===t[e]&&(t[e]=[]),t[e].push(n)}var A=!0,k=[];return n.safeMode||(k=u.reduce(r,function(t,e,r){if("string"==typeof e.PATTERN){var i=e.PATTERN.charCodeAt(0);R(t,i,_[r])}else if(u.isArray(e.START_CHARS_HINT))u.forEach(e.START_CHARS_HINT,function(e){var n="string"==typeof e?e.charCodeAt(0):e;R(t,n,_[r])});else if(u.isRegExp(e.PATTERN))if(e.PATTERN.unicode)A=!1,n.ensureOptimizations&&u.PRINT_ERROR(c.failedOptimizationPrefixMsg+"\tUnable to analyze < "+e.PATTERN.toString()+" > pattern.\n\tThe regexp unicode flag is not currently supported by the regexp-to-ast library.\n\tThis will disable the lexer's first char optimizations.\n\tFor details See: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#UNICODE_OPTIMIZE");else{var o=c.getStartCodes(e.PATTERN,n.ensureOptimizations);u.isEmpty(o)&&(A=!1),u.forEach(o,function(e){R(t,e,_[r])})}else n.ensureOptimizations&&u.PRINT_ERROR(c.failedOptimizationPrefixMsg+"\tTokenType: <"+a.tokenName(e)+"> is using a custom token pattern without providing parameter.\n\tThis will disable the lexer's first char optimizations.\n\tFor details See: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#CUSTOM_OPTIMIZE"),A=!1;return t},[])),A&&k.length<65536&&(k=u.packArray(k)),{emptyGroups:g,patternIdxToConfig:_,charCodeToPatternIdxToConfig:k,hasCustom:i,canBeOptimized:A}},e.validatePatterns=function(t,e){var n=[],r=h(t);n=n.concat(r.errors);var i=f(r.valid),o=i.valid;return n=(n=(n=(n=(n=n.concat(i.errors)).concat(function(t){var e=[],n=u.filter(t,function(t){return u.isRegExp(t[l])});return e=(e=(e=(e=(e=e.concat(E(n))).concat(T(n))).concat(v(n))).concat(g(n))).concat(m(n))}(o))).concat(_(o))).concat(R(o,e))).concat(A(o))},e.findMissingPatterns=h,e.findInvalidPatterns=f;var d=/[^\\][\$]/;function E(t){var e=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.found=!1,e}return i(e,t),e.prototype.visitEndAnchor=function(t){this.found=!0},e}(o.BaseRegExpVisitor),n=u.filter(t,function(t){var n=t[l];try{var r=p.pattern(n.toString()),i=new e;return i.visit(r),i.found}catch(t){return d.test(n.source)}});return u.map(n,function(t){return{message:"Unexpected RegExp Anchor Error:\n\tToken Type: ->"+a.tokenName(t)+"<- static 'PATTERN' cannot contain end of input anchor '$'\n\tSee sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#ANCHORS\tfor details.",type:s.LexerDefinitionErrorType.EOI_ANCHOR_FOUND,tokenTypes:[t]}})}function m(t){var e=u.filter(t,function(t){return t[l].test("")});return u.map(e,function(t){return{message:"Token Type: ->"+a.tokenName(t)+"<- static 'PATTERN' must not match an empty string",type:s.LexerDefinitionErrorType.EMPTY_MATCH_PATTERN,tokenTypes:[t]}})}e.findEndOfInputAnchor=E,e.findEmptyMatchRegExps=m;var y=/[^\\[][\^]|^\^/;function T(t){var e=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.found=!1,e}return i(e,t),e.prototype.visitStartAnchor=function(t){this.found=!0},e}(o.BaseRegExpVisitor),n=u.filter(t,function(t){var n=t[l];try{var r=p.pattern(n.toString()),i=new e;return i.visit(r),i.found}catch(t){return y.test(n.source)}});return u.map(n,function(t){return{message:"Unexpected RegExp Anchor Error:\n\tToken Type: ->"+a.tokenName(t)+"<- static 'PATTERN' cannot contain start of input anchor '^'\n\tSee https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#ANCHORS\tfor details.",type:s.LexerDefinitionErrorType.SOI_ANCHOR_FOUND,tokenTypes:[t]}})}function v(t){var e=u.filter(t,function(t){var e=t[l];return e instanceof RegExp&&(e.multiline||e.global)});return u.map(e,function(t){return{message:"Token Type: ->"+a.tokenName(t)+"<- static 'PATTERN' may NOT contain global('g') or multiline('m')",type:s.LexerDefinitionErrorType.UNSUPPORTED_FLAGS_FOUND,tokenTypes:[t]}})}function g(t){var e=[],n=u.map(t,function(n){return u.reduce(t,function(t,r){return n.PATTERN.source!==r.PATTERN.source||u.contains(e,r)||r.PATTERN===s.Lexer.NA?t:(e.push(r),t.push(r),t)},[])});n=u.compact(n);var r=u.filter(n,function(t){return t.length>1});return u.map(r,function(t){var e=u.map(t,function(t){return a.tokenName(t)});return{message:"The same RegExp pattern ->"+u.first(t).PATTERN+"<-has been used in all of the following Token Types: "+e.join(", ")+" <-",type:s.LexerDefinitionErrorType.DUPLICATE_PATTERNS_FOUND,tokenTypes:t}})}function _(t){var e=u.filter(t,function(t){if(!u.has(t,"GROUP"))return!1;var e=t.GROUP;return e!==s.Lexer.SKIPPED&&e!==s.Lexer.NA&&!u.isString(e)});return u.map(e,function(t){return{message:"Token Type: ->"+a.tokenName(t)+"<- static 'GROUP' can only be Lexer.SKIPPED/Lexer.NA/A String",type:s.LexerDefinitionErrorType.INVALID_GROUP_TYPE_FOUND,tokenTypes:[t]}})}function R(t,e){var n=u.filter(t,function(t){return void 0!==t.PUSH_MODE&&!u.contains(e,t.PUSH_MODE)});return u.map(n,function(t){return{message:"Token Type: ->"+a.tokenName(t)+"<- static 'PUSH_MODE' value cannot refer to a Lexer Mode ->"+t.PUSH_MODE+"<-which does not exist",type:s.LexerDefinitionErrorType.PUSH_MODE_DOES_NOT_EXIST,tokenTypes:[t]}})}function A(t){var e=[],n=u.reduce(t,function(t,e,n){var r,i=e.PATTERN;return i===s.Lexer.NA?t:(u.isString(i)?t.push({str:i,idx:n,tokenType:e}):u.isRegExp(i)&&(r=i,void 0===u.find([".","\\","[","]","|","^","$","(",")","?","*","+","{"],function(t){return-1!==r.source.indexOf(t)}))&&t.push({str:i.source,idx:n,tokenType:e}),t)},[]);return u.forEach(t,function(t,r){u.forEach(n,function(n){var i=n.str,o=n.idx,c=n.tokenType;if(r"+a.tokenName(t)+"<-in the lexer's definition.\nSee https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#UNREACHABLE";e.push({message:p,type:s.LexerDefinitionErrorType.UNREACHABLE_PATTERN,tokenTypes:[t,c]})}})}),e}function N(t){var e=t.ignoreCase?"i":"";return new RegExp("^(?:"+t.source+")",e)}function O(t){var e=t.ignoreCase?"iy":"y";return new RegExp(""+t.source,e)}function S(t){var e=t.PATTERN;if(u.isRegExp(e))return!1;if(u.isFunction(e))return!0;if(u.has(e,"exec"))return!0;if(u.isString(e))return!1;throw Error("non exhaustive match")}function I(t){return!(!u.isString(t)||1!==t.length)&&t.charCodeAt(0)}function L(t,e){if(u.has(t,"LINE_BREAKS"))return!1;if(u.isRegExp(t.PATTERN)){try{c.canMatchCharCode(e,t.PATTERN)}catch(t){return{issue:s.LexerDefinitionErrorType.IDENTIFY_TERMINATOR,errMsg:t.message}}return!1}if(u.isString(t.PATTERN))return!1;if(S(t))return{issue:s.LexerDefinitionErrorType.CUSTOM_LINE_BREAK};throw Error("non exhaustive match")}function k(t,e){if(e.issue===s.LexerDefinitionErrorType.IDENTIFY_TERMINATOR)return"Warning: unable to identify line terminator usage in pattern.\n\tThe problem is in the <"+t.name+"> Token Type\n\t Root cause: "+e.errMsg+".\n\tFor details See: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#IDENTIFY_TERMINATOR";if(e.issue===s.LexerDefinitionErrorType.CUSTOM_LINE_BREAK)return"Warning: A Custom Token Pattern should specify the option.\n\tThe problem is in the <"+t.name+"> Token Type\n\tFor details See: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#CUSTOM_LINE_BREAK";throw Error("non exhaustive match")}function P(t){return u.map(t,function(t){return u.isString(t)&&t.length>0?t.charCodeAt(0):t})}e.findStartOfInputAnchor=T,e.findUnsupportedFlags=v,e.findDuplicatePatterns=g,e.findInvalidGroupType=_,e.findModesThatDoNotExist=R,e.findUnreachablePatterns=A,e.addStartOfInput=N,e.addStickyFlag=O,e.performRuntimeChecks=function(t,n,r){var i=[];return u.has(t,e.DEFAULT_MODE)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+e.DEFAULT_MODE+"> property in its definition\n",type:s.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE}),u.has(t,e.MODES)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+e.MODES+"> property in its definition\n",type:s.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY}),u.has(t,e.MODES)&&u.has(t,e.DEFAULT_MODE)&&!u.has(t.modes,t.defaultMode)&&i.push({message:"A MultiMode Lexer cannot be initialized with a "+e.DEFAULT_MODE+": <"+t.defaultMode+">which does not exist\n",type:s.LexerDefinitionErrorType.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST}),u.has(t,e.MODES)&&u.forEach(t.modes,function(t,e){u.forEach(t,function(t,n){u.isUndefined(t)&&i.push({message:"A Lexer cannot be initialized using an undefined Token Type. Mode:<"+e+"> at index: <"+n+">\n",type:s.LexerDefinitionErrorType.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED})})}),i},e.performWarningRuntimeChecks=function(t,e,n){var r=[],i=!1,o=u.compact(u.flatten(u.mapValues(t.modes,function(t){return t}))),a=u.reject(o,function(t){return t[l]===s.Lexer.NA}),p=P(n);return e&&u.forEach(a,function(t){var e=L(t,p);if(!1!==e){var n={message:k(t,e),type:e.issue,tokenType:t};r.push(n)}else u.has(t,"LINE_BREAKS")?!0===t.LINE_BREAKS&&(i=!0):c.canMatchCharCode(p,t.PATTERN)&&(i=!0)}),e&&!i&&r.push({message:"Warning: No LINE_BREAKS Found.\n\tThis Lexer has been defined to track line and column information,\n\tBut none of the Token Types can be identified as matching a line terminator.\n\tSee https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#LINE_BREAKS \n\tfor details.",type:s.LexerDefinitionErrorType.NO_LINE_BREAKS_FLAGS}),r},e.cloneEmptyGroups=function(t){var e={},n=u.keys(t);return u.forEach(n,function(n){var r=t[n];if(!u.isArray(r))throw Error("non exhaustive match");e[n]=[]}),e},e.isCustomPattern=S,e.isShortPattern=I,e.LineTerminatorOptimizedTester={test:function(t){for(var e=t.length,n=this.lastIndex;n\n\tComplement Sets cannot be automatically optimized.\n\tThis will disable the lexer's first char optimizations.\n\tSee: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#COMPLEMENT for details.");else{var l="";n&&(l="\n\tThis will disable the lexer's first char optimizations.\n\tSee: https://sap.github.io/chevrotain/docs/guide/resolving_lexer_errors.html#REGEXP_PARSING for details."),a.PRINT_ERROR(e.failedOptimizationPrefixMsg+"\n\tFailed parsing: < "+t.toString()+" >\n\tUsing the regexp-to-ast library version: "+o.VERSION+"\n\tPlease open an issue at: https://github.com/bd82/regexp-to-ast/issues"+l)}}return[]},e.firstChar=c,e.applyIgnoreCase=p;var f=function(t){function e(e){var n=t.call(this)||this;return n.targetCharCodes=e,n.found=!1,n}return i(e,t),e.prototype.visitChildren=function(e){switch(e.type){case"Lookahead":return void this.visitLookahead(e);case"NegativeLookahead":return void this.visitNegativeLookahead(e)}t.prototype.visitChildren.call(this,e)},e.prototype.visitCharacter=function(t){a.contains(this.targetCharCodes,t.value)&&(this.found=!0)},e.prototype.visitSet=function(t){t.complement?void 0===l(t,this.targetCharCodes)&&(this.found=!0):void 0!==l(t,this.targetCharCodes)&&(this.found=!0)},e}(o.BaseRegExpVisitor);e.canMatchCharCode=function(t,e){if(e instanceof RegExp){var n=s.pattern(e.toString()),r=new f(t);return r.visit(n),r.found}return void 0!==a.find(e,function(e){return a.contains(t,e.charCodeAt(0))})}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=function(){function t(t,e){if(this.start=t,this.end=e,!i(t,e))throw new Error("INVALID RANGE")}return t.prototype.contains=function(t){return this.start<=t&&this.end>=t},t.prototype.containsRange=function(t){return this.start<=t.start&&this.end>=t.end},t.prototype.isContainedInRange=function(t){return t.containsRange(this)},t.prototype.strictlyContainsRange=function(t){return this.startt.end},t.prototype.isStrictlyContainedInRange=function(t){return t.strictlyContainsRange(this)},t}();function i(t,e){return!(t<0||e on "+o.functionName(t.constructor)+" CST Visitor.",type:r.MISSING_METHOD,methodName:e}});return i.compact(n)}e.defaultVisit=s,e.createBaseSemanticVisitorConstructor=function(t,e){var n=function(){};return o.defineNameProp(n,t+"BaseSemantics"),(n.prototype={visit:function(t,e){if(i.isArray(t)&&(t=t[0]),!i.isUndefined(t))return void 0!==t.fullName?this[t.fullName](t.children,e):this[t.name](t.children,e)},validateVisitor:function(){var t=u(this,e);if(!i.isEmpty(t)){var n=i.map(t,function(t){return t.msg});throw Error("Errors Detected in CST Visitor <"+o.functionName(this.constructor)+">:\n\t"+n.join("\n\n").replace(/\n/g,"\n\t"))}}}).constructor=n,n._RULE_NAMES=e,n},e.createBaseVisitorConstructorWithDefaults=function(t,e,n){var r=function(){};o.defineNameProp(r,t+"BaseSemanticsWithDefaults");var a=Object.create(n.prototype);return i.forEach(e,function(t){a[t]=s}),(r.prototype=a).constructor=r,r},function(t){t[t.REDUNDANT_METHOD=0]="REDUNDANT_METHOD",t[t.MISSING_METHOD=1]="MISSING_METHOD"}(r=e.CstVisitorDefinitionError||(e.CstVisitorDefinitionError={})),e.validateVisitor=u,e.validateMissingCstMethods=c;var p=["constructor","visit","validateVisitor"];function l(t,e){var n=[];for(var s in t)a.validTermsPattern.test(s)&&i.isFunction(t[s])&&!i.contains(p,s)&&!i.contains(e,s)&&n.push({msg:"Redundant visitor method: <"+s+"> on "+o.functionName(t.constructor)+" CST Visitor\nThere is no Grammar Rule corresponding to this method's name.\nFor utility methods on visitor classes use methods names that do not match /"+a.validTermsPattern.source+"/.",type:r.REDUNDANT_METHOD,methodName:s});return n}e.validateRedundantMethods=l},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=function(){function t(){}return t.prototype.initLexerAdapter=function(){this.tokVector=[],this.tokVectorLength=0,this.currIdx=-1},Object.defineProperty(t.prototype,"input",{get:function(){return this.tokVector},set:function(t){this.reset(),this.tokVector=t,this.tokVectorLength=t.length},enumerable:!0,configurable:!0}),t.prototype.SKIP_TOKEN=function(){return this.currIdx<=this.tokVector.length-2?(this.consumeToken(),this.LA(1)):r.END_OF_FILE},t.prototype.LA=function(t){return this.currIdx+t<0||this.tokVectorLength<=this.currIdx+t?r.END_OF_FILE:this.tokVector[this.currIdx+t]},t.prototype.consumeToken=function(){this.currIdx++},t.prototype.exportLexerState=function(){return this.currIdx},t.prototype.importLexerState=function(t){this.currIdx=t},t.prototype.resetLexerState=function(){this.currIdx=-1},t.prototype.moveToTerminatedState=function(){this.currIdx=this.tokVector.length-1},t.prototype.getLexerPosition=function(){return this.exportLexerState()},t}();e.LexerAdapter=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),i=n(6),o=n(3),a=n(10),s=n(23),u=n(11),c=n(1),p=function(){function t(){}return t.prototype.CONSUME=function(t,e){return this.consumeInternal(t,0,e)},t.prototype.CONSUME1=function(t,e){return this.consumeInternal(t,1,e)},t.prototype.CONSUME2=function(t,e){return this.consumeInternal(t,2,e)},t.prototype.CONSUME3=function(t,e){return this.consumeInternal(t,3,e)},t.prototype.CONSUME4=function(t,e){return this.consumeInternal(t,4,e)},t.prototype.CONSUME5=function(t,e){return this.consumeInternal(t,5,e)},t.prototype.CONSUME6=function(t,e){return this.consumeInternal(t,6,e)},t.prototype.CONSUME7=function(t,e){return this.consumeInternal(t,7,e)},t.prototype.CONSUME8=function(t,e){return this.consumeInternal(t,8,e)},t.prototype.CONSUME9=function(t,e){return this.consumeInternal(t,9,e)},t.prototype.SUBRULE=function(t,e){return this.subruleInternal(t,0,e)},t.prototype.SUBRULE1=function(t,e){return this.subruleInternal(t,1,e)},t.prototype.SUBRULE2=function(t,e){return this.subruleInternal(t,2,e)},t.prototype.SUBRULE3=function(t,e){return this.subruleInternal(t,3,e)},t.prototype.SUBRULE4=function(t,e){return this.subruleInternal(t,4,e)},t.prototype.SUBRULE5=function(t,e){return this.subruleInternal(t,5,e)},t.prototype.SUBRULE6=function(t,e){return this.subruleInternal(t,6,e)},t.prototype.SUBRULE7=function(t,e){return this.subruleInternal(t,7,e)},t.prototype.SUBRULE8=function(t,e){return this.subruleInternal(t,8,e)},t.prototype.SUBRULE9=function(t,e){return this.subruleInternal(t,9,e)},t.prototype.OPTION=function(t){return this.optionInternal(t,0)},t.prototype.OPTION1=function(t){return this.optionInternal(t,1)},t.prototype.OPTION2=function(t){return this.optionInternal(t,2)},t.prototype.OPTION3=function(t){return this.optionInternal(t,3)},t.prototype.OPTION4=function(t){return this.optionInternal(t,4)},t.prototype.OPTION5=function(t){return this.optionInternal(t,5)},t.prototype.OPTION6=function(t){return this.optionInternal(t,6)},t.prototype.OPTION7=function(t){return this.optionInternal(t,7)},t.prototype.OPTION8=function(t){return this.optionInternal(t,8)},t.prototype.OPTION9=function(t){return this.optionInternal(t,9)},t.prototype.OR=function(t){return this.orInternal(t,0)},t.prototype.OR1=function(t){return this.orInternal(t,1)},t.prototype.OR2=function(t){return this.orInternal(t,2)},t.prototype.OR3=function(t){return this.orInternal(t,3)},t.prototype.OR4=function(t){return this.orInternal(t,4)},t.prototype.OR5=function(t){return this.orInternal(t,5)},t.prototype.OR6=function(t){return this.orInternal(t,6)},t.prototype.OR7=function(t){return this.orInternal(t,7)},t.prototype.OR8=function(t){return this.orInternal(t,8)},t.prototype.OR9=function(t){return this.orInternal(t,9)},t.prototype.MANY=function(t){this.manyInternal(0,t)},t.prototype.MANY1=function(t){this.manyInternal(1,t)},t.prototype.MANY2=function(t){this.manyInternal(2,t)},t.prototype.MANY3=function(t){this.manyInternal(3,t)},t.prototype.MANY4=function(t){this.manyInternal(4,t)},t.prototype.MANY5=function(t){this.manyInternal(5,t)},t.prototype.MANY6=function(t){this.manyInternal(6,t)},t.prototype.MANY7=function(t){this.manyInternal(7,t)},t.prototype.MANY8=function(t){this.manyInternal(8,t)},t.prototype.MANY9=function(t){this.manyInternal(9,t)},t.prototype.MANY_SEP=function(t){this.manySepFirstInternal(0,t)},t.prototype.MANY_SEP1=function(t){this.manySepFirstInternal(1,t)},t.prototype.MANY_SEP2=function(t){this.manySepFirstInternal(2,t)},t.prototype.MANY_SEP3=function(t){this.manySepFirstInternal(3,t)},t.prototype.MANY_SEP4=function(t){this.manySepFirstInternal(4,t)},t.prototype.MANY_SEP5=function(t){this.manySepFirstInternal(5,t)},t.prototype.MANY_SEP6=function(t){this.manySepFirstInternal(6,t)},t.prototype.MANY_SEP7=function(t){this.manySepFirstInternal(7,t)},t.prototype.MANY_SEP8=function(t){this.manySepFirstInternal(8,t)},t.prototype.MANY_SEP9=function(t){this.manySepFirstInternal(9,t)},t.prototype.AT_LEAST_ONE=function(t){this.atLeastOneInternal(0,t)},t.prototype.AT_LEAST_ONE1=function(t){return this.atLeastOneInternal(1,t)},t.prototype.AT_LEAST_ONE2=function(t){this.atLeastOneInternal(2,t)},t.prototype.AT_LEAST_ONE3=function(t){this.atLeastOneInternal(3,t)},t.prototype.AT_LEAST_ONE4=function(t){this.atLeastOneInternal(4,t)},t.prototype.AT_LEAST_ONE5=function(t){this.atLeastOneInternal(5,t)},t.prototype.AT_LEAST_ONE6=function(t){this.atLeastOneInternal(6,t)},t.prototype.AT_LEAST_ONE7=function(t){this.atLeastOneInternal(7,t)},t.prototype.AT_LEAST_ONE8=function(t){this.atLeastOneInternal(8,t)},t.prototype.AT_LEAST_ONE9=function(t){this.atLeastOneInternal(9,t)},t.prototype.AT_LEAST_ONE_SEP=function(t){this.atLeastOneSepFirstInternal(0,t)},t.prototype.AT_LEAST_ONE_SEP1=function(t){this.atLeastOneSepFirstInternal(1,t)},t.prototype.AT_LEAST_ONE_SEP2=function(t){this.atLeastOneSepFirstInternal(2,t)},t.prototype.AT_LEAST_ONE_SEP3=function(t){this.atLeastOneSepFirstInternal(3,t)},t.prototype.AT_LEAST_ONE_SEP4=function(t){this.atLeastOneSepFirstInternal(4,t)},t.prototype.AT_LEAST_ONE_SEP5=function(t){this.atLeastOneSepFirstInternal(5,t)},t.prototype.AT_LEAST_ONE_SEP6=function(t){this.atLeastOneSepFirstInternal(6,t)},t.prototype.AT_LEAST_ONE_SEP7=function(t){this.atLeastOneSepFirstInternal(7,t)},t.prototype.AT_LEAST_ONE_SEP8=function(t){this.atLeastOneSepFirstInternal(8,t)},t.prototype.AT_LEAST_ONE_SEP9=function(t){this.atLeastOneSepFirstInternal(9,t)},t.prototype.RULE=function(t,e,n){if(void 0===n&&(n=o.DEFAULT_RULE_CONFIG),r.contains(this.definedRulesNames,t)){var i={message:a.defaultGrammarValidatorErrorProvider.buildDuplicateRuleNameError({topLevelRule:t,grammarName:this.className}),type:o.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:t};this.definitionErrors.push(i)}if(this.definedRulesNames.push(t),!this.gastProductionsCache.containsKey(t)&&!this.serializedGrammar){var u=s.buildTopProduction(e.toString(),t,this.tokensMap);this.gastProductionsCache.put(t,u)}var c=this.defineRule(t,e,n);return this[t]=c,c},t.prototype.OVERRIDE_RULE=function(t,e,n){void 0===n&&(n=o.DEFAULT_RULE_CONFIG);var r=[];if(r=r.concat(u.validateRuleIsOverridden(t,this.definedRulesNames,this.className)),this.definitionErrors.push.apply(this.definitionErrors,r),!this.serializedGrammar){var i=s.buildTopProduction(e.toString(),t,this.tokensMap);this.gastProductionsCache.put(t,i)}var a=this.defineRule(t,e,n);return this[t]=a,a},t.prototype.BACKTRACK=function(t,e){return function(){this.isBackTrackingStack.push(1);var n=this.saveRecogState();try{return t.apply(this,e),!0}catch(t){if(i.isRecognitionException(t))return!1;throw t}finally{this.reloadRecogState(n),this.isBackTrackingStack.pop()}}},t.prototype.getGAstProductions=function(){return this.gastProductionsCache},t.prototype.getSerializedGastProductions=function(){return c.serializeGrammar(this.gastProductionsCache.values())},t}();e.RecognizerApi=p},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),i=n(9),o=n(6),a=n(12),s=n(13),u=n(3),c=n(25),p=n(2),l=n(7),h=n(4),f=function(){function t(){}return t.prototype.initRecognizerEngine=function(t,e){if(this.className=h.classNameFromInstance(this),this.shortRuleNameToFull=new h.HashTable,this.fullRuleNameToShort=new h.HashTable,this.ruleShortNameIdx=256,this.tokenMatcher=l.tokenStructuredMatcherNoCategories,this.definedRulesNames=[],this.tokensMap={},this.allRuleNames=[],this.isBackTrackingStack=[],this.RULE_STACK=[],this.RULE_OCCURRENCE_STACK=[],this.gastProductionsCache=new h.HashTable,this.serializedGrammar=r.has(e,"serializedGrammar")?e.serializedGrammar:u.DEFAULT_PARSER_CONFIG.serializedGrammar,r.isArray(t)){if(r.isEmpty(t))throw Error("A Token Vocabulary cannot be empty.\n\tNote that the first argument for the parser constructor\n\tis no longer a Token vector (since v4.0).");if("number"==typeof t[0].startOffset)throw Error("The Parser constructor no longer accepts a token vector as the first argument.\n\tSee: https://sap.github.io/chevrotain/docs/changes/BREAKING_CHANGES.html#_4-0-0\n\tFor Further details.")}if(r.isArray(t))this.tokensMap=r.reduce(t,function(t,e){return t[p.tokenName(e)]=e,t},{});else if(r.has(t,"modes")&&r.every(r.flatten(r.values(t.modes)),l.isTokenType)){var n=r.flatten(r.values(t.modes)),i=r.uniq(n);this.tokensMap=r.reduce(i,function(t,e){return t[p.tokenName(e)]=e,t},{})}else{if(!r.isObject(t))throw new Error(" argument must be An Array of Token constructors, A dictionary of Token constructors or an IMultiModeLexerDefinition");this.tokensMap=r.cloneObj(t)}this.tokensMap.EOF=p.EOF;var o=r.every(r.values(t),function(t){return r.isEmpty(t.categoryMatches)});this.tokenMatcher=o?l.tokenStructuredMatcherNoCategories:l.tokenStructuredMatcher,l.augmentTokenTypes(r.values(this.tokensMap))},t.prototype.defineRule=function(t,e,n){if(this.selfAnalysisDone)throw Error("Grammar rule <"+t+"> may not be defined after the 'performSelfAnalysis' method has been called'\nMake sure that all grammar rule definitions are done before 'performSelfAnalysis' is called.");var a,s=r.has(n,"resyncEnabled")?n.resyncEnabled:u.DEFAULT_RULE_CONFIG.resyncEnabled,c=r.has(n,"recoveryValueFunc")?n.recoveryValueFunc:u.DEFAULT_RULE_CONFIG.recoveryValueFunc,p=this.ruleShortNameIdx<e},t.prototype.orInternalNoCst=function(t,e){var n=r.isArray(t)?t:t.DEF,i=this.getLookaheadFuncForOr(e,n).call(this,n);if(void 0!==i)return n[i].ALT.call(this);this.raiseNoAltException(e,t.ERR_MSG)},t.prototype.orInternal=function(t,e){var n=this.getKeyForAutomaticLookahead(i.OR_IDX,e),o=this.nestedRuleBeforeClause(t,n);try{var a=r.isArray(t)?t:t.DEF,s=this.getLookaheadFuncForOr(e,a).call(this,a);if(void 0!==s){var u=a[s],c=this.nestedAltBeforeClause(u,e,i.OR_IDX,s);try{return u.ALT.call(this)}finally{void 0!==c&&this.nestedRuleFinallyClause(c.shortName,c.nestedName)}}this.raiseNoAltException(e,t.ERR_MSG)}finally{void 0!==o&&this.nestedRuleFinallyClause(n,o)}},t.prototype.ruleFinallyStateUpdate=function(){if(this.RULE_STACK.pop(),this.RULE_OCCURRENCE_STACK.pop(),this.cstFinallyStateUpdate(),0===this.RULE_STACK.length&&!this.isAtEndOfInput()){var t=this.LA(1),e=this.errorMessageProvider.buildNotAllInputParsedMessage({firstRedundant:t,ruleName:this.getCurrRuleFullName()});this.SAVE_ERROR(new o.NotAllInputParsedException(e,t))}},t.prototype.subruleInternal=function(t,e,n){var r;try{var i=void 0!==n?n.ARGS:void 0;return r=t.call(this,e,i),this.cstPostNonTerminal(r,void 0!==n&&void 0!==n.LABEL?n.LABEL:t.ruleName),r}catch(e){throw o.isRecognitionException(e)&&void 0!==e.partialCstResult&&(this.cstPostNonTerminal(e.partialCstResult,void 0!==n&&void 0!==n.LABEL?n.LABEL:t.ruleName),delete e.partialCstResult),e}},t.prototype.consumeInternal=function(t,e,n){var r;try{var i=this.LA(1);if(!0!==this.tokenMatcher(i,t)){var a=void 0,s=this.LA(0);throw a=void 0!==n&&n.ERR_MSG?n.ERR_MSG:this.errorMessageProvider.buildMismatchTokenMessage({expected:t,actual:i,previous:s,ruleName:this.getCurrRuleFullName()}),this.SAVE_ERROR(new o.MismatchedTokenException(a,i,s))}this.consumeToken(),r=i}catch(n){if(!this.recoveryEnabled||"MismatchedTokenException"!==n.name||this.isBackTracking())throw n;var u=this.getFollowsForInRuleRecovery(t,e);try{r=this.tryInRuleRecovery(t,u)}catch(t){throw t.name===c.IN_RULE_RECOVERY_EXCEPTION?n:t}}return this.cstPostTerminal(void 0!==n&&void 0!==n.LABEL?n.LABEL:t.tokenName,r),r},t.prototype.saveRecogState=function(){var t=this.errors,e=r.cloneArr(this.RULE_STACK);return{errors:t,lexerState:this.exportLexerState(),RULE_STACK:e,CST_STACK:this.CST_STACK,LAST_EXPLICIT_RULE_STACK:this.LAST_EXPLICIT_RULE_STACK}},t.prototype.reloadRecogState=function(t){this.errors=t.errors,this.importLexerState(t.lexerState),this.RULE_STACK=t.RULE_STACK},t.prototype.ruleInvocationStateUpdate=function(t,e,n){this.RULE_OCCURRENCE_STACK.push(n),this.RULE_STACK.push(t),this.cstInvocationStateUpdate(e,t)},t.prototype.isBackTracking=function(){return!r.isEmpty(this.isBackTrackingStack)},t.prototype.getCurrRuleFullName=function(){var t=this.getLastExplicitRuleShortName();return this.shortRuleNameToFull.get(t)},t.prototype.shortRuleNameToFullName=function(t){return this.shortRuleNameToFull.get(t)},t.prototype.isAtEndOfInput=function(){return this.tokenMatcher(this.LA(1),p.EOF)},t.prototype.reset=function(){this.resetLexerState(),this.isBackTrackingStack=[],this.errors=[],this.RULE_STACK=[],this.LAST_EXPLICIT_RULE_STACK=[],this.CST_STACK=[],this.RULE_OCCURRENCE_STACK=[]},t}();e.RecognizerEngine=f},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6),i=n(0),o=n(12),a=n(3),s=function(){function t(){}return t.prototype.initErrorHandler=function(t){this._errors=[],this.errorMessageProvider=i.defaults(t.errorMessageProvider,a.DEFAULT_PARSER_CONFIG.errorMessageProvider)},t.prototype.SAVE_ERROR=function(t){if(r.isRecognitionException(t))return t.context={ruleStack:this.getHumanReadableRuleStack(),ruleOccurrenceStack:i.cloneArr(this.RULE_OCCURRENCE_STACK)},this._errors.push(t),t;throw Error("Trying to save an Error which is not a RecognitionException")},Object.defineProperty(t.prototype,"errors",{get:function(){return i.cloneArr(this._errors)},set:function(t){this._errors=t},enumerable:!0,configurable:!0}),t.prototype.raiseEarlyExitException=function(t,e,n){for(var i=this.getCurrRuleFullName(),a=this.getGAstProductions().get(i),s=o.getLookaheadPathsForOptionalProd(t,a,e,this.maxLookahead)[0],u=[],c=1;c"+t+"<- does not exist in this grammar.");return r.nextPossibleTokensAfter([n],e,this.tokenMatcher,this.maxLookahead)},t.prototype.getNextPossibleTokenTypes=function(t){var e=i.first(t.ruleStack),n=this.getGAstProductions().get(e);return new r.NextAfterTokenWalker(n,t).startWalking()},t}();e.ContentAssist=o},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(17);e.createSyntaxDiagramsCode=function(t,e){var n=void 0===e?{}:e,i=n.resourceBase,o=void 0===i?"https://unpkg.com/chevrotain@"+r.VERSION+"/diagrams/":i,a=n.css;return"\n\x3c!-- This is a generated file --\x3e\n\n\n\n\n\n\n\n + + + +`,p=` +
+`,l=` + +`,m=` + +`;return s+c+f+p+l+m}cr.createSyntaxDiagramsCode=Iu});var Fa=R(E=>{"use strict";Object.defineProperty(E,"__esModule",{value:!0});E.Parser=E.createSyntaxDiagramsCode=E.clearCache=E.GAstVisitor=E.serializeProduction=E.serializeGrammar=E.Terminal=E.Rule=E.RepetitionWithSeparator=E.RepetitionMandatoryWithSeparator=E.RepetitionMandatory=E.Repetition=E.Option=E.NonTerminal=E.Alternative=E.Alternation=E.defaultLexerErrorProvider=E.NoViableAltException=E.NotAllInputParsedException=E.MismatchedTokenException=E.isRecognitionException=E.EarlyExitException=E.defaultParserErrorProvider=E.tokenName=E.tokenMatcher=E.tokenLabel=E.EOF=E.createTokenInstance=E.createToken=E.LexerDefinitionErrorType=E.Lexer=E.EMPTY_ALT=E.ParserDefinitionErrorType=E.EmbeddedActionsParser=E.CstParser=E.VERSION=void 0;var ku=Er();Object.defineProperty(E,"VERSION",{enumerable:!0,get:function(){return ku.VERSION}});var lr=ce();Object.defineProperty(E,"CstParser",{enumerable:!0,get:function(){return lr.CstParser}});Object.defineProperty(E,"EmbeddedActionsParser",{enumerable:!0,get:function(){return lr.EmbeddedActionsParser}});Object.defineProperty(E,"ParserDefinitionErrorType",{enumerable:!0,get:function(){return lr.ParserDefinitionErrorType}});Object.defineProperty(E,"EMPTY_ALT",{enumerable:!0,get:function(){return lr.EMPTY_ALT}});var Ma=ft();Object.defineProperty(E,"Lexer",{enumerable:!0,get:function(){return Ma.Lexer}});Object.defineProperty(E,"LexerDefinitionErrorType",{enumerable:!0,get:function(){return Ma.LexerDefinitionErrorType}});var nt=Ue();Object.defineProperty(E,"createToken",{enumerable:!0,get:function(){return nt.createToken}});Object.defineProperty(E,"createTokenInstance",{enumerable:!0,get:function(){return nt.createTokenInstance}});Object.defineProperty(E,"EOF",{enumerable:!0,get:function(){return nt.EOF}});Object.defineProperty(E,"tokenLabel",{enumerable:!0,get:function(){return nt.tokenLabel}});Object.defineProperty(E,"tokenMatcher",{enumerable:!0,get:function(){return nt.tokenMatcher}});Object.defineProperty(E,"tokenName",{enumerable:!0,get:function(){return nt.tokenName}});var Pu=mt();Object.defineProperty(E,"defaultParserErrorProvider",{enumerable:!0,get:function(){return Pu.defaultParserErrorProvider}});var Nt=et();Object.defineProperty(E,"EarlyExitException",{enumerable:!0,get:function(){return Nt.EarlyExitException}});Object.defineProperty(E,"isRecognitionException",{enumerable:!0,get:function(){return Nt.isRecognitionException}});Object.defineProperty(E,"MismatchedTokenException",{enumerable:!0,get:function(){return Nt.MismatchedTokenException}});Object.defineProperty(E,"NotAllInputParsedException",{enumerable:!0,get:function(){return Nt.NotAllInputParsedException}});Object.defineProperty(E,"NoViableAltException",{enumerable:!0,get:function(){return Nt.NoViableAltException}});var Su=kr();Object.defineProperty(E,"defaultLexerErrorProvider",{enumerable:!0,get:function(){return Su.defaultLexerErrorProvider}});var Se=ne();Object.defineProperty(E,"Alternation",{enumerable:!0,get:function(){return Se.Alternation}});Object.defineProperty(E,"Alternative",{enumerable:!0,get:function(){return Se.Alternative}});Object.defineProperty(E,"NonTerminal",{enumerable:!0,get:function(){return Se.NonTerminal}});Object.defineProperty(E,"Option",{enumerable:!0,get:function(){return Se.Option}});Object.defineProperty(E,"Repetition",{enumerable:!0,get:function(){return Se.Repetition}});Object.defineProperty(E,"RepetitionMandatory",{enumerable:!0,get:function(){return Se.RepetitionMandatory}});Object.defineProperty(E,"RepetitionMandatoryWithSeparator",{enumerable:!0,get:function(){return Se.RepetitionMandatoryWithSeparator}});Object.defineProperty(E,"RepetitionWithSeparator",{enumerable:!0,get:function(){return Se.RepetitionWithSeparator}});Object.defineProperty(E,"Rule",{enumerable:!0,get:function(){return Se.Rule}});Object.defineProperty(E,"Terminal",{enumerable:!0,get:function(){return Se.Terminal}});var ba=ne();Object.defineProperty(E,"serializeGrammar",{enumerable:!0,get:function(){return ba.serializeGrammar}});Object.defineProperty(E,"serializeProduction",{enumerable:!0,get:function(){return ba.serializeProduction}});var xu=$e();Object.defineProperty(E,"GAstVisitor",{enumerable:!0,get:function(){return xu.GAstVisitor}});function Cu(){console.warn(`The clearCache function was 'soft' removed from the Chevrotain API. + It performs no action other than printing this message. + Please avoid using it as it will be completely removed in the future`)}E.clearCache=Cu;var Lu=La();Object.defineProperty(E,"createSyntaxDiagramsCode",{enumerable:!0,get:function(){return Lu.createSyntaxDiagramsCode}});var Mu=function(){function t(){throw new Error(`The Parser class has been deprecated, use CstParser or EmbeddedActionsParser instead. +See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_7-0-0`)}return t}();E.Parser=Mu});export default Fa(); diff --git a/examples/jsm/libs/fflate.module.js b/examples/jsm/libs/fflate.module.js new file mode 100644 index 00000000000000..808000a503cf63 --- /dev/null +++ b/examples/jsm/libs/fflate.module.js @@ -0,0 +1,2474 @@ +/*! +fflate - fast JavaScript compression/decompression + +Licensed under MIT. https://github.com/101arrowz/fflate/blob/master/LICENSE +version 0.6.9 +*/ + +// DEFLATE is a complex format; to read this code, you should probably check the RFC first: +// https://tools.ietf.org/html/rfc1951 +// You may also wish to take a look at the guide I made about this program: +// https://gist.github.com/101arrowz/253f31eb5abc3d9275ab943003ffecad +// Some of the following code is similar to that of UZIP.js: +// https://github.com/photopea/UZIP.js +// However, the vast majority of the codebase has diverged from UZIP.js to increase performance and reduce bundle size. +// Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint +// is better for memory in most engines (I *think*). +var ch2 = {}; +var durl = function (c) { return URL.createObjectURL(new Blob([c], { type: 'text/javascript' })); }; +var cwk = function (u) { return new Worker(u); }; +try { + URL.revokeObjectURL(durl('')); +} +catch (e) { + // We're in Deno or a very old browser + durl = function (c) { return 'data:application/javascript;charset=UTF-8,' + encodeURI(c); }; + // If Deno, this is necessary; if not, this changes nothing + cwk = function (u) { return new Worker(u, { type: 'module' }); }; +} +var wk = (function (c, id, msg, transfer, cb) { + var w = cwk(ch2[id] || (ch2[id] = durl(c))); + w.onerror = function (e) { return cb(e.error, null); }; + w.onmessage = function (e) { return cb(null, e.data); }; + w.postMessage(msg, transfer); + return w; +}); + +// aliases for shorter compressed code (most minifers don't do this) +var u8 = Uint8Array, u16 = Uint16Array, u32 = Uint32Array; +// fixed length extra bits +var fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]); +// fixed distance extra bits +// see fleb note +var fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 0, 0]); +// code length index map +var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); +// get base, reverse index map from extra bits +var freb = function (eb, start) { + var b = new u16(31); + for (var i = 0; i < 31; ++i) { + b[i] = start += 1 << eb[i - 1]; + } + // numbers here are at max 18 bits + var r = new u32(b[30]); + for (var i = 1; i < 30; ++i) { + for (var j = b[i]; j < b[i + 1]; ++j) { + r[j] = ((j - b[i]) << 5) | i; + } + } + return [b, r]; +}; +var _a = freb(fleb, 2), fl = _a[0], revfl = _a[1]; +// we can ignore the fact that the other numbers are wrong; they never happen anyway +fl[28] = 258, revfl[258] = 28; +var _b = freb(fdeb, 0), fd = _b[0], revfd = _b[1]; +// map of value to reverse (assuming 16 bits) +var rev = new u16(32768); +for (var i = 0; i < 32768; ++i) { + // reverse table algorithm from SO + var x = ((i & 0xAAAA) >>> 1) | ((i & 0x5555) << 1); + x = ((x & 0xCCCC) >>> 2) | ((x & 0x3333) << 2); + x = ((x & 0xF0F0) >>> 4) | ((x & 0x0F0F) << 4); + rev[i] = (((x & 0xFF00) >>> 8) | ((x & 0x00FF) << 8)) >>> 1; +} +// create huffman tree from u8 "map": index -> code length for code index +// mb (max bits) must be at most 15 +// TODO: optimize/split up? +var hMap = (function (cd, mb, r) { + var s = cd.length; + // index + var i = 0; + // u16 "map": index -> # of codes with bit length = index + var l = new u16(mb); + // length of cd must be 288 (total # of codes) + for (; i < s; ++i) + ++l[cd[i] - 1]; + // u16 "map": index -> minimum code for bit length = index + var le = new u16(mb); + for (i = 0; i < mb; ++i) { + le[i] = (le[i - 1] + l[i - 1]) << 1; + } + var co; + if (r) { + // u16 "map": index -> number of actual bits, symbol for code + co = new u16(1 << mb); + // bits to remove for reverser + var rvb = 15 - mb; + for (i = 0; i < s; ++i) { + // ignore 0 lengths + if (cd[i]) { + // num encoding both symbol and bits read + var sv = (i << 4) | cd[i]; + // free bits + var r_1 = mb - cd[i]; + // start value + var v = le[cd[i] - 1]++ << r_1; + // m is end value + for (var m = v | ((1 << r_1) - 1); v <= m; ++v) { + // every 16 bit value starting with the code yields the same result + co[rev[v] >>> rvb] = sv; + } + } + } + } + else { + co = new u16(s); + for (i = 0; i < s; ++i) { + if (cd[i]) { + co[i] = rev[le[cd[i] - 1]++] >>> (15 - cd[i]); + } + } + } + return co; +}); +// fixed length tree +var flt = new u8(288); +for (var i = 0; i < 144; ++i) + flt[i] = 8; +for (var i = 144; i < 256; ++i) + flt[i] = 9; +for (var i = 256; i < 280; ++i) + flt[i] = 7; +for (var i = 280; i < 288; ++i) + flt[i] = 8; +// fixed distance tree +var fdt = new u8(32); +for (var i = 0; i < 32; ++i) + fdt[i] = 5; +// fixed length map +var flm = /*#__PURE__*/ hMap(flt, 9, 0), flrm = /*#__PURE__*/ hMap(flt, 9, 1); +// fixed distance map +var fdm = /*#__PURE__*/ hMap(fdt, 5, 0), fdrm = /*#__PURE__*/ hMap(fdt, 5, 1); +// find max of array +var max = function (a) { + var m = a[0]; + for (var i = 1; i < a.length; ++i) { + if (a[i] > m) + m = a[i]; + } + return m; +}; +// read d, starting at bit p and mask with m +var bits = function (d, p, m) { + var o = (p / 8) | 0; + return ((d[o] | (d[o + 1] << 8)) >> (p & 7)) & m; +}; +// read d, starting at bit p continuing for at least 16 bits +var bits16 = function (d, p) { + var o = (p / 8) | 0; + return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16)) >> (p & 7)); +}; +// get end of byte +var shft = function (p) { return ((p / 8) | 0) + (p & 7 && 1); }; +// typed array slice - allows garbage collector to free original reference, +// while being more compatible than .slice +var slc = function (v, s, e) { + if (s == null || s < 0) + s = 0; + if (e == null || e > v.length) + e = v.length; + // can't use .constructor in case user-supplied + var n = new (v instanceof u16 ? u16 : v instanceof u32 ? u32 : u8)(e - s); + n.set(v.subarray(s, e)); + return n; +}; +// expands raw DEFLATE data +var inflt = function (dat, buf, st) { + // source length + var sl = dat.length; + if (!sl || (st && !st.l && sl < 5)) + return buf || new u8(0); + // have to estimate size + var noBuf = !buf || st; + // no state + var noSt = !st || st.i; + if (!st) + st = {}; + // Assumes roughly 33% compression ratio average + if (!buf) + buf = new u8(sl * 3); + // ensure buffer can fit at least l elements + var cbuf = function (l) { + var bl = buf.length; + // need to increase size to fit + if (l > bl) { + // Double or set to necessary, whichever is greater + var nbuf = new u8(Math.max(bl * 2, l)); + nbuf.set(buf); + buf = nbuf; + } + }; + // last chunk bitpos bytes + var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n; + // total bits + var tbts = sl * 8; + do { + if (!lm) { + // BFINAL - this is only 1 when last chunk is next + st.f = final = bits(dat, pos, 1); + // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman + var type = bits(dat, pos + 1, 3); + pos += 3; + if (!type) { + // go to end of byte boundary + var s = shft(pos) + 4, l = dat[s - 4] | (dat[s - 3] << 8), t = s + l; + if (t > sl) { + if (noSt) + throw 'unexpected EOF'; + break; + } + // ensure size + if (noBuf) + cbuf(bt + l); + // Copy over uncompressed data + buf.set(dat.subarray(s, t), bt); + // Get new bitpos, update byte count + st.b = bt += l, st.p = pos = t * 8; + continue; + } + else if (type == 1) + lm = flrm, dm = fdrm, lbt = 9, dbt = 5; + else if (type == 2) { + // literal lengths + var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4; + var tl = hLit + bits(dat, pos + 5, 31) + 1; + pos += 14; + // length+distance tree + var ldt = new u8(tl); + // code length tree + var clt = new u8(19); + for (var i = 0; i < hcLen; ++i) { + // use index map to get real code + clt[clim[i]] = bits(dat, pos + i * 3, 7); + } + pos += hcLen * 3; + // code lengths bits + var clb = max(clt), clbmsk = (1 << clb) - 1; + // code lengths map + var clm = hMap(clt, clb, 1); + for (var i = 0; i < tl;) { + var r = clm[bits(dat, pos, clbmsk)]; + // bits read + pos += r & 15; + // symbol + var s = r >>> 4; + // code length to copy + if (s < 16) { + ldt[i++] = s; + } + else { + // copy count + var c = 0, n = 0; + if (s == 16) + n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1]; + else if (s == 17) + n = 3 + bits(dat, pos, 7), pos += 3; + else if (s == 18) + n = 11 + bits(dat, pos, 127), pos += 7; + while (n--) + ldt[i++] = c; + } + } + // length tree distance tree + var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit); + // max length bits + lbt = max(lt); + // max dist bits + dbt = max(dt); + lm = hMap(lt, lbt, 1); + dm = hMap(dt, dbt, 1); + } + else + throw 'invalid block type'; + if (pos > tbts) { + if (noSt) + throw 'unexpected EOF'; + break; + } + } + // Make sure the buffer can hold this + the largest possible addition + // Maximum chunk size (practically, theoretically infinite) is 2^17; + if (noBuf) + cbuf(bt + 131072); + var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1; + var lpos = pos; + for (;; lpos = pos) { + // bits read, code + var c = lm[bits16(dat, pos) & lms], sym = c >>> 4; + pos += c & 15; + if (pos > tbts) { + if (noSt) + throw 'unexpected EOF'; + break; + } + if (!c) + throw 'invalid length/literal'; + if (sym < 256) + buf[bt++] = sym; + else if (sym == 256) { + lpos = pos, lm = null; + break; + } + else { + var add = sym - 254; + // no extra bits needed if less + if (sym > 264) { + // index + var i = sym - 257, b = fleb[i]; + add = bits(dat, pos, (1 << b) - 1) + fl[i]; + pos += b; + } + // dist + var d = dm[bits16(dat, pos) & dms], dsym = d >>> 4; + if (!d) + throw 'invalid distance'; + pos += d & 15; + var dt = fd[dsym]; + if (dsym > 3) { + var b = fdeb[dsym]; + dt += bits16(dat, pos) & ((1 << b) - 1), pos += b; + } + if (pos > tbts) { + if (noSt) + throw 'unexpected EOF'; + break; + } + if (noBuf) + cbuf(bt + 131072); + var end = bt + add; + for (; bt < end; bt += 4) { + buf[bt] = buf[bt - dt]; + buf[bt + 1] = buf[bt + 1 - dt]; + buf[bt + 2] = buf[bt + 2 - dt]; + buf[bt + 3] = buf[bt + 3 - dt]; + } + bt = end; + } + } + st.l = lm, st.p = lpos, st.b = bt; + if (lm) + final = 1, st.m = lbt, st.d = dm, st.n = dbt; + } while (!final); + return bt == buf.length ? buf : slc(buf, 0, bt); +}; +// starting at p, write the minimum number of bits that can hold v to d +var wbits = function (d, p, v) { + v <<= p & 7; + var o = (p / 8) | 0; + d[o] |= v; + d[o + 1] |= v >>> 8; +}; +// starting at p, write the minimum number of bits (>8) that can hold v to d +var wbits16 = function (d, p, v) { + v <<= p & 7; + var o = (p / 8) | 0; + d[o] |= v; + d[o + 1] |= v >>> 8; + d[o + 2] |= v >>> 16; +}; +// creates code lengths from a frequency table +var hTree = function (d, mb) { + // Need extra info to make a tree + var t = []; + for (var i = 0; i < d.length; ++i) { + if (d[i]) + t.push({ s: i, f: d[i] }); + } + var s = t.length; + var t2 = t.slice(); + if (!s) + return [et, 0]; + if (s == 1) { + var v = new u8(t[0].s + 1); + v[t[0].s] = 1; + return [v, 1]; + } + t.sort(function (a, b) { return a.f - b.f; }); + // after i2 reaches last ind, will be stopped + // freq must be greater than largest possible number of symbols + t.push({ s: -1, f: 25001 }); + var l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2; + t[0] = { s: -1, f: l.f + r.f, l: l, r: r }; + // efficient algorithm from UZIP.js + // i0 is lookbehind, i2 is lookahead - after processing two low-freq + // symbols that combined have high freq, will start processing i2 (high-freq, + // non-composite) symbols instead + // see https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/ + while (i1 != s - 1) { + l = t[t[i0].f < t[i2].f ? i0++ : i2++]; + r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++]; + t[i1++] = { s: -1, f: l.f + r.f, l: l, r: r }; + } + var maxSym = t2[0].s; + for (var i = 1; i < s; ++i) { + if (t2[i].s > maxSym) + maxSym = t2[i].s; + } + // code lengths + var tr = new u16(maxSym + 1); + // max bits in tree + var mbt = ln(t[i1 - 1], tr, 0); + if (mbt > mb) { + // more algorithms from UZIP.js + // TODO: find out how this code works (debt) + // ind debt + var i = 0, dt = 0; + // left cost + var lft = mbt - mb, cst = 1 << lft; + t2.sort(function (a, b) { return tr[b.s] - tr[a.s] || a.f - b.f; }); + for (; i < s; ++i) { + var i2_1 = t2[i].s; + if (tr[i2_1] > mb) { + dt += cst - (1 << (mbt - tr[i2_1])); + tr[i2_1] = mb; + } + else + break; + } + dt >>>= lft; + while (dt > 0) { + var i2_2 = t2[i].s; + if (tr[i2_2] < mb) + dt -= 1 << (mb - tr[i2_2]++ - 1); + else + ++i; + } + for (; i >= 0 && dt; --i) { + var i2_3 = t2[i].s; + if (tr[i2_3] == mb) { + --tr[i2_3]; + ++dt; + } + } + mbt = mb; + } + return [new u8(tr), mbt]; +}; +// get the max length and assign length codes +var ln = function (n, l, d) { + return n.s == -1 + ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1)) + : (l[n.s] = d); +}; +// length codes generation +var lc = function (c) { + var s = c.length; + // Note that the semicolon was intentional + while (s && !c[--s]) + ; + var cl = new u16(++s); + // ind num streak + var cli = 0, cln = c[0], cls = 1; + var w = function (v) { cl[cli++] = v; }; + for (var i = 1; i <= s; ++i) { + if (c[i] == cln && i != s) + ++cls; + else { + if (!cln && cls > 2) { + for (; cls > 138; cls -= 138) + w(32754); + if (cls > 2) { + w(cls > 10 ? ((cls - 11) << 5) | 28690 : ((cls - 3) << 5) | 12305); + cls = 0; + } + } + else if (cls > 3) { + w(cln), --cls; + for (; cls > 6; cls -= 6) + w(8304); + if (cls > 2) + w(((cls - 3) << 5) | 8208), cls = 0; + } + while (cls--) + w(cln); + cls = 1; + cln = c[i]; + } + } + return [cl.subarray(0, cli), s]; +}; +// calculate the length of output from tree, code lengths +var clen = function (cf, cl) { + var l = 0; + for (var i = 0; i < cl.length; ++i) + l += cf[i] * cl[i]; + return l; +}; +// writes a fixed block +// returns the new bit pos +var wfblk = function (out, pos, dat) { + // no need to write 00 as type: TypedArray defaults to 0 + var s = dat.length; + var o = shft(pos + 2); + out[o] = s & 255; + out[o + 1] = s >>> 8; + out[o + 2] = out[o] ^ 255; + out[o + 3] = out[o + 1] ^ 255; + for (var i = 0; i < s; ++i) + out[o + i + 4] = dat[i]; + return (o + 4 + s) * 8; +}; +// writes a block +var wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) { + wbits(out, p++, final); + ++lf[256]; + var _a = hTree(lf, 15), dlt = _a[0], mlb = _a[1]; + var _b = hTree(df, 15), ddt = _b[0], mdb = _b[1]; + var _c = lc(dlt), lclt = _c[0], nlc = _c[1]; + var _d = lc(ddt), lcdt = _d[0], ndc = _d[1]; + var lcfreq = new u16(19); + for (var i = 0; i < lclt.length; ++i) + lcfreq[lclt[i] & 31]++; + for (var i = 0; i < lcdt.length; ++i) + lcfreq[lcdt[i] & 31]++; + var _e = hTree(lcfreq, 7), lct = _e[0], mlcb = _e[1]; + var nlcc = 19; + for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc) + ; + var flen = (bl + 5) << 3; + var ftlen = clen(lf, flt) + clen(df, fdt) + eb; + var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + (2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18]); + if (flen <= ftlen && flen <= dtlen) + return wfblk(out, p, dat.subarray(bs, bs + bl)); + var lm, ll, dm, dl; + wbits(out, p, 1 + (dtlen < ftlen)), p += 2; + if (dtlen < ftlen) { + lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt; + var llm = hMap(lct, mlcb, 0); + wbits(out, p, nlc - 257); + wbits(out, p + 5, ndc - 1); + wbits(out, p + 10, nlcc - 4); + p += 14; + for (var i = 0; i < nlcc; ++i) + wbits(out, p + 3 * i, lct[clim[i]]); + p += 3 * nlcc; + var lcts = [lclt, lcdt]; + for (var it = 0; it < 2; ++it) { + var clct = lcts[it]; + for (var i = 0; i < clct.length; ++i) { + var len = clct[i] & 31; + wbits(out, p, llm[len]), p += lct[len]; + if (len > 15) + wbits(out, p, (clct[i] >>> 5) & 127), p += clct[i] >>> 12; + } + } + } + else { + lm = flm, ll = flt, dm = fdm, dl = fdt; + } + for (var i = 0; i < li; ++i) { + if (syms[i] > 255) { + var len = (syms[i] >>> 18) & 31; + wbits16(out, p, lm[len + 257]), p += ll[len + 257]; + if (len > 7) + wbits(out, p, (syms[i] >>> 23) & 31), p += fleb[len]; + var dst = syms[i] & 31; + wbits16(out, p, dm[dst]), p += dl[dst]; + if (dst > 3) + wbits16(out, p, (syms[i] >>> 5) & 8191), p += fdeb[dst]; + } + else { + wbits16(out, p, lm[syms[i]]), p += ll[syms[i]]; + } + } + wbits16(out, p, lm[256]); + return p + ll[256]; +}; +// deflate options (nice << 13) | chain +var deo = /*#__PURE__*/ new u32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]); +// empty +var et = /*#__PURE__*/ new u8(0); +// compresses data into a raw DEFLATE buffer +var dflt = function (dat, lvl, plvl, pre, post, lst) { + var s = dat.length; + var o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7000)) + post); + // writing to this writes to the output buffer + var w = o.subarray(pre, o.length - post); + var pos = 0; + if (!lvl || s < 8) { + for (var i = 0; i <= s; i += 65535) { + // end + var e = i + 65535; + if (e < s) { + // write full block + pos = wfblk(w, pos, dat.subarray(i, e)); + } + else { + // write final block + w[i] = lst; + pos = wfblk(w, pos, dat.subarray(i, s)); + } + } + } + else { + var opt = deo[lvl - 1]; + var n = opt >>> 13, c = opt & 8191; + var msk_1 = (1 << plvl) - 1; + // prev 2-byte val map curr 2-byte val map + var prev = new u16(32768), head = new u16(msk_1 + 1); + var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1; + var hsh = function (i) { return (dat[i] ^ (dat[i + 1] << bs1_1) ^ (dat[i + 2] << bs2_1)) & msk_1; }; + // 24576 is an arbitrary number of maximum symbols per block + // 424 buffer for last block + var syms = new u32(25000); + // length/literal freq distance freq + var lf = new u16(288), df = new u16(32); + // l/lcnt exbits index l/lind waitdx bitpos + var lc_1 = 0, eb = 0, i = 0, li = 0, wi = 0, bs = 0; + for (; i < s; ++i) { + // hash value + // deopt when i > s - 3 - at end, deopt acceptable + var hv = hsh(i); + // index mod 32768 previous index mod + var imod = i & 32767, pimod = head[hv]; + prev[imod] = pimod; + head[hv] = imod; + // We always should modify head and prev, but only add symbols if + // this data is not yet processed ("wait" for wait index) + if (wi <= i) { + // bytes remaining + var rem = s - i; + if ((lc_1 > 7000 || li > 24576) && rem > 423) { + pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos); + li = lc_1 = eb = 0, bs = i; + for (var j = 0; j < 286; ++j) + lf[j] = 0; + for (var j = 0; j < 30; ++j) + df[j] = 0; + } + // len dist chain + var l = 2, d = 0, ch_1 = c, dif = (imod - pimod) & 32767; + if (rem > 2 && hv == hsh(i - dif)) { + var maxn = Math.min(n, rem) - 1; + var maxd = Math.min(32767, i); + // max possible length + // not capped at dif because decompressors implement "rolling" index population + var ml = Math.min(258, rem); + while (dif <= maxd && --ch_1 && imod != pimod) { + if (dat[i + l] == dat[i + l - dif]) { + var nl = 0; + for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl) + ; + if (nl > l) { + l = nl, d = dif; + // break out early when we reach "nice" (we are satisfied enough) + if (nl > maxn) + break; + // now, find the rarest 2-byte sequence within this + // length of literals and search for that instead. + // Much faster than just using the start + var mmd = Math.min(dif, nl - 2); + var md = 0; + for (var j = 0; j < mmd; ++j) { + var ti = (i - dif + j + 32768) & 32767; + var pti = prev[ti]; + var cd = (ti - pti + 32768) & 32767; + if (cd > md) + md = cd, pimod = ti; + } + } + } + // check the previous match + imod = pimod, pimod = prev[imod]; + dif += (imod - pimod + 32768) & 32767; + } + } + // d will be nonzero only when a match was found + if (d) { + // store both dist and len data in one Uint32 + // Make sure this is recognized as a len/dist with 28th bit (2^28) + syms[li++] = 268435456 | (revfl[l] << 18) | revfd[d]; + var lin = revfl[l] & 31, din = revfd[d] & 31; + eb += fleb[lin] + fdeb[din]; + ++lf[257 + lin]; + ++df[din]; + wi = i + l; + ++lc_1; + } + else { + syms[li++] = dat[i]; + ++lf[dat[i]]; + } + } + } + pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos); + // this is the easiest way to avoid needing to maintain state + if (!lst && pos & 7) + pos = wfblk(w, pos + 1, et); + } + return slc(o, 0, pre + shft(pos) + post); +}; +// CRC32 table +var crct = /*#__PURE__*/ (function () { + var t = new u32(256); + for (var i = 0; i < 256; ++i) { + var c = i, k = 9; + while (--k) + c = ((c & 1) && 0xEDB88320) ^ (c >>> 1); + t[i] = c; + } + return t; +})(); +// CRC32 +var crc = function () { + var c = -1; + return { + p: function (d) { + // closures have awful performance + var cr = c; + for (var i = 0; i < d.length; ++i) + cr = crct[(cr & 255) ^ d[i]] ^ (cr >>> 8); + c = cr; + }, + d: function () { return ~c; } + }; +}; +// Alder32 +var adler = function () { + var a = 1, b = 0; + return { + p: function (d) { + // closures have awful performance + var n = a, m = b; + var l = d.length; + for (var i = 0; i != l;) { + var e = Math.min(i + 2655, l); + for (; i < e; ++i) + m += n += d[i]; + n = (n & 65535) + 15 * (n >> 16), m = (m & 65535) + 15 * (m >> 16); + } + a = n, b = m; + }, + d: function () { + a %= 65521, b %= 65521; + return (a & 255) << 24 | (a >>> 8) << 16 | (b & 255) << 8 | (b >>> 8); + } + }; +}; +; +// deflate with opts +var dopt = function (dat, opt, pre, post, st) { + return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : (12 + opt.mem), pre, post, !st); +}; +// Walmart object spread +var mrg = function (a, b) { + var o = {}; + for (var k in a) + o[k] = a[k]; + for (var k in b) + o[k] = b[k]; + return o; +}; +// worker clone +// This is possibly the craziest part of the entire codebase, despite how simple it may seem. +// The only parameter to this function is a closure that returns an array of variables outside of the function scope. +// We're going to try to figure out the variable names used in the closure as strings because that is crucial for workerization. +// We will return an object mapping of true variable name to value (basically, the current scope as a JS object). +// The reason we can't just use the original variable names is minifiers mangling the toplevel scope. +// This took me three weeks to figure out how to do. +var wcln = function (fn, fnStr, td) { + var dt = fn(); + var st = fn.toString(); + var ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/ /g, '').split(','); + for (var i = 0; i < dt.length; ++i) { + var v = dt[i], k = ks[i]; + if (typeof v == 'function') { + fnStr += ';' + k + '='; + var st_1 = v.toString(); + if (v.prototype) { + // for global objects + if (st_1.indexOf('[native code]') != -1) { + var spInd = st_1.indexOf(' ', 8) + 1; + fnStr += st_1.slice(spInd, st_1.indexOf('(', spInd)); + } + else { + fnStr += st_1; + for (var t in v.prototype) + fnStr += ';' + k + '.prototype.' + t + '=' + v.prototype[t].toString(); + } + } + else + fnStr += st_1; + } + else + td[k] = v; + } + return [fnStr, td]; +}; +var ch = []; +// clone bufs +var cbfs = function (v) { + var tl = []; + for (var k in v) { + if (v[k] instanceof u8 || v[k] instanceof u16 || v[k] instanceof u32) + tl.push((v[k] = new v[k].constructor(v[k])).buffer); + } + return tl; +}; +// use a worker to execute code +var wrkr = function (fns, init, id, cb) { + var _a; + if (!ch[id]) { + var fnStr = '', td_1 = {}, m = fns.length - 1; + for (var i = 0; i < m; ++i) + _a = wcln(fns[i], fnStr, td_1), fnStr = _a[0], td_1 = _a[1]; + ch[id] = wcln(fns[m], fnStr, td_1); + } + var td = mrg({}, ch[id][1]); + return wk(ch[id][0] + ';onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=' + init.toString() + '}', id, td, cbfs(td), cb); +}; +// base async inflate fn +var bInflt = function () { return [u8, u16, u32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, hMap, max, bits, bits16, shft, slc, inflt, inflateSync, pbf, gu8]; }; +var bDflt = function () { return [u8, u16, u32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf]; }; +// gzip extra +var gze = function () { return [gzh, gzhl, wbytes, crc, crct]; }; +// gunzip extra +var guze = function () { return [gzs, gzl]; }; +// zlib extra +var zle = function () { return [zlh, wbytes, adler]; }; +// unzlib extra +var zule = function () { return [zlv]; }; +// post buf +var pbf = function (msg) { return postMessage(msg, [msg.buffer]); }; +// get u8 +var gu8 = function (o) { return o && o.size && new u8(o.size); }; +// async helper +var cbify = function (dat, opts, fns, init, id, cb) { + var w = wrkr(fns, init, id, function (err, dat) { + w.terminate(); + cb(err, dat); + }); + w.postMessage([dat, opts], opts.consume ? [dat.buffer] : []); + return function () { w.terminate(); }; +}; +// auto stream +var astrm = function (strm) { + strm.ondata = function (dat, final) { return postMessage([dat, final], [dat.buffer]); }; + return function (ev) { return strm.push(ev.data[0], ev.data[1]); }; +}; +// async stream attach +var astrmify = function (fns, strm, opts, init, id) { + var t; + var w = wrkr(fns, init, id, function (err, dat) { + if (err) + w.terminate(), strm.ondata.call(strm, err); + else { + if (dat[1]) + w.terminate(); + strm.ondata.call(strm, err, dat[0], dat[1]); + } + }); + w.postMessage(opts); + strm.push = function (d, f) { + if (t) + throw 'stream finished'; + if (!strm.ondata) + throw 'no stream handler'; + w.postMessage([d, t = f], [d.buffer]); + }; + strm.terminate = function () { w.terminate(); }; +}; +// read 2 bytes +var b2 = function (d, b) { return d[b] | (d[b + 1] << 8); }; +// read 4 bytes +var b4 = function (d, b) { return (d[b] | (d[b + 1] << 8) | (d[b + 2] << 16) | (d[b + 3] << 24)) >>> 0; }; +var b8 = function (d, b) { return b4(d, b) + (b4(d, b + 4) * 4294967296); }; +// write bytes +var wbytes = function (d, b, v) { + for (; v; ++b) + d[b] = v, v >>>= 8; +}; +// gzip header +var gzh = function (c, o) { + var fn = o.filename; + c[0] = 31, c[1] = 139, c[2] = 8, c[8] = o.level < 2 ? 4 : o.level == 9 ? 2 : 0, c[9] = 3; // assume Unix + if (o.mtime != 0) + wbytes(c, 4, Math.floor(new Date(o.mtime || Date.now()) / 1000)); + if (fn) { + c[3] = 8; + for (var i = 0; i <= fn.length; ++i) + c[i + 10] = fn.charCodeAt(i); + } +}; +// gzip footer: -8 to -4 = CRC, -4 to -0 is length +// gzip start +var gzs = function (d) { + if (d[0] != 31 || d[1] != 139 || d[2] != 8) + throw 'invalid gzip data'; + var flg = d[3]; + var st = 10; + if (flg & 4) + st += d[10] | (d[11] << 8) + 2; + for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]) + ; + return st + (flg & 2); +}; +// gzip length +var gzl = function (d) { + var l = d.length; + return ((d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16) | (d[l - 1] << 24)) >>> 0; +}; +// gzip header length +var gzhl = function (o) { return 10 + ((o.filename && (o.filename.length + 1)) || 0); }; +// zlib header +var zlh = function (c, o) { + var lv = o.level, fl = lv == 0 ? 0 : lv < 6 ? 1 : lv == 9 ? 3 : 2; + c[0] = 120, c[1] = (fl << 6) | (fl ? (32 - 2 * fl) : 1); +}; +// zlib valid +var zlv = function (d) { + if ((d[0] & 15) != 8 || (d[0] >>> 4) > 7 || ((d[0] << 8 | d[1]) % 31)) + throw 'invalid zlib data'; + if (d[1] & 32) + throw 'invalid zlib data: preset dictionaries not supported'; +}; +function AsyncCmpStrm(opts, cb) { + if (!cb && typeof opts == 'function') + cb = opts, opts = {}; + this.ondata = cb; + return opts; +} +// zlib footer: -4 to -0 is Adler32 +/** + * Streaming DEFLATE compression + */ +var Deflate = /*#__PURE__*/ (function () { + function Deflate(opts, cb) { + if (!cb && typeof opts == 'function') + cb = opts, opts = {}; + this.ondata = cb; + this.o = opts || {}; + } + Deflate.prototype.p = function (c, f) { + this.ondata(dopt(c, this.o, 0, 0, !f), f); + }; + /** + * Pushes a chunk to be deflated + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Deflate.prototype.push = function (chunk, final) { + if (this.d) + throw 'stream finished'; + if (!this.ondata) + throw 'no stream handler'; + this.d = final; + this.p(chunk, final || false); + }; + return Deflate; +}()); +export { Deflate }; +/** + * Asynchronous streaming DEFLATE compression + */ +var AsyncDeflate = /*#__PURE__*/ (function () { + function AsyncDeflate(opts, cb) { + astrmify([ + bDflt, + function () { return [astrm, Deflate]; } + ], this, AsyncCmpStrm.call(this, opts, cb), function (ev) { + var strm = new Deflate(ev.data); + onmessage = astrm(strm); + }, 6); + } + return AsyncDeflate; +}()); +export { AsyncDeflate }; +export function deflate(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return cbify(data, opts, [ + bDflt, + ], function (ev) { return pbf(deflateSync(ev.data[0], ev.data[1])); }, 0, cb); +} +/** + * Compresses data with DEFLATE without any wrapper + * @param data The data to compress + * @param opts The compression options + * @returns The deflated version of the data + */ +export function deflateSync(data, opts) { + return dopt(data, opts || {}, 0, 0); +} +/** + * Streaming DEFLATE decompression + */ +var Inflate = /*#__PURE__*/ (function () { + /** + * Creates an inflation stream + * @param cb The callback to call whenever data is inflated + */ + function Inflate(cb) { + this.s = {}; + this.p = new u8(0); + this.ondata = cb; + } + Inflate.prototype.e = function (c) { + if (this.d) + throw 'stream finished'; + if (!this.ondata) + throw 'no stream handler'; + var l = this.p.length; + var n = new u8(l + c.length); + n.set(this.p), n.set(c, l), this.p = n; + }; + Inflate.prototype.c = function (final) { + this.d = this.s.i = final || false; + var bts = this.s.b; + var dt = inflt(this.p, this.o, this.s); + this.ondata(slc(dt, bts, this.s.b), this.d); + this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length; + this.p = slc(this.p, (this.s.p / 8) | 0), this.s.p &= 7; + }; + /** + * Pushes a chunk to be inflated + * @param chunk The chunk to push + * @param final Whether this is the final chunk + */ + Inflate.prototype.push = function (chunk, final) { + this.e(chunk), this.c(final); + }; + return Inflate; +}()); +export { Inflate }; +/** + * Asynchronous streaming DEFLATE decompression + */ +var AsyncInflate = /*#__PURE__*/ (function () { + /** + * Creates an asynchronous inflation stream + * @param cb The callback to call whenever data is deflated + */ + function AsyncInflate(cb) { + this.ondata = cb; + astrmify([ + bInflt, + function () { return [astrm, Inflate]; } + ], this, 0, function () { + var strm = new Inflate(); + onmessage = astrm(strm); + }, 7); + } + return AsyncInflate; +}()); +export { AsyncInflate }; +export function inflate(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return cbify(data, opts, [ + bInflt + ], function (ev) { return pbf(inflateSync(ev.data[0], gu8(ev.data[1]))); }, 1, cb); +} +/** + * Expands DEFLATE data with no wrapper + * @param data The data to decompress + * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length. + * @returns The decompressed version of the data + */ +export function inflateSync(data, out) { + return inflt(data, out); +} +// before you yell at me for not just using extends, my reason is that TS inheritance is hard to workerize. +/** + * Streaming GZIP compression + */ +var Gzip = /*#__PURE__*/ (function () { + function Gzip(opts, cb) { + this.c = crc(); + this.l = 0; + this.v = 1; + Deflate.call(this, opts, cb); + } + /** + * Pushes a chunk to be GZIPped + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Gzip.prototype.push = function (chunk, final) { + Deflate.prototype.push.call(this, chunk, final); + }; + Gzip.prototype.p = function (c, f) { + this.c.p(c); + this.l += c.length; + var raw = dopt(c, this.o, this.v && gzhl(this.o), f && 8, !f); + if (this.v) + gzh(raw, this.o), this.v = 0; + if (f) + wbytes(raw, raw.length - 8, this.c.d()), wbytes(raw, raw.length - 4, this.l); + this.ondata(raw, f); + }; + return Gzip; +}()); +export { Gzip }; +/** + * Asynchronous streaming GZIP compression + */ +var AsyncGzip = /*#__PURE__*/ (function () { + function AsyncGzip(opts, cb) { + astrmify([ + bDflt, + gze, + function () { return [astrm, Deflate, Gzip]; } + ], this, AsyncCmpStrm.call(this, opts, cb), function (ev) { + var strm = new Gzip(ev.data); + onmessage = astrm(strm); + }, 8); + } + return AsyncGzip; +}()); +export { AsyncGzip }; +export function gzip(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return cbify(data, opts, [ + bDflt, + gze, + function () { return [gzipSync]; } + ], function (ev) { return pbf(gzipSync(ev.data[0], ev.data[1])); }, 2, cb); +} +/** + * Compresses data with GZIP + * @param data The data to compress + * @param opts The compression options + * @returns The gzipped version of the data + */ +export function gzipSync(data, opts) { + if (!opts) + opts = {}; + var c = crc(), l = data.length; + c.p(data); + var d = dopt(data, opts, gzhl(opts), 8), s = d.length; + return gzh(d, opts), wbytes(d, s - 8, c.d()), wbytes(d, s - 4, l), d; +} +/** + * Streaming GZIP decompression + */ +var Gunzip = /*#__PURE__*/ (function () { + /** + * Creates a GUNZIP stream + * @param cb The callback to call whenever data is inflated + */ + function Gunzip(cb) { + this.v = 1; + Inflate.call(this, cb); + } + /** + * Pushes a chunk to be GUNZIPped + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Gunzip.prototype.push = function (chunk, final) { + Inflate.prototype.e.call(this, chunk); + if (this.v) { + var s = this.p.length > 3 ? gzs(this.p) : 4; + if (s >= this.p.length && !final) + return; + this.p = this.p.subarray(s), this.v = 0; + } + if (final) { + if (this.p.length < 8) + throw 'invalid gzip stream'; + this.p = this.p.subarray(0, -8); + } + // necessary to prevent TS from using the closure value + // This allows for workerization to function correctly + Inflate.prototype.c.call(this, final); + }; + return Gunzip; +}()); +export { Gunzip }; +/** + * Asynchronous streaming GZIP decompression + */ +var AsyncGunzip = /*#__PURE__*/ (function () { + /** + * Creates an asynchronous GUNZIP stream + * @param cb The callback to call whenever data is deflated + */ + function AsyncGunzip(cb) { + this.ondata = cb; + astrmify([ + bInflt, + guze, + function () { return [astrm, Inflate, Gunzip]; } + ], this, 0, function () { + var strm = new Gunzip(); + onmessage = astrm(strm); + }, 9); + } + return AsyncGunzip; +}()); +export { AsyncGunzip }; +export function gunzip(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return cbify(data, opts, [ + bInflt, + guze, + function () { return [gunzipSync]; } + ], function (ev) { return pbf(gunzipSync(ev.data[0])); }, 3, cb); +} +/** + * Expands GZIP data + * @param data The data to decompress + * @param out Where to write the data. GZIP already encodes the output size, so providing this doesn't save memory. + * @returns The decompressed version of the data + */ +export function gunzipSync(data, out) { + return inflt(data.subarray(gzs(data), -8), out || new u8(gzl(data))); +} +/** + * Streaming Zlib compression + */ +var Zlib = /*#__PURE__*/ (function () { + function Zlib(opts, cb) { + this.c = adler(); + this.v = 1; + Deflate.call(this, opts, cb); + } + /** + * Pushes a chunk to be zlibbed + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Zlib.prototype.push = function (chunk, final) { + Deflate.prototype.push.call(this, chunk, final); + }; + Zlib.prototype.p = function (c, f) { + this.c.p(c); + var raw = dopt(c, this.o, this.v && 2, f && 4, !f); + if (this.v) + zlh(raw, this.o), this.v = 0; + if (f) + wbytes(raw, raw.length - 4, this.c.d()); + this.ondata(raw, f); + }; + return Zlib; +}()); +export { Zlib }; +/** + * Asynchronous streaming Zlib compression + */ +var AsyncZlib = /*#__PURE__*/ (function () { + function AsyncZlib(opts, cb) { + astrmify([ + bDflt, + zle, + function () { return [astrm, Deflate, Zlib]; } + ], this, AsyncCmpStrm.call(this, opts, cb), function (ev) { + var strm = new Zlib(ev.data); + onmessage = astrm(strm); + }, 10); + } + return AsyncZlib; +}()); +export { AsyncZlib }; +export function zlib(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return cbify(data, opts, [ + bDflt, + zle, + function () { return [zlibSync]; } + ], function (ev) { return pbf(zlibSync(ev.data[0], ev.data[1])); }, 4, cb); +} +/** + * Compress data with Zlib + * @param data The data to compress + * @param opts The compression options + * @returns The zlib-compressed version of the data + */ +export function zlibSync(data, opts) { + if (!opts) + opts = {}; + var a = adler(); + a.p(data); + var d = dopt(data, opts, 2, 4); + return zlh(d, opts), wbytes(d, d.length - 4, a.d()), d; +} +/** + * Streaming Zlib decompression + */ +var Unzlib = /*#__PURE__*/ (function () { + /** + * Creates a Zlib decompression stream + * @param cb The callback to call whenever data is inflated + */ + function Unzlib(cb) { + this.v = 1; + Inflate.call(this, cb); + } + /** + * Pushes a chunk to be unzlibbed + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Unzlib.prototype.push = function (chunk, final) { + Inflate.prototype.e.call(this, chunk); + if (this.v) { + if (this.p.length < 2 && !final) + return; + this.p = this.p.subarray(2), this.v = 0; + } + if (final) { + if (this.p.length < 4) + throw 'invalid zlib stream'; + this.p = this.p.subarray(0, -4); + } + // necessary to prevent TS from using the closure value + // This allows for workerization to function correctly + Inflate.prototype.c.call(this, final); + }; + return Unzlib; +}()); +export { Unzlib }; +/** + * Asynchronous streaming Zlib decompression + */ +var AsyncUnzlib = /*#__PURE__*/ (function () { + /** + * Creates an asynchronous Zlib decompression stream + * @param cb The callback to call whenever data is deflated + */ + function AsyncUnzlib(cb) { + this.ondata = cb; + astrmify([ + bInflt, + zule, + function () { return [astrm, Inflate, Unzlib]; } + ], this, 0, function () { + var strm = new Unzlib(); + onmessage = astrm(strm); + }, 11); + } + return AsyncUnzlib; +}()); +export { AsyncUnzlib }; +export function unzlib(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return cbify(data, opts, [ + bInflt, + zule, + function () { return [unzlibSync]; } + ], function (ev) { return pbf(unzlibSync(ev.data[0], gu8(ev.data[1]))); }, 5, cb); +} +/** + * Expands Zlib data + * @param data The data to decompress + * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length. + * @returns The decompressed version of the data + */ +export function unzlibSync(data, out) { + return inflt((zlv(data), data.subarray(2, -4)), out); +} +// Default algorithm for compression (used because having a known output size allows faster decompression) +export { gzip as compress, AsyncGzip as AsyncCompress }; +// Default algorithm for compression (used because having a known output size allows faster decompression) +export { gzipSync as compressSync, Gzip as Compress }; +/** + * Streaming GZIP, Zlib, or raw DEFLATE decompression + */ +var Decompress = /*#__PURE__*/ (function () { + /** + * Creates a decompression stream + * @param cb The callback to call whenever data is decompressed + */ + function Decompress(cb) { + this.G = Gunzip; + this.I = Inflate; + this.Z = Unzlib; + this.ondata = cb; + } + /** + * Pushes a chunk to be decompressed + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Decompress.prototype.push = function (chunk, final) { + if (!this.ondata) + throw 'no stream handler'; + if (!this.s) { + if (this.p && this.p.length) { + var n = new u8(this.p.length + chunk.length); + n.set(this.p), n.set(chunk, this.p.length); + } + else + this.p = chunk; + if (this.p.length > 2) { + var _this_1 = this; + var cb = function () { _this_1.ondata.apply(_this_1, arguments); }; + this.s = (this.p[0] == 31 && this.p[1] == 139 && this.p[2] == 8) + ? new this.G(cb) + : ((this.p[0] & 15) != 8 || (this.p[0] >> 4) > 7 || ((this.p[0] << 8 | this.p[1]) % 31)) + ? new this.I(cb) + : new this.Z(cb); + this.s.push(this.p, final); + this.p = null; + } + } + else + this.s.push(chunk, final); + }; + return Decompress; +}()); +export { Decompress }; +/** + * Asynchronous streaming GZIP, Zlib, or raw DEFLATE decompression + */ +var AsyncDecompress = /*#__PURE__*/ (function () { + /** + * Creates an asynchronous decompression stream + * @param cb The callback to call whenever data is decompressed + */ + function AsyncDecompress(cb) { + this.G = AsyncGunzip; + this.I = AsyncInflate; + this.Z = AsyncUnzlib; + this.ondata = cb; + } + /** + * Pushes a chunk to be decompressed + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + AsyncDecompress.prototype.push = function (chunk, final) { + Decompress.prototype.push.call(this, chunk, final); + }; + return AsyncDecompress; +}()); +export { AsyncDecompress }; +export function decompress(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + return (data[0] == 31 && data[1] == 139 && data[2] == 8) + ? gunzip(data, opts, cb) + : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31)) + ? inflate(data, opts, cb) + : unzlib(data, opts, cb); +} +/** + * Expands compressed GZIP, Zlib, or raw DEFLATE data, automatically detecting the format + * @param data The data to decompress + * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length. + * @returns The decompressed version of the data + */ +export function decompressSync(data, out) { + return (data[0] == 31 && data[1] == 139 && data[2] == 8) + ? gunzipSync(data, out) + : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31)) + ? inflateSync(data, out) + : unzlibSync(data, out); +} +// flatten a directory structure +var fltn = function (d, p, t, o) { + for (var k in d) { + var val = d[k], n = p + k; + if (val instanceof u8) + t[n] = [val, o]; + else if (Array.isArray(val)) + t[n] = [val[0], mrg(o, val[1])]; + else + fltn(val, n + '/', t, o); + } +}; +// text encoder +var te = typeof TextEncoder != 'undefined' && /*#__PURE__*/ new TextEncoder(); +// text decoder +var td = typeof TextDecoder != 'undefined' && /*#__PURE__*/ new TextDecoder(); +// text decoder stream +var tds = 0; +try { + td.decode(et, { stream: true }); + tds = 1; +} +catch (e) { } +// decode UTF8 +var dutf8 = function (d) { + for (var r = '', i = 0;;) { + var c = d[i++]; + var eb = (c > 127) + (c > 223) + (c > 239); + if (i + eb > d.length) + return [r, slc(d, i - 1)]; + if (!eb) + r += String.fromCharCode(c); + else if (eb == 3) { + c = ((c & 15) << 18 | (d[i++] & 63) << 12 | (d[i++] & 63) << 6 | (d[i++] & 63)) - 65536, + r += String.fromCharCode(55296 | (c >> 10), 56320 | (c & 1023)); + } + else if (eb & 1) + r += String.fromCharCode((c & 31) << 6 | (d[i++] & 63)); + else + r += String.fromCharCode((c & 15) << 12 | (d[i++] & 63) << 6 | (d[i++] & 63)); + } +}; +/** + * Streaming UTF-8 decoding + */ +var DecodeUTF8 = /*#__PURE__*/ (function () { + /** + * Creates a UTF-8 decoding stream + * @param cb The callback to call whenever data is decoded + */ + function DecodeUTF8(cb) { + this.ondata = cb; + if (tds) + this.t = new TextDecoder(); + else + this.p = et; + } + /** + * Pushes a chunk to be decoded from UTF-8 binary + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + DecodeUTF8.prototype.push = function (chunk, final) { + if (!this.ondata) + throw 'no callback'; + final = !!final; + if (this.t) { + this.ondata(this.t.decode(chunk, { stream: true }), final); + if (final) { + if (this.t.decode().length) + throw 'invalid utf-8 data'; + this.t = null; + } + return; + } + if (!this.p) + throw 'stream finished'; + var dat = new u8(this.p.length + chunk.length); + dat.set(this.p); + dat.set(chunk, this.p.length); + var _a = dutf8(dat), ch = _a[0], np = _a[1]; + if (final) { + if (np.length) + throw 'invalid utf-8 data'; + this.p = null; + } + else + this.p = np; + this.ondata(ch, final); + }; + return DecodeUTF8; +}()); +export { DecodeUTF8 }; +/** + * Streaming UTF-8 encoding + */ +var EncodeUTF8 = /*#__PURE__*/ (function () { + /** + * Creates a UTF-8 decoding stream + * @param cb The callback to call whenever data is encoded + */ + function EncodeUTF8(cb) { + this.ondata = cb; + } + /** + * Pushes a chunk to be encoded to UTF-8 + * @param chunk The string data to push + * @param final Whether this is the last chunk + */ + EncodeUTF8.prototype.push = function (chunk, final) { + if (!this.ondata) + throw 'no callback'; + if (this.d) + throw 'stream finished'; + this.ondata(strToU8(chunk), this.d = final || false); + }; + return EncodeUTF8; +}()); +export { EncodeUTF8 }; +/** + * Converts a string into a Uint8Array for use with compression/decompression methods + * @param str The string to encode + * @param latin1 Whether or not to interpret the data as Latin-1. This should + * not need to be true unless decoding a binary string. + * @returns The string encoded in UTF-8/Latin-1 binary + */ +export function strToU8(str, latin1) { + if (latin1) { + var ar_1 = new u8(str.length); + for (var i = 0; i < str.length; ++i) + ar_1[i] = str.charCodeAt(i); + return ar_1; + } + if (te) + return te.encode(str); + var l = str.length; + var ar = new u8(str.length + (str.length >> 1)); + var ai = 0; + var w = function (v) { ar[ai++] = v; }; + for (var i = 0; i < l; ++i) { + if (ai + 5 > ar.length) { + var n = new u8(ai + 8 + ((l - i) << 1)); + n.set(ar); + ar = n; + } + var c = str.charCodeAt(i); + if (c < 128 || latin1) + w(c); + else if (c < 2048) + w(192 | (c >> 6)), w(128 | (c & 63)); + else if (c > 55295 && c < 57344) + c = 65536 + (c & 1023 << 10) | (str.charCodeAt(++i) & 1023), + w(240 | (c >> 18)), w(128 | ((c >> 12) & 63)), w(128 | ((c >> 6) & 63)), w(128 | (c & 63)); + else + w(224 | (c >> 12)), w(128 | ((c >> 6) & 63)), w(128 | (c & 63)); + } + return slc(ar, 0, ai); +} +/** + * Converts a Uint8Array to a string + * @param dat The data to decode to string + * @param latin1 Whether or not to interpret the data as Latin-1. This should + * not need to be true unless encoding to binary string. + * @returns The original UTF-8/Latin-1 string + */ +export function strFromU8(dat, latin1) { + if (latin1) { + var r = ''; + for (var i = 0; i < dat.length; i += 16384) + r += String.fromCharCode.apply(null, dat.subarray(i, i + 16384)); + return r; + } + else if (td) + return td.decode(dat); + else { + var _a = dutf8(dat), out = _a[0], ext = _a[1]; + if (ext.length) + throw 'invalid utf-8 data'; + return out; + } +} +; +// deflate bit flag +var dbf = function (l) { return l == 1 ? 3 : l < 6 ? 2 : l == 9 ? 1 : 0; }; +// skip local zip header +var slzh = function (d, b) { return b + 30 + b2(d, b + 26) + b2(d, b + 28); }; +// read zip header +var zh = function (d, b, z) { + var fnl = b2(d, b + 28), fn = strFromU8(d.subarray(b + 46, b + 46 + fnl), !(b2(d, b + 8) & 2048)), es = b + 46 + fnl, bs = b4(d, b + 20); + var _a = z && bs == 4294967295 ? z64e(d, es) : [bs, b4(d, b + 24), b4(d, b + 42)], sc = _a[0], su = _a[1], off = _a[2]; + return [b2(d, b + 10), sc, su, fn, es + b2(d, b + 30) + b2(d, b + 32), off]; +}; +// read zip64 extra field +var z64e = function (d, b) { + for (; b2(d, b) != 1; b += 4 + b2(d, b + 2)) + ; + return [b8(d, b + 12), b8(d, b + 4), b8(d, b + 20)]; +}; +// extra field length +var exfl = function (ex) { + var le = 0; + if (ex) { + for (var k in ex) { + var l = ex[k].length; + if (l > 65535) + throw 'extra field too long'; + le += l + 4; + } + } + return le; +}; +// write zip header +var wzh = function (d, b, f, fn, u, c, ce, co) { + var fl = fn.length, ex = f.extra, col = co && co.length; + var exl = exfl(ex); + wbytes(d, b, ce != null ? 0x2014B50 : 0x4034B50), b += 4; + if (ce != null) + d[b++] = 20, d[b++] = f.os; + d[b] = 20, b += 2; // spec compliance? what's that? + d[b++] = (f.flag << 1) | (c == null && 8), d[b++] = u && 8; + d[b++] = f.compression & 255, d[b++] = f.compression >> 8; + var dt = new Date(f.mtime == null ? Date.now() : f.mtime), y = dt.getFullYear() - 1980; + if (y < 0 || y > 119) + throw 'date not in range 1980-2099'; + wbytes(d, b, (y << 25) | ((dt.getMonth() + 1) << 21) | (dt.getDate() << 16) | (dt.getHours() << 11) | (dt.getMinutes() << 5) | (dt.getSeconds() >>> 1)), b += 4; + if (c != null) { + wbytes(d, b, f.crc); + wbytes(d, b + 4, c); + wbytes(d, b + 8, f.size); + } + wbytes(d, b + 12, fl); + wbytes(d, b + 14, exl), b += 16; + if (ce != null) { + wbytes(d, b, col); + wbytes(d, b + 6, f.attrs); + wbytes(d, b + 10, ce), b += 14; + } + d.set(fn, b); + b += fl; + if (exl) { + for (var k in ex) { + var exf = ex[k], l = exf.length; + wbytes(d, b, +k); + wbytes(d, b + 2, l); + d.set(exf, b + 4), b += 4 + l; + } + } + if (col) + d.set(co, b), b += col; + return b; +}; +// write zip footer (end of central directory) +var wzf = function (o, b, c, d, e) { + wbytes(o, b, 0x6054B50); // skip disk + wbytes(o, b + 8, c); + wbytes(o, b + 10, c); + wbytes(o, b + 12, d); + wbytes(o, b + 16, e); +}; +/** + * A pass-through stream to keep data uncompressed in a ZIP archive. + */ +var ZipPassThrough = /*#__PURE__*/ (function () { + /** + * Creates a pass-through stream that can be added to ZIP archives + * @param filename The filename to associate with this data stream + */ + function ZipPassThrough(filename) { + this.filename = filename; + this.c = crc(); + this.size = 0; + this.compression = 0; + } + /** + * Processes a chunk and pushes to the output stream. You can override this + * method in a subclass for custom behavior, but by default this passes + * the data through. You must call this.ondata(err, chunk, final) at some + * point in this method. + * @param chunk The chunk to process + * @param final Whether this is the last chunk + */ + ZipPassThrough.prototype.process = function (chunk, final) { + this.ondata(null, chunk, final); + }; + /** + * Pushes a chunk to be added. If you are subclassing this with a custom + * compression algorithm, note that you must push data from the source + * file only, pre-compression. + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + ZipPassThrough.prototype.push = function (chunk, final) { + if (!this.ondata) + throw 'no callback - add to ZIP archive before pushing'; + this.c.p(chunk); + this.size += chunk.length; + if (final) + this.crc = this.c.d(); + this.process(chunk, final || false); + }; + return ZipPassThrough; +}()); +export { ZipPassThrough }; +// I don't extend because TypeScript extension adds 1kB of runtime bloat +/** + * Streaming DEFLATE compression for ZIP archives. Prefer using AsyncZipDeflate + * for better performance + */ +var ZipDeflate = /*#__PURE__*/ (function () { + /** + * Creates a DEFLATE stream that can be added to ZIP archives + * @param filename The filename to associate with this data stream + * @param opts The compression options + */ + function ZipDeflate(filename, opts) { + var _this_1 = this; + if (!opts) + opts = {}; + ZipPassThrough.call(this, filename); + this.d = new Deflate(opts, function (dat, final) { + _this_1.ondata(null, dat, final); + }); + this.compression = 8; + this.flag = dbf(opts.level); + } + ZipDeflate.prototype.process = function (chunk, final) { + try { + this.d.push(chunk, final); + } + catch (e) { + this.ondata(e, null, final); + } + }; + /** + * Pushes a chunk to be deflated + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + ZipDeflate.prototype.push = function (chunk, final) { + ZipPassThrough.prototype.push.call(this, chunk, final); + }; + return ZipDeflate; +}()); +export { ZipDeflate }; +/** + * Asynchronous streaming DEFLATE compression for ZIP archives + */ +var AsyncZipDeflate = /*#__PURE__*/ (function () { + /** + * Creates a DEFLATE stream that can be added to ZIP archives + * @param filename The filename to associate with this data stream + * @param opts The compression options + */ + function AsyncZipDeflate(filename, opts) { + var _this_1 = this; + if (!opts) + opts = {}; + ZipPassThrough.call(this, filename); + this.d = new AsyncDeflate(opts, function (err, dat, final) { + _this_1.ondata(err, dat, final); + }); + this.compression = 8; + this.flag = dbf(opts.level); + this.terminate = this.d.terminate; + } + AsyncZipDeflate.prototype.process = function (chunk, final) { + this.d.push(chunk, final); + }; + /** + * Pushes a chunk to be deflated + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + AsyncZipDeflate.prototype.push = function (chunk, final) { + ZipPassThrough.prototype.push.call(this, chunk, final); + }; + return AsyncZipDeflate; +}()); +export { AsyncZipDeflate }; +// TODO: Better tree shaking +/** + * A zippable archive to which files can incrementally be added + */ +var Zip = /*#__PURE__*/ (function () { + /** + * Creates an empty ZIP archive to which files can be added + * @param cb The callback to call whenever data for the generated ZIP archive + * is available + */ + function Zip(cb) { + this.ondata = cb; + this.u = []; + this.d = 1; + } + /** + * Adds a file to the ZIP archive + * @param file The file stream to add + */ + Zip.prototype.add = function (file) { + var _this_1 = this; + if (this.d & 2) + throw 'stream finished'; + var f = strToU8(file.filename), fl = f.length; + var com = file.comment, o = com && strToU8(com); + var u = fl != file.filename.length || (o && (com.length != o.length)); + var hl = fl + exfl(file.extra) + 30; + if (fl > 65535) + throw 'filename too long'; + var header = new u8(hl); + wzh(header, 0, file, f, u); + var chks = [header]; + var pAll = function () { + for (var _i = 0, chks_1 = chks; _i < chks_1.length; _i++) { + var chk = chks_1[_i]; + _this_1.ondata(null, chk, false); + } + chks = []; + }; + var tr = this.d; + this.d = 0; + var ind = this.u.length; + var uf = mrg(file, { + f: f, + u: u, + o: o, + t: function () { + if (file.terminate) + file.terminate(); + }, + r: function () { + pAll(); + if (tr) { + var nxt = _this_1.u[ind + 1]; + if (nxt) + nxt.r(); + else + _this_1.d = 1; + } + tr = 1; + } + }); + var cl = 0; + file.ondata = function (err, dat, final) { + if (err) { + _this_1.ondata(err, dat, final); + _this_1.terminate(); + } + else { + cl += dat.length; + chks.push(dat); + if (final) { + var dd = new u8(16); + wbytes(dd, 0, 0x8074B50); + wbytes(dd, 4, file.crc); + wbytes(dd, 8, cl); + wbytes(dd, 12, file.size); + chks.push(dd); + uf.c = cl, uf.b = hl + cl + 16, uf.crc = file.crc, uf.size = file.size; + if (tr) + uf.r(); + tr = 1; + } + else if (tr) + pAll(); + } + }; + this.u.push(uf); + }; + /** + * Ends the process of adding files and prepares to emit the final chunks. + * This *must* be called after adding all desired files for the resulting + * ZIP file to work properly. + */ + Zip.prototype.end = function () { + var _this_1 = this; + if (this.d & 2) { + if (this.d & 1) + throw 'stream finishing'; + throw 'stream finished'; + } + if (this.d) + this.e(); + else + this.u.push({ + r: function () { + if (!(_this_1.d & 1)) + return; + _this_1.u.splice(-1, 1); + _this_1.e(); + }, + t: function () { } + }); + this.d = 3; + }; + Zip.prototype.e = function () { + var bt = 0, l = 0, tl = 0; + for (var _i = 0, _a = this.u; _i < _a.length; _i++) { + var f = _a[_i]; + tl += 46 + f.f.length + exfl(f.extra) + (f.o ? f.o.length : 0); + } + var out = new u8(tl + 22); + for (var _b = 0, _c = this.u; _b < _c.length; _b++) { + var f = _c[_b]; + wzh(out, bt, f, f.f, f.u, f.c, l, f.o); + bt += 46 + f.f.length + exfl(f.extra) + (f.o ? f.o.length : 0), l += f.b; + } + wzf(out, bt, this.u.length, tl, l); + this.ondata(null, out, true); + this.d = 2; + }; + /** + * A method to terminate any internal workers used by the stream. Subsequent + * calls to add() will fail. + */ + Zip.prototype.terminate = function () { + for (var _i = 0, _a = this.u; _i < _a.length; _i++) { + var f = _a[_i]; + f.t(); + } + this.d = 2; + }; + return Zip; +}()); +export { Zip }; +export function zip(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; + if (typeof cb != 'function') + throw 'no callback'; + var r = {}; + fltn(data, '', r, opts); + var k = Object.keys(r); + var lft = k.length, o = 0, tot = 0; + var slft = lft, files = new Array(lft); + var term = []; + var tAll = function () { + for (var i = 0; i < term.length; ++i) + term[i](); + }; + var cbf = function () { + var out = new u8(tot + 22), oe = o, cdl = tot - o; + tot = 0; + for (var i = 0; i < slft; ++i) { + var f = files[i]; + try { + var l = f.c.length; + wzh(out, tot, f, f.f, f.u, l); + var badd = 30 + f.f.length + exfl(f.extra); + var loc = tot + badd; + out.set(f.c, loc); + wzh(out, o, f, f.f, f.u, l, tot, f.m), o += 16 + badd + (f.m ? f.m.length : 0), tot = loc + l; + } + catch (e) { + return cb(e, null); + } + } + wzf(out, o, files.length, cdl, oe); + cb(null, out); + }; + if (!lft) + cbf(); + var _loop_1 = function (i) { + var fn = k[i]; + var _a = r[fn], file = _a[0], p = _a[1]; + var c = crc(), size = file.length; + c.p(file); + var f = strToU8(fn), s = f.length; + var com = p.comment, m = com && strToU8(com), ms = m && m.length; + var exl = exfl(p.extra); + var compression = p.level == 0 ? 0 : 8; + var cbl = function (e, d) { + if (e) { + tAll(); + cb(e, null); + } + else { + var l = d.length; + files[i] = mrg(p, { + size: size, + crc: c.d(), + c: d, + f: f, + m: m, + u: s != fn.length || (m && (com.length != ms)), + compression: compression + }); + o += 30 + s + exl + l; + tot += 76 + 2 * (s + exl) + (ms || 0) + l; + if (!--lft) + cbf(); + } + }; + if (s > 65535) + cbl('filename too long', null); + if (!compression) + cbl(null, file); + else if (size < 160000) { + try { + cbl(null, deflateSync(file, p)); + } + catch (e) { + cbl(e, null); + } + } + else + term.push(deflate(file, p, cbl)); + }; + // Cannot use lft because it can decrease + for (var i = 0; i < slft; ++i) { + _loop_1(i); + } + return tAll; +} +/** + * Synchronously creates a ZIP file. Prefer using `zip` for better performance + * with more than one file. + * @param data The directory structure for the ZIP archive + * @param opts The main options, merged with per-file options + * @returns The generated ZIP archive + */ +export function zipSync(data, opts) { + if (!opts) + opts = {}; + var r = {}; + var files = []; + fltn(data, '', r, opts); + var o = 0; + var tot = 0; + for (var fn in r) { + var _a = r[fn], file = _a[0], p = _a[1]; + var compression = p.level == 0 ? 0 : 8; + var f = strToU8(fn), s = f.length; + var com = p.comment, m = com && strToU8(com), ms = m && m.length; + var exl = exfl(p.extra); + if (s > 65535) + throw 'filename too long'; + var d = compression ? deflateSync(file, p) : file, l = d.length; + var c = crc(); + c.p(file); + files.push(mrg(p, { + size: file.length, + crc: c.d(), + c: d, + f: f, + m: m, + u: s != fn.length || (m && (com.length != ms)), + o: o, + compression: compression + })); + o += 30 + s + exl + l; + tot += 76 + 2 * (s + exl) + (ms || 0) + l; + } + var out = new u8(tot + 22), oe = o, cdl = tot - o; + for (var i = 0; i < files.length; ++i) { + var f = files[i]; + wzh(out, f.o, f, f.f, f.u, f.c.length); + var badd = 30 + f.f.length + exfl(f.extra); + out.set(f.c, f.o + badd); + wzh(out, o, f, f.f, f.u, f.c.length, f.o, f.m), o += 16 + badd + (f.m ? f.m.length : 0); + } + wzf(out, o, files.length, cdl, oe); + return out; +} +/** + * Streaming pass-through decompression for ZIP archives + */ +var UnzipPassThrough = /*#__PURE__*/ (function () { + function UnzipPassThrough() { + } + UnzipPassThrough.prototype.push = function (data, final) { + this.ondata(null, data, final); + }; + UnzipPassThrough.compression = 0; + return UnzipPassThrough; +}()); +export { UnzipPassThrough }; +/** + * Streaming DEFLATE decompression for ZIP archives. Prefer AsyncZipInflate for + * better performance. + */ +var UnzipInflate = /*#__PURE__*/ (function () { + /** + * Creates a DEFLATE decompression that can be used in ZIP archives + */ + function UnzipInflate() { + var _this_1 = this; + this.i = new Inflate(function (dat, final) { + _this_1.ondata(null, dat, final); + }); + } + UnzipInflate.prototype.push = function (data, final) { + try { + this.i.push(data, final); + } + catch (e) { + this.ondata(e, data, final); + } + }; + UnzipInflate.compression = 8; + return UnzipInflate; +}()); +export { UnzipInflate }; +/** + * Asynchronous streaming DEFLATE decompression for ZIP archives + */ +var AsyncUnzipInflate = /*#__PURE__*/ (function () { + /** + * Creates a DEFLATE decompression that can be used in ZIP archives + */ + function AsyncUnzipInflate(_, sz) { + var _this_1 = this; + if (sz < 320000) { + this.i = new Inflate(function (dat, final) { + _this_1.ondata(null, dat, final); + }); + } + else { + this.i = new AsyncInflate(function (err, dat, final) { + _this_1.ondata(err, dat, final); + }); + this.terminate = this.i.terminate; + } + } + AsyncUnzipInflate.prototype.push = function (data, final) { + if (this.i.terminate) + data = slc(data, 0); + this.i.push(data, final); + }; + AsyncUnzipInflate.compression = 8; + return AsyncUnzipInflate; +}()); +export { AsyncUnzipInflate }; +/** + * A ZIP archive decompression stream that emits files as they are discovered + */ +var Unzip = /*#__PURE__*/ (function () { + /** + * Creates a ZIP decompression stream + * @param cb The callback to call whenever a file in the ZIP archive is found + */ + function Unzip(cb) { + this.onfile = cb; + this.k = []; + this.o = { + 0: UnzipPassThrough + }; + this.p = et; + } + /** + * Pushes a chunk to be unzipped + * @param chunk The chunk to push + * @param final Whether this is the last chunk + */ + Unzip.prototype.push = function (chunk, final) { + var _this_1 = this; + if (!this.onfile) + throw 'no callback'; + if (!this.p) + throw 'stream finished'; + if (this.c > 0) { + var len = Math.min(this.c, chunk.length); + var toAdd = chunk.subarray(0, len); + this.c -= len; + if (this.d) + this.d.push(toAdd, !this.c); + else + this.k[0].push(toAdd); + chunk = chunk.subarray(len); + if (chunk.length) + return this.push(chunk, final); + } + else { + var f = 0, i = 0, is = void 0, buf = void 0; + if (!this.p.length) + buf = chunk; + else if (!chunk.length) + buf = this.p; + else { + buf = new u8(this.p.length + chunk.length); + buf.set(this.p), buf.set(chunk, this.p.length); + } + var l = buf.length, oc = this.c, add = oc && this.d; + var _loop_2 = function () { + var _a; + var sig = b4(buf, i); + if (sig == 0x4034B50) { + f = 1, is = i; + this_1.d = null; + this_1.c = 0; + var bf = b2(buf, i + 6), cmp_1 = b2(buf, i + 8), u = bf & 2048, dd = bf & 8, fnl = b2(buf, i + 26), es = b2(buf, i + 28); + if (l > i + 30 + fnl + es) { + var chks_2 = []; + this_1.k.unshift(chks_2); + f = 2; + var sc_1 = b4(buf, i + 18), su_1 = b4(buf, i + 22); + var fn_1 = strFromU8(buf.subarray(i + 30, i += 30 + fnl), !u); + if (sc_1 == 4294967295) { + _a = dd ? [-2] : z64e(buf, i), sc_1 = _a[0], su_1 = _a[1]; + } + else if (dd) + sc_1 = -1; + i += es; + this_1.c = sc_1; + var d_1; + var file_1 = { + name: fn_1, + compression: cmp_1, + start: function () { + if (!file_1.ondata) + throw 'no callback'; + if (!sc_1) + file_1.ondata(null, et, true); + else { + var ctr = _this_1.o[cmp_1]; + if (!ctr) + throw 'unknown compression type ' + cmp_1; + d_1 = sc_1 < 0 ? new ctr(fn_1) : new ctr(fn_1, sc_1, su_1); + d_1.ondata = function (err, dat, final) { file_1.ondata(err, dat, final); }; + for (var _i = 0, chks_3 = chks_2; _i < chks_3.length; _i++) { + var dat = chks_3[_i]; + d_1.push(dat, false); + } + if (_this_1.k[0] == chks_2 && _this_1.c) + _this_1.d = d_1; + else + d_1.push(et, true); + } + }, + terminate: function () { + if (d_1 && d_1.terminate) + d_1.terminate(); + } + }; + if (sc_1 >= 0) + file_1.size = sc_1, file_1.originalSize = su_1; + this_1.onfile(file_1); + } + return "break"; + } + else if (oc) { + if (sig == 0x8074B50) { + is = i += 12 + (oc == -2 && 8), f = 3, this_1.c = 0; + return "break"; + } + else if (sig == 0x2014B50) { + is = i -= 4, f = 3, this_1.c = 0; + return "break"; + } + } + }; + var this_1 = this; + for (; i < l - 4; ++i) { + var state_1 = _loop_2(); + if (state_1 === "break") + break; + } + this.p = et; + if (oc < 0) { + var dat = f ? buf.subarray(0, is - 12 - (oc == -2 && 8) - (b4(buf, is - 16) == 0x8074B50 && 4)) : buf.subarray(0, i); + if (add) + add.push(dat, !!f); + else + this.k[+(f == 2)].push(dat); + } + if (f & 2) + return this.push(buf.subarray(i), final); + this.p = buf.subarray(i); + } + if (final) { + if (this.c) + throw 'invalid zip file'; + this.p = null; + } + }; + /** + * Registers a decoder with the stream, allowing for files compressed with + * the compression type provided to be expanded correctly + * @param decoder The decoder constructor + */ + Unzip.prototype.register = function (decoder) { + this.o[decoder.compression] = decoder; + }; + return Unzip; +}()); +export { Unzip }; +/** + * Asynchronously decompresses a ZIP archive + * @param data The raw compressed ZIP file + * @param cb The callback to call with the decompressed files + * @returns A function that can be used to immediately terminate the unzipping + */ +export function unzip(data, cb) { + if (typeof cb != 'function') + throw 'no callback'; + var term = []; + var tAll = function () { + for (var i = 0; i < term.length; ++i) + term[i](); + }; + var files = {}; + var e = data.length - 22; + for (; b4(data, e) != 0x6054B50; --e) { + if (!e || data.length - e > 65558) { + cb('invalid zip file', null); + return; + } + } + ; + var lft = b2(data, e + 8); + if (!lft) + cb(null, {}); + var c = lft; + var o = b4(data, e + 16); + var z = o == 4294967295; + if (z) { + e = b4(data, e - 12); + if (b4(data, e) != 0x6064B50) { + cb('invalid zip file', null); + return; + } + c = lft = b4(data, e + 32); + o = b4(data, e + 48); + } + var _loop_3 = function (i) { + var _a = zh(data, o, z), c_1 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off); + o = no; + var cbl = function (e, d) { + if (e) { + tAll(); + cb(e, null); + } + else { + files[fn] = d; + if (!--lft) + cb(null, files); + } + }; + if (!c_1) + cbl(null, slc(data, b, b + sc)); + else if (c_1 == 8) { + var infl = data.subarray(b, b + sc); + if (sc < 320000) { + try { + cbl(null, inflateSync(infl, new u8(su))); + } + catch (e) { + cbl(e, null); + } + } + else + term.push(inflate(infl, { size: su }, cbl)); + } + else + cbl('unknown compression type ' + c_1, null); + }; + for (var i = 0; i < c; ++i) { + _loop_3(i); + } + return tAll; +} +/** + * Synchronously decompresses a ZIP archive. Prefer using `unzip` for better + * performance with more than one file. + * @param data The raw compressed ZIP file + * @returns The decompressed files + */ +export function unzipSync(data) { + var files = {}; + var e = data.length - 22; + for (; b4(data, e) != 0x6054B50; --e) { + if (!e || data.length - e > 65558) + throw 'invalid zip file'; + } + ; + var c = b2(data, e + 8); + if (!c) + return {}; + var o = b4(data, e + 16); + var z = o == 4294967295; + if (z) { + e = b4(data, e - 12); + if (b4(data, e) != 0x6064B50) + throw 'invalid zip file'; + c = b4(data, e + 32); + o = b4(data, e + 48); + } + for (var i = 0; i < c; ++i) { + var _a = zh(data, o, z), c_2 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off); + o = no; + if (!c_2) + files[fn] = slc(data, b, b + sc); + else if (c_2 == 8) + files[fn] = inflateSync(data.subarray(b, b + sc), new u8(su)); + else + throw 'unknown compression type ' + c_2; + } + return files; +} diff --git a/examples/jsm/libs/fflate.module.min.js b/examples/jsm/libs/fflate.module.min.js deleted file mode 100644 index 48a17c2448c25d..00000000000000 --- a/examples/jsm/libs/fflate.module.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! -fflate - fast JavaScript compression/decompression - -Licensed under MIT. https://github.com/101arrowz/fflate/blob/master/LICENSE -*/ -var gn={},bn=function(n,r,t,e,i){var a=gn[r]||(gn[r]=URL.createObjectURL(new Blob([n],{type:"text/javascript"}))),o=new Worker(a);return o.onerror=function(f){return i(f.error,null)},o.onmessage=function(f){return i(null,f.data)},o.postMessage(t,e),o},A=Uint8Array,R=Uint16Array,nr=Uint32Array,ur=new A([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),lr=new A([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Mr=new A([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),wn=function(n,r){for(var t=new R(31),e=0;e<31;++e)t[e]=r+=1<>>1|(T&21845)<<1;ir=(ir&52428)>>>2|(ir&13107)<<2,ir=(ir&61680)>>>4|(ir&3855)<<4,Ur[T]=((ir&65280)>>>8|(ir&255)<<8)>>>1}for(var V=function(n,r,t){for(var e=n.length,i=0,a=new R(r);i>>h]=s}else for(f=new R(e),i=0;i>>15-n[i]);return f},tr=new A(288),T=0;T<144;++T)tr[T]=8;for(var T=144;T<256;++T)tr[T]=9;for(var T=256;T<280;++T)tr[T]=7;for(var T=280;T<288;++T)tr[T]=8;for(var vr=new A(32),T=0;T<32;++T)vr[T]=5;var xn=V(tr,9,0),An=V(tr,9,1),Dn=V(vr,5,0),Mn=V(vr,5,1),Gr=function(n){for(var r=n[0],t=1;tr&&(r=n[t]);return r},X=function(n,r,t){var e=r/8|0;return(n[e]|n[e+1]<<8)>>(r&7)&t},Or=function(n,r){var t=r/8|0;return(n[t]|n[t+1]<<8|n[t+2]<<16)>>(r&7)},Cr=function(n){return(n/8|0)+(n&7&&1)},$=function(n,r,t){(r==null||r<0)&&(r=0),(t==null||t>n.length)&&(t=n.length);var e=new(n instanceof R?R:n instanceof nr?nr:A)(t-r);return e.set(n.subarray(r,t)),e},Fr=function(n,r,t){var e=n.length;if(!e||t&&!t.l&&e<5)return r||new A(0);var i=!r||t,a=!t||t.i;t||(t={}),r||(r=new A(e*3));var o=function(Tr){var Dr=r.length;if(Tr>Dr){var hr=new A(Math.max(Dr*2,Tr));hr.set(r),r=hr}},f=t.f||0,h=t.p||0,s=t.b||0,u=t.l,l=t.d,p=t.m,y=t.n,c=e*8;do{if(!u){t.f=f=X(n,h,1);var g=X(n,h+1,3);if(h+=3,g)if(g==1)u=An,l=Mn,p=9,y=5;else if(g==2){var m=X(n,h,31)+257,D=X(n,h+10,15)+4,C=m+X(n,h+5,31)+1;h+=14;for(var U=new A(C),x=new A(19),v=0;vc)break;for(var K=V(x,E,1),v=0;v>>4;if(w<16)U[v++]=w;else{var Z=0,B=0;for(w==16?(B=3+X(n,h,3),h+=2,Z=U[v-1]):w==17?(B=3+X(n,h,7),h+=3):w==18&&(B=11+X(n,h,127),h+=7);B--;)U[v++]=Z}}var G=U.subarray(0,m),k=U.subarray(m);p=Gr(G),y=Gr(k),u=V(G,p,1),l=V(k,y,1)}else throw"invalid block type";else{var w=Cr(h)+4,M=n[w-4]|n[w-3]<<8,z=w+M;if(z>e){if(a)throw"unexpected EOF";break}i&&o(s+M),r.set(n.subarray(w,z),s),t.b=s+=M,t.p=h=z*8;continue}if(h>c)throw"unexpected EOF"}i&&o(s+131072);for(var O=(1<>>4;if(h+=Z&15,h>c)throw"unexpected EOF";if(!Z)throw"invalid length/literal";if(Q<256)r[s++]=Q;else if(Q==256){u=null;break}else{var W=Q-254;if(Q>264){var v=Q-257,d=ur[v];W=X(n,h,(1<>>4;if(!_)throw"invalid distance";h+=_&15;var k=zn[j];if(j>3){var d=lr[j];k+=Or(n,h)&(1<c)throw"unexpected EOF";i&&o(s+131072);for(var q=s+W;s>>8},cr=function(n,r,t){t<<=r&7;var e=r/8|0;n[e]|=t,n[e+1]|=t>>>8,n[e+2]|=t>>>16},Er=function(n,r){for(var t=[],e=0;ep&&(p=a[e].s);var y=new R(p+1),c=Pr(t[u-1],y,0);if(c>r){var e=0,g=0,w=c-r,M=1<r)g+=M-(1<>>=w;g>0;){var m=a[e].s;y[m]=0&&g;--e){var D=a[e].s;y[D]==r&&(--y[D],++g)}c=r}return[new A(y),c]},Pr=function(n,r,t){return n.s==-1?Math.max(Pr(n.l,r,t+1),Pr(n.r,r,t+1)):r[n.s]=t},Vr=function(n){for(var r=n.length;r&&!n[--r];);for(var t=new R(++r),e=0,i=n[0],a=1,o=function(h){t[e++]=h},f=1;f<=r;++f)if(n[f]==i&&f!=r)++a;else{if(!i&&a>2){for(;a>138;a-=138)o(32754);a>2&&(o(a>10?a-11<<5|28690:a-3<<5|12305),a=0)}else if(a>3){for(o(i),--a;a>6;a-=6)o(8304);a>2&&(o(a-3<<5|8208),a=0)}for(;a--;)o(i);a=1,i=n[f]}return[t.subarray(0,e),r]},pr=function(n,r){for(var t=0,e=0;e>>8,n[i+2]=n[i]^255,n[i+3]=n[i+1]^255;for(var a=0;a4&&!S[Mr[I-1]];--I);var Z=s+5<<3,B=pr(i,tr)+pr(a,vr)+o,G=pr(i,p)+pr(a,g)+o+14+3*I+pr(x,S)+(2*x[16]+3*x[17]+7*x[18]);if(Z<=B&&Z<=G)return Sr(r,u,n.subarray(h,h+s));var k,O,H,N;if(b(r,u,1+(G15&&(b(r,u,_[v]>>>5&127),u+=_[v]>>>12)}}else k=xn,O=tr,H=Dn,N=vr;for(var v=0;v255){var j=e[v]>>>18&31;cr(r,u,k[j+257]),u+=O[j+257],j>7&&(b(r,u,e[v]>>>23&31),u+=ur[j]);var q=e[v]&31;cr(r,u,H[q]),u+=N[q],q>3&&(cr(r,u,e[v]>>>5&8191),u+=lr[q])}else cr(r,u,k[e[v]]),u+=O[e[v]];return cr(r,u,k[256]),u+O[256]},Un=new nr([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),er=new A(0),Cn=function(n,r,t,e,i,a){var o=n.length,f=new A(e+o+5*(1+Math.ceil(o/7e3))+i),h=f.subarray(e,f.length-i),s=0;if(!r||o<8)for(var u=0;u<=o;u+=65535){var l=u+65535;l>>13,c=p&8191,g=(1<7e3||S>24576)&&k>423){s=Xr(n,h,0,C,U,x,E,S,I,u-I,s),S=v=E=0,I=u;for(var O=0;O<286;++O)U[O]=0;for(var O=0;O<30;++O)x[O]=0}var H=2,N=0,Q=c,W=B-G&32767;if(k>2&&Z==D(u-W))for(var d=Math.min(y,k)-1,_=Math.min(32767,u),j=Math.min(258,k);W<=_&&--Q&&B!=G;){if(n[u+H]==n[u+H-W]){for(var q=0;qH){if(H=q,N=W,q>d)break;for(var Tr=Math.min(W,q-2),Dr=0,O=0;ODr&&(Dr=vn,G=hr)}}}B=G,G=w[B],W+=B-G+32768&32767}if(N){C[S++]=268435456|Ir[H]<<18|Qr[N];var cn=Ir[H]&31,pn=Qr[N]&31;E+=ur[cn]+lr[pn],++U[257+cn],++x[pn],K=u+H,++v}else C[S++]=n[u],++U[n[u]]}}s=Xr(n,h,a,C,U,x,E,S,I,u-I,s),!a&&s&7&&(s=Sr(h,s+1,er))}return $(f,0,e+Cr(s)+i)},Fn=function(){for(var n=new nr(256),r=0;r<256;++r){for(var t=r,e=9;--e;)t=(t&1&&3988292384)^t>>>1;n[r]=t}return n}(),gr=function(){var n=-1;return{p:function(r){for(var t=n,e=0;e>>8;n=t},d:function(){return~n}}},$r=function(){var n=1,r=0;return{p:function(t){for(var e=n,i=r,a=t.length,o=0;o!=a;){for(var f=Math.min(o+2655,a);o>16),i=(i&65535)+15*(i>>16)}n=e,r=i},d:function(){return n%=65521,r%=65521,(n>>>8<<16|(r&255)<<8|r>>>8)+((n&255)<<23)*2}}},sr=function(n,r,t,e,i){return Cn(n,r.level==null?6:r.level,r.mem==null?Math.ceil(Math.max(8,Math.min(13,Math.log(n.length)))*1.5):12+r.mem,t,e,!i)},Zr=function(n,r){var t={};for(var e in n)t[e]=n[e];for(var e in r)t[e]=r[e];return t},Sn=function(n,r,t){for(var e=n(),i=n.toString(),a=i.slice(i.indexOf("[")+1,i.lastIndexOf("]")).replace(/ /g,"").split(","),o=0;o>>=8},_r=function(n,r){var t=r.filename;if(n[0]=31,n[1]=139,n[2]=8,n[8]=r.level<2?4:r.level==9?2:0,n[9]=3,r.mtime!=0&&F(n,4,Math.floor(new Date(r.mtime||Date.now())/1e3)),t){n[3]=8;for(var e=0;e<=t.length;++e)n[e+10]=t.charCodeAt(e)}},br=function(n){if(n[0]!=31||n[1]!=139||n[2]!=8)throw"invalid gzip data";var r=n[3],t=10;r&4&&(t+=n[10]|(n[11]<<8)+2);for(var e=(r>>3&1)+(r>>4&1);e>0;e-=!n[t++]);return t+(r&2)},Gn=function(n){var r=n.length;return(n[r-4]|n[r-3]<<8|n[r-2]<<16)+2*(n[r-1]<<23)},rn=function(n){return 10+(n.filename&&n.filename.length+1||0)},nn=function(n,r){var t=r.level,e=t==0?0:t<6?1:t==9?3:2;n[0]=120,n[1]=e<<6|(e?32-2*e:1)},On=function(n){if((n[0]&15)!=8||n[0]>>>4>7||(n[0]<<8|n[1])%31)throw"invalid zlib data";if(n[1]&32)throw"invalid zlib data: preset dictionaries not supported"};function tn(n,r){return!r&&typeof n=="function"&&(r=n,n={}),this.ondata=r,n}var rr=function(){function n(r,t){!t&&typeof r=="function"&&(t=r,r={}),this.ondata=t,this.o=r||{}}return n.prototype.p=function(r,t){this.ondata(sr(r,this.o,0,0,!t),t)},n.prototype.push=function(r,t){if(this.d)throw"stream finished";if(!this.ondata)throw"no stream handler";this.d=t,this.p(r,t||!1)},n}(),En=function(){function n(r,t){zr([yr,function(){return[L,rr]}],this,tn.call(this,r,t),function(e){var i=new rr(e.data);onmessage=L(i)},6)}return n}();function Pn(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return mr(n,r,[yr],function(e){return ar(kr(e.data[0],e.data[1]))},0,t)}function kr(n,r){return sr(n,r||{},0,0)}var J=function(){function n(r){this.s={},this.p=new A(0),this.ondata=r}return n.prototype.e=function(r){if(this.d)throw"stream finished";if(!this.ondata)throw"no stream handler";var t=this.p.length,e=new A(t+r.length);e.set(this.p),e.set(r,t),this.p=e},n.prototype.c=function(r){this.d=this.s.i=r||!1;var t=this.s.b,e=Fr(this.p,this.o,this.s);this.ondata($(e,t,this.s.b),this.d),this.o=$(e,this.s.b-32768),this.s.b=this.o.length,this.p=$(this.p,this.s.p/8|0),this.s.p&=7},n.prototype.push=function(r,t){this.e(r),this.c(t)},n}(),en=function(){function n(r){this.ondata=r,zr([wr,function(){return[L,J]}],this,0,function(){var t=new J;onmessage=L(t)},7)}return n}();function an(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return mr(n,r,[wr],function(e){return ar(xr(e.data[0],Lr(e.data[1])))},1,t)}function xr(n,r){return Fr(n,r)}var qr=function(){function n(r,t){this.c=gr(),this.l=0,this.v=1,rr.call(this,r,t)}return n.prototype.push=function(r,t){rr.prototype.push.call(this,r,t)},n.prototype.p=function(r,t){this.c.p(r),this.l+=r.length;var e=sr(r,this.o,this.v&&rn(this.o),t&&8,!t);this.v&&(_r(e,this.o),this.v=0),t&&(F(e,e.length-8,this.c.d()),F(e,e.length-4,this.l)),this.ondata(e,t)},n}(),Rn=function(){function n(r,t){zr([yr,kn,function(){return[L,rr,qr]}],this,tn.call(this,r,t),function(e){var i=new qr(e.data);onmessage=L(i)},8)}return n}();function qn(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return mr(n,r,[yr,kn,function(){return[Hr]}],function(e){return ar(Hr(e.data[0],e.data[1]))},2,t)}function Hr(n,r){r||(r={});var t=gr(),e=n.length;t.p(n);var i=sr(n,r,rn(r),8),a=i.length;return _r(i,r),F(i,a-8,t.d()),F(i,a-4,e),i}var Wr=function(){function n(r){this.v=1,J.call(this,r)}return n.prototype.push=function(r,t){if(J.prototype.e.call(this,r),this.v){var e=this.p.length>3?br(this.p):4;if(e>=this.p.length&&!t)return;this.p=this.p.subarray(e),this.v=0}if(t){if(this.p.length<8)throw"invalid gzip stream";this.p=this.p.subarray(0,-8)}J.prototype.c.call(this,t)},n}(),Hn=function(){function n(r){this.ondata=r,zr([wr,Bn,function(){return[L,J,Wr]}],this,0,function(){var t=new Wr;onmessage=L(t)},9)}return n}();function Wn(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return mr(n,r,[wr,Bn,function(){return[Yr]}],function(e){return ar(Yr(e.data[0]))},3,t)}function Yr(n,r){return Fr(n.subarray(br(n),-8),r||new A(Gn(n)))}var on=function(){function n(r,t){this.c=$r(),this.v=1,rr.call(this,r,t)}return n.prototype.push=function(r,t){rr.prototype.push.call(this,r,t)},n.prototype.p=function(r,t){this.c.p(r);var e=sr(r,this.o,this.v&&2,t&&4,!t);this.v&&(nn(e,this.o),this.v=0),t&&F(e,e.length-4,this.c.d()),this.ondata(e,t)},n}(),nt=function(){function n(r,t){zr([yr,Tn,function(){return[L,rr,on]}],this,tn.call(this,r,t),function(e){var i=new on(e.data);onmessage=L(i)},10)}return n}();function tt(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return mr(n,r,[yr,Tn,function(){return[fn]}],function(e){return ar(fn(e.data[0],e.data[1]))},4,t)}function fn(n,r){r||(r={});var t=$r();t.p(n);var e=sr(n,r,2,4);return nn(e,r),F(e,e.length-4,t.d()),e}var jr=function(){function n(r){this.v=1,J.call(this,r)}return n.prototype.push=function(r,t){if(J.prototype.e.call(this,r),this.v){if(this.p.length<2&&!t)return;this.p=this.p.subarray(2),this.v=0}if(t){if(this.p.length<4)throw"invalid zlib stream";this.p=this.p.subarray(0,-4)}J.prototype.c.call(this,t)},n}(),Yn=function(){function n(r){this.ondata=r,zr([wr,In,function(){return[L,J,jr]}],this,0,function(){var t=new jr;onmessage=L(t)},11)}return n}();function jn(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return mr(n,r,[wr,In,function(){return[Jr]}],function(e){return ar(Jr(e.data[0],Lr(e.data[1])))},5,t)}function Jr(n,r){return Fr((On(n),n.subarray(2,-4)),r)}var Jn=function(){function n(r){this.G=Wr,this.I=J,this.Z=jr,this.ondata=r}return n.prototype.push=function(r,t){if(!this.ondata)throw"no stream handler";if(this.s)this.s.push(r,t);else{if(this.p&&this.p.length){var e=new A(this.p.length+r.length);e.set(this.p),e.set(r,this.p.length)}else this.p=r;if(this.p.length>2){var i=this,a=function(){i.ondata.apply(i,arguments)};this.s=this.p[0]==31&&this.p[1]==139&&this.p[2]==8?new this.G(a):(this.p[0]&15)!=8||this.p[0]>>4>7||(this.p[0]<<8|this.p[1])%31?new this.I(a):new this.Z(a),this.s.push(this.p,t),this.p=null}}},n}(),et=function(){function n(r){this.G=Hn,this.I=en,this.Z=Yn,this.ondata=r}return n.prototype.push=function(r,t){Jn.prototype.push.call(this,r,t)},n}();function it(n,r,t){if(t||(t=r,r={}),typeof t!="function")throw"no callback";return n[0]==31&&n[1]==139&&n[2]==8?Wn(n,r,t):(n[0]&15)!=8||n[0]>>4>7||(n[0]<<8|n[1])%31?an(n,r,t):jn(n,r,t)}function at(n,r){return n[0]==31&&n[1]==139&&n[2]==8?Yr(n,r):(n[0]&15)!=8||n[0]>>4>7||(n[0]<<8|n[1])%31?xr(n,r):Jr(n,r)}var sn=function(n,r,t,e){for(var i in n){var a=n[i],o=r+i;a instanceof A?t[o]=[a,e]:Array.isArray(a)?t[o]=[a[0],Zr(e,a[1])]:sn(a,o+"/",t,e)}},Kn=typeof TextEncoder!="undefined"&&new TextEncoder,hn=typeof TextDecoder!="undefined"&&new TextDecoder,Nn=0;try{hn.decode(er,{stream:!0}),Nn=1}catch(n){}var Qn=function(n){for(var r="",t=0;;){var e=n[t++],i=(e>127)+(e>223)+(e>239);if(t+i>n.length)return[r,$(n,t-1)];i?i==3?(e=((e&15)<<18|(n[t++]&63)<<12|(n[t++]&63)<<6|n[t++]&63)-65536,r+=String.fromCharCode(55296|e>>10,56320|e&1023)):i&1?r+=String.fromCharCode((e&31)<<6|n[t++]&63):r+=String.fromCharCode((e&15)<<12|(n[t++]&63)<<6|n[t++]&63):r+=String.fromCharCode(e)}},ot=function(){function n(r){this.ondata=r,Nn?this.t=new TextDecoder:this.p=er}return n.prototype.push=function(r,t){if(!this.ondata)throw"no callback";if(t||(t=!1),this.t)return this.ondata(this.t.decode(r,{stream:!t}),t);var e=new A(this.p.length+r.length);e.set(this.p),e.set(r,this.p.length);var i=Qn(e),a=i[0],o=i[1];if(t&&o.length)throw"invalid utf-8 data";this.p=o,this.ondata(a,t)},n}(),ft=function(){function n(r){this.ondata=r}return n.prototype.push=function(r,t){if(!this.ondata)throw"no callback";this.ondata(or(r),t||!1)},n}();function or(n,r){if(r){for(var t=new A(n.length),e=0;e>1)),o=0,f=function(u){a[o++]=u},e=0;ea.length){var h=new A(o+8+(i-e<<1));h.set(a),a=h}var s=n.charCodeAt(e);s<128||r?f(s):s<2048?(f(192|s>>>6),f(128|s&63)):s>55295&&s<57344?(s=65536+(s&1023<<10)|n.charCodeAt(++e)&1023,f(240|s>>>18),f(128|s>>>12&63),f(128|s>>>6&63),f(128|s&63)):(f(224|s>>>12),f(128|s>>>6&63),f(128|s&63))}return $(a,0,o)}function un(n,r){if(r){for(var t="",e=0;e65535)throw"extra field too long";r+=e+4}return r},Ar=function(n,r,t,e,i,a,o,f){var h=e.length,s=t.extra,u=f&&f.length,l=fr(s);F(n,r,o!=null?33639248:67324752),r+=4,o!=null&&(n[r++]=20,n[r++]=t.os),n[r]=20,r+=2,n[r++]=t.flag<<1|(a==null&&8),n[r++]=i&&8,n[r++]=t.compression&255,n[r++]=t.compression>>8;var p=new Date(t.mtime==null?Date.now():t.mtime),y=p.getFullYear()-1980;if(y<0||y>119)throw"date not in range 1980-2099";if(F(n,r,(y<<24)*2|p.getMonth()+1<<21|p.getDate()<<16|p.getHours()<<11|p.getMinutes()<<5|p.getSeconds()>>>1),r+=4,a!=null&&(F(n,r,t.crc),F(n,r+4,a),F(n,r+8,t.size)),F(n,r+12,h),F(n,r+14,l),r+=16,o!=null&&(F(n,r,u),F(n,r+6,t.attrs),F(n,r+10,o),r+=14),n.set(e,r),r+=h,l)for(var c in s){var g=s[c],w=g.length;F(n,r,+c),F(n,r+2,w),n.set(g,r+4),r+=4+w}return u&&(n.set(f,r),r+=u),r},ln=function(n,r,t,e,i){F(n,r,101010256),F(n,r+8,t),F(n,r+10,t),F(n,r+12,e),F(n,r+16,i)},Br=function(){function n(r){this.filename=r,this.c=gr(),this.size=0,this.compression=0}return n.prototype.process=function(r,t){this.ondata(null,r,t)},n.prototype.push=function(r,t){if(!this.ondata)throw"no callback - add to ZIP archive before pushing";this.c.p(r),this.size+=r.length,t&&(this.crc=this.c.d()),this.process(r,t||!1)},n}(),st=function(){function n(r,t){var e=this;t||(t={}),Br.call(this,r),this.d=new rr(t,function(i,a){e.ondata(null,i,a)}),this.compression=8,this.flag=Vn(t.level)}return n.prototype.process=function(r,t){try{this.d.push(r,t)}catch(e){this.ondata(e,null,t)}},n.prototype.push=function(r,t){Br.prototype.push.call(this,r,t)},n}(),ht=function(){function n(r,t){var e=this;t||(t={}),Br.call(this,r),this.d=new En(t,function(i,a,o){e.ondata(i,a,o)}),this.compression=8,this.flag=Vn(t.level),this.terminate=this.d.terminate}return n.prototype.process=function(r,t){this.d.push(r,t)},n.prototype.push=function(r,t){Br.prototype.push.call(this,r,t)},n}(),ut=function(){function n(r){this.ondata=r,this.u=[],this.d=1}return n.prototype.add=function(r){var t=this;if(this.d&2)throw"stream finished";var e=or(r.filename),i=e.length,a=r.comment,o=a&&or(a),f=i!=r.filename.length||o&&a.length!=o.length,h=i+fr(r.extra)+30;if(i>65535)throw"filename too long";var s=new A(h);Ar(s,0,r,e,f);var u=[s],l=function(){for(var w=0,M=u;w65535&&Z("filename too long",null),!I)Z(null,z);else if(C<16e4)try{Z(null,kr(z,m))}catch(B){Z(B,null)}else u.push(Pn(z,m,Z))},c=0;c65535)throw"filename too long";var M=u?kr(h,s):h,z=M.length,m=gr();m.p(h),e.push(Zr(s,{size:h.length,crc:m.d(),c:M,f:l,m:c,u:p!=o.length||c&&y.length!=g,o:i,compression:u})),i+=30+p+w+z,a+=76+2*(p+w)+(g||0)+z}for(var D=new A(a+22),C=i,U=a-i,x=0;x0){var i=Math.min(this.c,r.length),a=r.subarray(0,i);if(this.c-=i,this.d?this.d.push(a,!this.c):this.k[0].push(a),r=r.subarray(i),r.length)return this.push(r,t)}else{var o=0,f=0,h=void 0,s=void 0;this.p.length?r.length?(s=new A(this.p.length+r.length),s.set(this.p),s.set(r,this.p.length)):s=this.p:s=r;for(var u=s.length,l=this.c,p=l&&this.d,y=function(){var M,z=P(s,f);if(z==67324752){o=1,h=f,c.d=null,c.c=0;var m=Y(s,f+6),D=Y(s,f+8),C=m&2048,U=m&8,x=Y(s,f+26),v=Y(s,f+28);if(u>f+30+x+v){var E=[];c.k.unshift(E),o=2;var S=P(s,f+18),K=P(s,f+22),I=un(s.subarray(f+30,f+=30+x),!C);S==4294967295?(M=U?[-2]:Ln(s,f),S=M[0],K=M[1]):U&&(S=-1),f+=v,c.c=S;var Z={name:I,compression:D,start:function(){if(!Z.ondata)throw"no callback";if(!S)Z.ondata(null,er,!0);else{var B=e.o[D];if(!B)throw"unknown compression type "+D;var G=S<0?new B(I):new B(I,S,K);G.ondata=function(N,Q,W){Z.ondata(N,Q,W)};for(var k=0,O=E;k=0&&(Z.size=S,Z.originalSize=K),c.onfile(Z)}return"break"}else if(l){if(z==134695760)return h=f+=12+(l==-2&&8),o=2,c.c=0,"break";if(z==33639248)return h=f-=4,o=2,c.c=0,"break"}},c=this;f65558){r("invalid zip file",null);return}var o=Y(n,a+8);o||r(null,{});var f=o,h=P(n,a+16),s=h==4294967295;if(s){if(a=P(n,a-12),P(n,a)!=101075792){r("invalid zip file",null);return}f=o=P(n,a+32),h=P(n,a+48)}for(var u=function(p){var y=$n(n,h,s),c=y[0],g=y[1],w=y[2],M=y[3],z=y[4],m=y[5],D=Xn(n,m);h=z;var C=function(x,v){x?(e(),r(x,null)):(i[M]=v,--o||r(null,i))};if(!c)C(null,$(n,D,D+g));else if(c==8){var U=n.subarray(D,D+g);if(g<32e4)try{C(null,xr(U,new A(w)))}catch(x){C(x,null)}else t.push(an(U,{size:w},C))}else C("unknown compression type "+c,null)},l=0;l65558)throw"invalid zip file";var e=Y(n,t+8);if(!e)return{};var i=P(n,t+16),a=i==4294967295;if(a){if(t=P(n,t-12),P(n,t)!=101075792)throw"invalid zip file";e=P(n,t+32),i=P(n,t+48)}for(var o=0;o near && _end4.z > near; + if ( isBehindCameraNear ) { - start.w = 1; - end.w = 1; + continue; - // camera space - start.applyMatrix4( mvMatrix ); - end.applyMatrix4( mvMatrix ); - - // skip the segment if it's entirely behind the camera - var isBehindCameraNear = start.z > near && end.z > near; - if ( isBehindCameraNear ) { - - continue; - - } - - // trim the segment if it extends behind camera near - if ( start.z > near ) { + } - const deltaDist = start.z - end.z; - const t = ( start.z - near ) / deltaDist; - start.lerp( end, t ); + // trim the segment if it extends behind camera near + if ( _start4.z > near ) { - } else if ( end.z > near ) { + const deltaDist = _start4.z - _end4.z; + const t = ( _start4.z - near ) / deltaDist; + _start4.lerp( _end4, t ); - const deltaDist = end.z - start.z; - const t = ( end.z - near ) / deltaDist; - end.lerp( start, t ); + } else if ( _end4.z > near ) { - } + const deltaDist = _end4.z - _start4.z; + const t = ( _end4.z - near ) / deltaDist; + _end4.lerp( _start4, t ); - // clip space - start.applyMatrix4( projectionMatrix ); - end.applyMatrix4( projectionMatrix ); + } - // ndc space [ - 1.0, 1.0 ] - start.multiplyScalar( 1 / start.w ); - end.multiplyScalar( 1 / end.w ); + // clip space + _start4.applyMatrix4( projectionMatrix ); + _end4.applyMatrix4( projectionMatrix ); - // screen space - start.x *= resolution.x / 2; - start.y *= resolution.y / 2; + // ndc space [ - 1.0, 1.0 ] + _start4.multiplyScalar( 1 / _start4.w ); + _end4.multiplyScalar( 1 / _end4.w ); - end.x *= resolution.x / 2; - end.y *= resolution.y / 2; + // screen space + _start4.x *= resolution.x / 2; + _start4.y *= resolution.y / 2; - // create 2d segment - line.start.copy( start ); - line.start.z = 0; + _end4.x *= resolution.x / 2; + _end4.y *= resolution.y / 2; - line.end.copy( end ); - line.end.z = 0; + // create 2d segment + _line.start.copy( _start4 ); + _line.start.z = 0; - // get closest point on ray to segment - var param = line.closestPointToPointParameter( ssOrigin3, true ); - line.at( param, closestPoint ); + _line.end.copy( _end4 ); + _line.end.z = 0; - // check if the intersection point is within clip space - var zPos = MathUtils.lerp( start.z, end.z, param ); - var isInClipSpace = zPos >= - 1 && zPos <= 1; + // get closest point on ray to segment + const param = _line.closestPointToPointParameter( _ssOrigin3, true ); + _line.at( param, _closestPoint ); - var isInside = ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5; + // check if the intersection point is within clip space + const zPos = MathUtils.lerp( _start4.z, _end4.z, param ); + const isInClipSpace = zPos >= - 1 && zPos <= 1; - if ( isInClipSpace && isInside ) { + const isInside = _ssOrigin3.distanceTo( _closestPoint ) < lineWidth * 0.5; - line.start.fromBufferAttribute( instanceStart, i ); - line.end.fromBufferAttribute( instanceEnd, i ); + if ( isInClipSpace && isInside ) { - line.start.applyMatrix4( matrixWorld ); - line.end.applyMatrix4( matrixWorld ); + _line.start.fromBufferAttribute( instanceStart, i ); + _line.end.fromBufferAttribute( instanceEnd, i ); - var pointOnLine = new Vector3(); - var point = new Vector3(); + _line.start.applyMatrix4( matrixWorld ); + _line.end.applyMatrix4( matrixWorld ); - ray.distanceSqToSegment( line.start, line.end, point, pointOnLine ); + const pointOnLine = new Vector3(); + const point = new Vector3(); - intersects.push( { + ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine ); - point: point, - pointOnLine: pointOnLine, - distance: ray.origin.distanceTo( point ), + intersects.push( { - object: this, - face: null, - faceIndex: i, - uv: null, - uv2: null, + point: point, + pointOnLine: pointOnLine, + distance: ray.origin.distanceTo( point ), - } ); + object: this, + face: null, + faceIndex: i, + uv: null, + uv2: null, - } + } ); } - }; + } + + } - }() ) +} -} ); +LineSegments2.prototype.LineSegments2 = true; export { LineSegments2 }; diff --git a/examples/jsm/lines/LineSegmentsGeometry.js b/examples/jsm/lines/LineSegmentsGeometry.js index b30831b658f234..019dea9f970930 100644 --- a/examples/jsm/lines/LineSegmentsGeometry.js +++ b/examples/jsm/lines/LineSegmentsGeometry.js @@ -9,32 +9,31 @@ import { WireframeGeometry } from '../../../build/three.module.js'; -var LineSegmentsGeometry = function () { +const _box = new Box3(); +const _vector = new Vector3(); - InstancedBufferGeometry.call( this ); +class LineSegmentsGeometry extends InstancedBufferGeometry { - this.type = 'LineSegmentsGeometry'; + constructor() { - var positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; - var uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ]; - var index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; + super(); - this.setIndex( index ); - this.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + this.type = 'LineSegmentsGeometry'; -}; + const positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; + const uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ]; + const index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; -LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGeometry.prototype ), { + this.setIndex( index ); + this.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - constructor: LineSegmentsGeometry, - - isLineSegmentsGeometry: true, + } - applyMatrix4: function ( matrix ) { + applyMatrix4( matrix ) { - var start = this.attributes.instanceStart; - var end = this.attributes.instanceEnd; + const start = this.attributes.instanceStart; + const end = this.attributes.instanceEnd; if ( start !== undefined ) { @@ -60,11 +59,11 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe return this; - }, + } - setPositions: function ( array ) { + setPositions( array ) { - var lineSegments; + let lineSegments; if ( array instanceof Float32Array ) { @@ -76,7 +75,7 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe } - var instanceBuffer = new InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz + const instanceBuffer = new InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz this.setAttribute( 'instanceStart', new InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz this.setAttribute( 'instanceEnd', new InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz @@ -88,11 +87,11 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe return this; - }, + } - setColors: function ( array ) { + setColors( array ) { - var colors; + let colors; if ( array instanceof Float32Array ) { @@ -104,32 +103,32 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe } - var instanceColorBuffer = new InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb + const instanceColorBuffer = new InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb this.setAttribute( 'instanceColorStart', new InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb this.setAttribute( 'instanceColorEnd', new InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb return this; - }, + } - fromWireframeGeometry: function ( geometry ) { + fromWireframeGeometry( geometry ) { this.setPositions( geometry.attributes.position.array ); return this; - }, + } - fromEdgesGeometry: function ( geometry ) { + fromEdgesGeometry( geometry ) { this.setPositions( geometry.attributes.position.array ); return this; - }, + } - fromMesh: function ( mesh ) { + fromMesh( mesh ) { this.fromWireframeGeometry( new WireframeGeometry( mesh.geometry ) ); @@ -137,11 +136,11 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe return this; - }, + } - fromLineSegments: function ( lineSegments ) { + romLineSegments( lineSegments ) { - var geometry = lineSegments.geometry; + const geometry = lineSegments.geometry; if ( geometry.isGeometry ) { @@ -158,97 +157,85 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe return this; - }, - - computeBoundingBox: function () { - - var box = new Box3(); - - return function computeBoundingBox() { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } + } - var start = this.attributes.instanceStart; - var end = this.attributes.instanceEnd; + computeBoundingBox() { - if ( start !== undefined && end !== undefined ) { + if ( this.boundingBox === null ) { - this.boundingBox.setFromBufferAttribute( start ); + this.boundingBox = new Box3(); - box.setFromBufferAttribute( end ); + } - this.boundingBox.union( box ); + const start = this.attributes.instanceStart; + const end = this.attributes.instanceEnd; - } + if ( start !== undefined && end !== undefined ) { - }; + this.boundingBox.setFromBufferAttribute( start ); - }(), + _box.setFromBufferAttribute( end ); - computeBoundingSphere: function () { + this.boundingBox.union( _box ); - var vector = new Vector3(); + } - return function computeBoundingSphere() { + } - if ( this.boundingSphere === null ) { + computeBoundingSphere() { - this.boundingSphere = new Sphere(); + if ( this.boundingSphere === null ) { - } + this.boundingSphere = new Sphere(); - if ( this.boundingBox === null ) { + } - this.computeBoundingBox(); + if ( this.boundingBox === null ) { - } + this.computeBoundingBox(); - var start = this.attributes.instanceStart; - var end = this.attributes.instanceEnd; + } - if ( start !== undefined && end !== undefined ) { + const start = this.attributes.instanceStart; + const end = this.attributes.instanceEnd; - var center = this.boundingSphere.center; + if ( start !== undefined && end !== undefined ) { - this.boundingBox.getCenter( center ); + const center = this.boundingSphere.center; - var maxRadiusSq = 0; + this.boundingBox.getCenter( center ); - for ( var i = 0, il = start.count; i < il; i ++ ) { + let maxRadiusSq = 0; - vector.fromBufferAttribute( start, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + for ( let i = 0, il = start.count; i < il; i ++ ) { - vector.fromBufferAttribute( end, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + _vector.fromBufferAttribute( start, i ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) ); - } + _vector.fromBufferAttribute( end, i ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) ); - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + } - if ( isNaN( this.boundingSphere.radius ) ) { + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); + if ( isNaN( this.boundingSphere.radius ) ) { - } + console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); } - }; + } - }(), + } - toJSON: function () { + toJSON() { // todo - }, + } - applyMatrix: function ( matrix ) { + applyMatrix( matrix ) { console.warn( 'THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().' ); @@ -256,6 +243,8 @@ LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGe } -} ); +} + +LineSegmentsGeometry.prototype.isLineSegmentsGeometry = true; export { LineSegmentsGeometry }; diff --git a/examples/jsm/lines/Wireframe.js b/examples/jsm/lines/Wireframe.js index 21d1f5c917a9ec..c06e80c5fec20b 100644 --- a/examples/jsm/lines/Wireframe.js +++ b/examples/jsm/lines/Wireframe.js @@ -7,57 +7,50 @@ import { import { LineSegmentsGeometry } from '../lines/LineSegmentsGeometry.js'; import { LineMaterial } from '../lines/LineMaterial.js'; -var Wireframe = function ( geometry, material ) { +const _start = new Vector3(); +const _end = new Vector3(); - Mesh.call( this ); +class Wireframe extends Mesh { - this.type = 'Wireframe'; + constructor( geometry = new LineSegmentsGeometry(), material = new LineMaterial( { color: Math.random() * 0xffffff } ) ) { - this.geometry = geometry !== undefined ? geometry : new LineSegmentsGeometry(); - this.material = material !== undefined ? material : new LineMaterial( { color: Math.random() * 0xffffff } ); + super( geometry, material ); -}; + this.type = 'Wireframe'; -Wireframe.prototype = Object.assign( Object.create( Mesh.prototype ), { + } - constructor: Wireframe, + // for backwards-compatability, but could be a method of LineSegmentsGeometry... - isWireframe: true, + computeLineDistances() { - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + const geometry = this.geometry; - var start = new Vector3(); - var end = new Vector3(); + const instanceStart = geometry.attributes.instanceStart; + const instanceEnd = geometry.attributes.instanceEnd; + const lineDistances = new Float32Array( 2 * instanceStart.count ); - return function computeLineDistances() { + for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) { - var geometry = this.geometry; + _start.fromBufferAttribute( instanceStart, i ); + _end.fromBufferAttribute( instanceEnd, i ); - var instanceStart = geometry.attributes.instanceStart; - var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.count ); + lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; + lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end ); - for ( var i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) { + } - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + const instanceDistanceBuffer = new InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1 - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + geometry.setAttribute( 'instanceDistanceStart', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 + geometry.setAttribute( 'instanceDistanceEnd', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 - } + return this; - var instanceDistanceBuffer = new InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1 + } - geometry.setAttribute( 'instanceDistanceStart', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 +} - return this; - - }; - - }() ) - -} ); +Wireframe.prototype.isWireframe = true; export { Wireframe }; diff --git a/examples/jsm/lines/WireframeGeometry2.js b/examples/jsm/lines/WireframeGeometry2.js index 4b63a4a06a35dd..dfb4f6c5191993 100644 --- a/examples/jsm/lines/WireframeGeometry2.js +++ b/examples/jsm/lines/WireframeGeometry2.js @@ -3,24 +3,22 @@ import { } from '../../../build/three.module.js'; import { LineSegmentsGeometry } from '../lines/LineSegmentsGeometry.js'; -var WireframeGeometry2 = function ( geometry ) { +class WireframeGeometry2 extends LineSegmentsGeometry { - LineSegmentsGeometry.call( this ); + constructor( geometry ) { - this.type = 'WireframeGeometry2'; + super(); - this.fromWireframeGeometry( new WireframeGeometry( geometry ) ); + this.type = 'WireframeGeometry2'; - // set colors, maybe + this.fromWireframeGeometry( new WireframeGeometry( geometry ) ); -}; + // set colors, maybe -WireframeGeometry2.prototype = Object.assign( Object.create( LineSegmentsGeometry.prototype ), { + } - constructor: WireframeGeometry2, +} - isWireframeGeometry2: true - -} ); +WireframeGeometry2.prototype.isWireframeGeometry2 = true; export { WireframeGeometry2 }; diff --git a/examples/jsm/loaders/3DMLoader.js b/examples/jsm/loaders/3DMLoader.js index 2f9842127021b5..7d555c149690ac 100644 --- a/examples/jsm/loaders/3DMLoader.js +++ b/examples/jsm/loaders/3DMLoader.js @@ -24,52 +24,50 @@ import { TextureLoader } from '../../../build/three.module.js'; -var Rhino3dmLoader = function ( manager ) { +const _taskCache = new WeakMap(); - Loader.call( this, manager ); +class Rhino3dmLoader extends Loader { - this.libraryPath = ''; - this.libraryPending = null; - this.libraryBinary = null; - this.libraryConfig = {}; + constructor( manager ) { - this.url = ''; + super( manager ); - this.workerLimit = 4; - this.workerPool = []; - this.workerNextTaskID = 1; - this.workerSourceURL = ''; - this.workerConfig = {}; + this.libraryPath = ''; + this.libraryPending = null; + this.libraryBinary = null; + this.libraryConfig = {}; - this.materials = []; + this.url = ''; -}; + this.workerLimit = 4; + this.workerPool = []; + this.workerNextTaskID = 1; + this.workerSourceURL = ''; + this.workerConfig = {}; -Rhino3dmLoader.taskCache = new WeakMap(); + this.materials = []; -Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: Rhino3dmLoader, + } - setLibraryPath: function ( path ) { + setLibraryPath( path ) { this.libraryPath = path; return this; - }, + } - setWorkerLimit: function ( workerLimit ) { + setWorkerLimit( workerLimit ) { this.workerLimit = workerLimit; return this; - }, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); @@ -81,9 +79,9 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // Check for an existing task using this buffer. A transferred buffer cannot be transferred // again from this thread. - if ( Rhino3dmLoader.taskCache.has( buffer ) ) { + if ( _taskCache.has( buffer ) ) { - var cachedTask = Rhino3dmLoader.taskCache.get( buffer ); + const cachedTask = _taskCache.get( buffer ); return cachedTask.promise.then( onLoad ).catch( onError ); @@ -96,22 +94,22 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - debug: function () { + debug() { console.log( 'Task load: ', this.workerPool.map( ( worker ) => worker._taskLoad ) ); - }, + } - decodeObjects: function ( buffer, url ) { + decodeObjects( buffer, url ) { - var worker; - var taskID; + let worker; + let taskID; - var taskCost = buffer.byteLength; + const taskCost = buffer.byteLength; - var objectPending = this._getWorker( taskCost ) + const objectPending = this._getWorker( taskCost ) .then( ( _worker ) => { worker = _worker; @@ -147,7 +145,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } ); // Cache the task result. - Rhino3dmLoader.taskCache.set( buffer, { + _taskCache.set( buffer, { url: url, promise: objectPending @@ -156,19 +154,19 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return objectPending; - }, + } - parse: function ( data, onLoad, onError ) { + parse( data, onLoad, onError ) { this.decodeObjects( data, '' ) .then( onLoad ) .catch( onError ); - }, + } - _compareMaterials: function ( material ) { + _compareMaterials( material ) { - var mat = {}; + const mat = {}; mat.name = material.name; mat.color = {}; mat.color.r = material.color.r; @@ -176,10 +174,10 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { mat.color.b = material.color.b; mat.type = material.type; - for ( var i = 0; i < this.materials.length; i ++ ) { + for ( let i = 0; i < this.materials.length; i ++ ) { - var m = this.materials[ i ]; - var _mat = {}; + const m = this.materials[ i ]; + const _mat = {}; _mat.name = m.name; _mat.color = {}; _mat.color.r = m.color.r; @@ -199,9 +197,9 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return material; - }, + } - _createMaterial: function ( material ) { + _createMaterial( material ) { if ( material === undefined ) { @@ -214,9 +212,9 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var _diffuseColor = material.diffuseColor; + const _diffuseColor = material.diffuseColor; - var diffusecolor = new Color( _diffuseColor.r / 255.0, _diffuseColor.g / 255.0, _diffuseColor.b / 255.0 ); + const diffusecolor = new Color( _diffuseColor.r / 255.0, _diffuseColor.g / 255.0, _diffuseColor.b / 255.0 ); if ( _diffuseColor.r === 0 && _diffuseColor.g === 0 && _diffuseColor.b === 0 ) { @@ -228,7 +226,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // console.log( material ); - var mat = new MeshStandardMaterial( { + const mat = new MeshStandardMaterial( { color: diffusecolor, name: material.name, side: 2, @@ -236,15 +234,15 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { opacity: 1.0 - material.transparency } ); - var textureLoader = new TextureLoader(); + const textureLoader = new TextureLoader(); - for ( var i = 0; i < material.textures.length; i ++ ) { + for ( let i = 0; i < material.textures.length; i ++ ) { - var texture = material.textures[ i ]; + const texture = material.textures[ i ]; if ( texture.image !== null ) { - var map = textureLoader.load( texture.image ); + const map = textureLoader.load( texture.image ); switch ( texture.type ) { @@ -281,16 +279,16 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return mat; - }, + } - _createGeometry: function ( data ) { + _createGeometry( data ) { // console.log(data); - var object = new Object3D(); - var instanceDefinitionObjects = []; - var instanceDefinitions = []; - var instanceReferences = []; + const object = new Object3D(); + const instanceDefinitionObjects = []; + const instanceDefinitions = []; + const instanceReferences = []; object.userData[ 'layers' ] = data.layers; object.userData[ 'groups' ] = data.groups; @@ -299,13 +297,13 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { object.userData[ 'materials' ] = null; object.name = this.url; - var objects = data.objects; - var materials = data.materials; + let objects = data.objects; + const materials = data.materials; - for ( var i = 0; i < objects.length; i ++ ) { + for ( let i = 0; i < objects.length; i ++ ) { - var obj = objects[ i ]; - var attributes = obj.attributes; + const obj = objects[ i ]; + const attributes = obj.attributes; switch ( obj.objectType ) { @@ -323,17 +321,19 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { default: + let _object; + if ( attributes.materialIndex >= 0 ) { - var rMaterial = materials[ attributes.materialIndex ]; - var material = this._createMaterial( rMaterial ); + const rMaterial = materials[ attributes.materialIndex ]; + let material = this._createMaterial( rMaterial ); material = this._compareMaterials( material ); - var _object = this._createObject( obj, material ); + _object = this._createObject( obj, material ); } else { - var material = this._createMaterial( ); - var _object = this._createObject( obj, material ); + const material = this._createMaterial( ); + _object = this._createObject( obj, material ); } @@ -343,7 +343,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var layer = data.layers[ attributes.layerIndex ]; + const layer = data.layers[ attributes.layerIndex ]; _object.visible = layer ? data.layers[ attributes.layerIndex ].visible : true; @@ -363,19 +363,19 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - for ( var i = 0; i < instanceDefinitions.length; i ++ ) { + for ( let i = 0; i < instanceDefinitions.length; i ++ ) { - var iDef = instanceDefinitions[ i ]; + const iDef = instanceDefinitions[ i ]; - var objects = []; + objects = []; - for ( var j = 0; j < iDef.attributes.objectIds.length; j ++ ) { + for ( let j = 0; j < iDef.attributes.objectIds.length; j ++ ) { - var objId = iDef.attributes.objectIds[ j ]; + const objId = iDef.attributes.objectIds[ j ]; - for ( var p = 0; p < instanceDefinitionObjects.length; p ++ ) { + for ( let p = 0; p < instanceDefinitionObjects.length; p ++ ) { - var idoId = instanceDefinitionObjects[ p ].userData.attributes.id; + const idoId = instanceDefinitionObjects[ p ].userData.attributes.id; if ( objId === idoId ) { @@ -389,21 +389,21 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // Currently clones geometry and does not take advantage of instancing - for ( var j = 0; j < instanceReferences.length; j ++ ) { + for ( let j = 0; j < instanceReferences.length; j ++ ) { - var iRef = instanceReferences[ j ]; + const iRef = instanceReferences[ j ]; if ( iRef.geometry.parentIdefId === iDef.attributes.id ) { - var iRefObject = new Object3D(); - var xf = iRef.geometry.xform.array; + const iRefObject = new Object3D(); + const xf = iRef.geometry.xform.array; - var matrix = new Matrix4(); + const matrix = new Matrix4(); matrix.set( xf[ 0 ], xf[ 1 ], xf[ 2 ], xf[ 3 ], xf[ 4 ], xf[ 5 ], xf[ 6 ], xf[ 7 ], xf[ 8 ], xf[ 9 ], xf[ 10 ], xf[ 11 ], xf[ 12 ], xf[ 13 ], xf[ 14 ], xf[ 15 ] ); iRefObject.applyMatrix4( matrix ); - for ( var p = 0; p < objects.length; p ++ ) { + for ( let p = 0; p < objects.length; p ++ ) { iRefObject.add( objects[ p ].clone( true ) ); @@ -420,37 +420,38 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { object.userData[ 'materials' ] = this.materials; return object; - }, + } + + _createObject( obj, mat ) { - _createObject: function ( obj, mat ) { + const loader = new BufferGeometryLoader(); - var loader = new BufferGeometryLoader(); + const attributes = obj.attributes; - var attributes = obj.attributes; + let geometry, material, _color, color; switch ( obj.objectType ) { case 'Point': case 'PointSet': - var geometry = loader.parse( obj.geometry ); + geometry = loader.parse( obj.geometry ); - var material = null; if ( geometry.attributes.hasOwnProperty( 'color' ) ) { material = new PointsMaterial( { vertexColors: true, sizeAttenuation: false, size: 2 } ); } else { - var _color = attributes.drawColor; - var color = new Color( _color.r / 255.0, _color.g / 255.0, _color.b / 255.0 ); + _color = attributes.drawColor; + color = new Color( _color.r / 255.0, _color.g / 255.0, _color.b / 255.0 ); material = new PointsMaterial( { color: color, sizeAttenuation: false, size: 2 } ); } material = this._compareMaterials( material ); - var points = new Points( geometry, material ); + const points = new Points( geometry, material ); points.userData[ 'attributes' ] = attributes; points.userData[ 'objectType' ] = obj.objectType; @@ -469,7 +470,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( obj.geometry === null ) return; - var geometry = loader.parse( obj.geometry ); + geometry = loader.parse( obj.geometry ); if ( geometry.attributes.hasOwnProperty( 'color' ) ) { @@ -484,7 +485,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var mesh = new Mesh( geometry, mat ); + const mesh = new Mesh( geometry, mat ); mesh.castShadow = attributes.castsShadows; mesh.receiveShadow = attributes.receivesShadows; mesh.userData[ 'attributes' ] = attributes; @@ -502,13 +503,13 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { geometry = loader.parse( obj.geometry ); - var _color = attributes.drawColor; - var color = new Color( _color.r / 255.0, _color.g / 255.0, _color.b / 255.0 ); + _color = attributes.drawColor; + color = new Color( _color.r / 255.0, _color.g / 255.0, _color.b / 255.0 ); - var material = new LineBasicMaterial( { color: color } ); + material = new LineBasicMaterial( { color: color } ); material = this._compareMaterials( material ); - var lines = new Line( geometry, material ); + const lines = new Line( geometry, material ); lines.userData[ 'attributes' ] = attributes; lines.userData[ 'objectType' ] = obj.objectType; @@ -524,13 +525,13 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { geometry = obj.geometry; - var ctx = document.createElement( 'canvas' ).getContext( '2d' ); - var font = `${geometry.fontHeight}px ${geometry.fontFace}`; + const ctx = document.createElement( 'canvas' ).getContext( '2d' ); + const font = `${geometry.fontHeight}px ${geometry.fontFace}`; ctx.font = font; - var width = ctx.measureText( geometry.text ).width + 10; - var height = geometry.fontHeight + 10; + const width = ctx.measureText( geometry.text ).width + 10; + const height = geometry.fontHeight + 10; - var r = window.devicePixelRatio; + const r = window.devicePixelRatio; ctx.canvas.width = width * r; ctx.canvas.height = height * r; @@ -541,19 +542,19 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { ctx.font = font; ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; - var color = attributes.drawColor; + color = attributes.drawColor; ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${color.a})`; ctx.fillRect( 0, 0, width, height ); ctx.fillStyle = 'white'; ctx.fillText( geometry.text, width / 2, height / 2 ); - var texture = new CanvasTexture( ctx.canvas ); + const texture = new CanvasTexture( ctx.canvas ); texture.minFilter = LinearFilter; texture.wrapS = ClampToEdgeWrapping; texture.wrapT = ClampToEdgeWrapping; - var material = new SpriteMaterial( { map: texture, depthTest: false } ); - var sprite = new Sprite( material ); + material = new SpriteMaterial( { map: texture, depthTest: false } ); + const sprite = new Sprite( material ); sprite.position.set( geometry.point[ 0 ], geometry.point[ 1 ], geometry.point[ 2 ] ); sprite.scale.set( width / 10, height / 10, 1.0 ); @@ -572,7 +573,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { geometry = obj.geometry; - var light; + let light; if ( geometry.isDirectionalLight ) { @@ -593,8 +594,8 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { light = new RectAreaLight(); - var width = Math.abs( geometry.width[ 2 ] ); - var height = Math.abs( geometry.length[ 0 ] ); + const width = Math.abs( geometry.width[ 2 ] ); + const height = Math.abs( geometry.length[ 0 ] ); light.position.set( geometry.location[ 0 ] - ( height / 2 ), geometry.location[ 1 ], geometry.location[ 2 ] - ( width / 2 ) ); @@ -623,8 +624,8 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( light ) { light.intensity = geometry.intensity; - var _color = geometry.diffuse; - var color = new Color( _color.r / 255.0, _color.g / 255.0, _color.b / 255.0 ); + _color = geometry.diffuse; + color = new Color( _color.r / 255.0, _color.g / 255.0, _color.b / 255.0 ); light.color = color; light.userData[ 'attributes' ] = attributes; light.userData[ 'objectType' ] = obj.objectType; @@ -635,26 +636,26 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - }, + } - _initLibrary: function () { + _initLibrary() { if ( ! this.libraryPending ) { // Load rhino3dm wrapper. - var jsLoader = new FileLoader( this.manager ); + const jsLoader = new FileLoader( this.manager ); jsLoader.setPath( this.libraryPath ); - var jsContent = new Promise( ( resolve, reject ) => { + const jsContent = new Promise( ( resolve, reject ) => { jsLoader.load( 'rhino3dm.js', resolve, undefined, reject ); } ); // Load rhino3dm WASM binary. - var binaryLoader = new FileLoader( this.manager ); + const binaryLoader = new FileLoader( this.manager ); binaryLoader.setPath( this.libraryPath ); binaryLoader.setResponseType( 'arraybuffer' ); - var binaryContent = new Promise( ( resolve, reject ) => { + const binaryContent = new Promise( ( resolve, reject ) => { binaryLoader.load( 'rhino3dm.wasm', resolve, undefined, reject ); @@ -666,9 +667,9 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { //this.libraryBinary = binaryContent; this.libraryConfig.wasmBinary = binaryContent; - var fn = Rhino3dmLoader.Rhino3dmWorker.toString(); + const fn = Rhino3dmWorker.toString(); - var body = [ + const body = [ '/* rhino3dm.js */', jsContent, '/* worker */', @@ -683,15 +684,15 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return this.libraryPending; - }, + } - _getWorker: function ( taskCost ) { + _getWorker( taskCost ) { return this._initLibrary().then( () => { if ( this.workerPool.length < this.workerLimit ) { - var worker = new Worker( this.workerSourceURL ); + const worker = new Worker( this.workerSourceURL ); worker._callbacks = {}; worker._taskCosts = {}; @@ -704,7 +705,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { worker.onmessage = function ( e ) { - var message = e.data; + const message = e.data; switch ( message.type ) { @@ -735,7 +736,7 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var worker = this.workerPool[ this.workerPool.length - 1 ]; + const worker = this.workerPool[ this.workerPool.length - 1 ]; worker._taskLoad += taskCost; @@ -743,19 +744,19 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } ); - }, + } - _releaseTask: function ( worker, taskID ) { + _releaseTask( worker, taskID ) { worker._taskLoad -= worker._taskCosts[ taskID ]; delete worker._callbacks[ taskID ]; delete worker._taskCosts[ taskID ]; - }, + } - dispose: function () { + dispose() { - for ( var i = 0; i < this.workerPool.length; ++ i ) { + for ( let i = 0; i < this.workerPool.length; ++ i ) { this.workerPool[ i ].terminate(); @@ -767,27 +768,27 @@ Rhino3dmLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} /* WEB WORKER */ -Rhino3dmLoader.Rhino3dmWorker = function () { +function Rhino3dmWorker() { - var libraryPending; - var libraryConfig; - var rhino; + let libraryPending; + let libraryConfig; + let rhino; onmessage = function ( e ) { - var message = e.data; + const message = e.data; switch ( message.type ) { case 'init': libraryConfig = message.libraryConfig; - var wasmBinary = libraryConfig.wasmBinary; - var RhinoModule; + const wasmBinary = libraryConfig.wasmBinary; + let RhinoModule; libraryPending = new Promise( function ( resolve ) { /* Like Basis Loader */ @@ -805,10 +806,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { case 'decode': - var buffer = message.buffer; + const buffer = message.buffer; libraryPending.then( () => { - var data = decodeObjects( rhino, buffer ); + const data = decodeObjects( rhino, buffer ); self.postMessage( { type: 'decode', id: message.id, data } ); @@ -822,26 +823,26 @@ Rhino3dmLoader.Rhino3dmWorker = function () { function decodeObjects( rhino, buffer ) { - var arr = new Uint8Array( buffer ); - var doc = rhino.File3dm.fromByteArray( arr ); + const arr = new Uint8Array( buffer ); + const doc = rhino.File3dm.fromByteArray( arr ); - var objects = []; - var materials = []; - var layers = []; - var views = []; - var namedViews = []; - var groups = []; + const objects = []; + const materials = []; + const layers = []; + const views = []; + const namedViews = []; + const groups = []; //Handle objects - var objs = doc.objects(); - var cnt = objs.count; + const objs = doc.objects(); + const cnt = objs.count; - for ( var i = 0; i < cnt; i ++ ) { + for ( let i = 0; i < cnt; i ++ ) { - var _object = objs.get( i ); + const _object = objs.get( i ); - var object = extractObjectData( _object, doc ); + const object = extractObjectData( _object, doc ); _object.delete(); @@ -856,10 +857,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle instance definitions // console.log( `Instance Definitions Count: ${doc.instanceDefinitions().count()}` ); - for ( var i = 0; i < doc.instanceDefinitions().count(); i ++ ) { + for ( let i = 0; i < doc.instanceDefinitions().count(); i ++ ) { - var idef = doc.instanceDefinitions().get( i ); - var idefAttributes = extractProperties( idef ); + const idef = doc.instanceDefinitions().get( i ); + const idefAttributes = extractProperties( idef ); idefAttributes.objectIds = idef.getObjectIds(); objects.push( { geometry: null, attributes: idefAttributes, objectType: 'InstanceDefinition' } ); @@ -868,7 +869,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle materials - var textureTypes = [ + const textureTypes = [ // rhino.TextureType.Bitmap, rhino.TextureType.Diffuse, rhino.TextureType.Bump, @@ -877,7 +878,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { rhino.TextureType.Emap ]; - var pbrTextureTypes = [ + const pbrTextureTypes = [ rhino.TextureType.PBR_BaseColor, rhino.TextureType.PBR_Subsurface, rhino.TextureType.PBR_SubsurfaceScattering, @@ -900,25 +901,25 @@ Rhino3dmLoader.Rhino3dmWorker = function () { rhino.TextureType.PBR_Displacement ]; - for ( var i = 0; i < doc.materials().count(); i ++ ) { + for ( let i = 0; i < doc.materials().count(); i ++ ) { - var _material = doc.materials().get( i ); - var _pbrMaterial = _material.physicallyBased(); + const _material = doc.materials().get( i ); + const _pbrMaterial = _material.physicallyBased(); - var material = extractProperties( _material ); + let material = extractProperties( _material ); - var textures = []; + const textures = []; - for ( var j = 0; j < textureTypes.length; j ++ ) { + for ( let j = 0; j < textureTypes.length; j ++ ) { - var _texture = _material.getTexture( textureTypes[ j ] ); + const _texture = _material.getTexture( textureTypes[ j ] ); if ( _texture ) { - var textureType = textureTypes[ j ].constructor.name; + let textureType = textureTypes[ j ].constructor.name; textureType = textureType.substring( 12, textureType.length ); - var texture = { type: textureType }; + const texture = { type: textureType }; - var image = doc.getEmbeddedFileAsBase64( _texture.fileName ); + const image = doc.getEmbeddedFileAsBase64( _texture.fileName ); if ( image ) { @@ -945,15 +946,15 @@ Rhino3dmLoader.Rhino3dmWorker = function () { console.log( 'pbr true' ); - for ( var j = 0; j < pbrTextureTypes.length; j ++ ) { + for ( let j = 0; j < pbrTextureTypes.length; j ++ ) { - var _texture = _material.getTexture( textureTypes[ j ] ); + const _texture = _material.getTexture( textureTypes[ j ] ); if ( _texture ) { - var image = doc.getEmbeddedFileAsBase64( _texture.fileName ); - var textureType = textureTypes[ j ].constructor.name; + const image = doc.getEmbeddedFileAsBase64( _texture.fileName ); + let textureType = textureTypes[ j ].constructor.name; textureType = textureType.substring( 12, textureType.length ); - var texture = { type: textureType, image: 'data:image/png;base64,' + image }; + const texture = { type: textureType, image: 'data:image/png;base64,' + image }; textures.push( texture ); _texture.delete(); @@ -962,7 +963,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { } - var pbMaterialProperties = extractProperties( _material.physicallyBased() ); + const pbMaterialProperties = extractProperties( _material.physicallyBased() ); material = Object.assign( pbMaterialProperties, material ); @@ -977,10 +978,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle layers - for ( var i = 0; i < doc.layers().count(); i ++ ) { + for ( let i = 0; i < doc.layers().count(); i ++ ) { - var _layer = doc.layers().get( i ); - var layer = extractProperties( _layer ); + const _layer = doc.layers().get( i ); + const layer = extractProperties( _layer ); layers.push( layer ); @@ -990,10 +991,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle views - for ( var i = 0; i < doc.views().count(); i ++ ) { + for ( let i = 0; i < doc.views().count(); i ++ ) { - var _view = doc.views().get( i ); - var view = extractProperties( _view ); + const _view = doc.views().get( i ); + const view = extractProperties( _view ); views.push( view ); @@ -1003,10 +1004,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle named views - for ( var i = 0; i < doc.namedViews().count(); i ++ ) { + for ( let i = 0; i < doc.namedViews().count(); i ++ ) { - var _namedView = doc.namedViews().get( i ); - var namedView = extractProperties( _namedView ); + const _namedView = doc.namedViews().get( i ); + const namedView = extractProperties( _namedView ); namedViews.push( namedView ); @@ -1016,10 +1017,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle groups - for ( var i = 0; i < doc.groups().count(); i ++ ) { + for ( let i = 0; i < doc.groups().count(); i ++ ) { - var _group = doc.groups().get( i ); - var group = extractProperties( _group ); + const _group = doc.groups().get( i ); + const group = extractProperties( _group ); groups.push( group ); @@ -1029,7 +1030,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // Handle settings - var settings = extractProperties( doc.settings() ); + const settings = extractProperties( doc.settings() ); //TODO: Handle other document stuff like dimstyles, instance definitions, bitmaps etc. @@ -1065,11 +1066,10 @@ Rhino3dmLoader.Rhino3dmWorker = function () { function extractObjectData( object, doc ) { - var _geometry = object.geometry(); - var _attributes = object.attributes(); - var objectType = _geometry.objectType; - var geometry = null; - var attributes = null; + const _geometry = object.geometry(); + const _attributes = object.attributes(); + let objectType = _geometry.objectType; + let geometry, attributes, position, data, mesh; // skip instance definition objects //if( _attributes.isInstanceDefinitionObject ) { continue; } @@ -1079,17 +1079,17 @@ Rhino3dmLoader.Rhino3dmWorker = function () { case rhino.ObjectType.Curve: - var pts = curveToPoints( _geometry, 100 ); + const pts = curveToPoints( _geometry, 100 ); - var position = {}; - var attributes = {}; - var data = {}; + position = {}; + attributes = {}; + data = {}; position.itemSize = 3; position.type = 'Float32Array'; position.array = []; - for ( var j = 0; j < pts.length; j ++ ) { + for ( let j = 0; j < pts.length; j ++ ) { position.array.push( pts[ j ][ 0 ] ); position.array.push( pts[ j ][ 1 ] ); @@ -1106,18 +1106,18 @@ Rhino3dmLoader.Rhino3dmWorker = function () { case rhino.ObjectType.Point: - var pt = _geometry.location; + const pt = _geometry.location; - var position = {}; - var color = {}; - var attributes = {}; - var data = {}; + position = {}; + const color = {}; + attributes = {}; + data = {}; position.itemSize = 3; position.type = 'Float32Array'; position.array = [ pt[ 0 ], pt[ 1 ], pt[ 2 ] ]; - var _color = _attributes.drawColor( doc ); + const _color = _attributes.drawColor( doc ); color.itemSize = 3; color.type = 'Float32Array'; @@ -1140,13 +1140,13 @@ Rhino3dmLoader.Rhino3dmWorker = function () { case rhino.ObjectType.Brep: - var faces = _geometry.faces(); - var mesh = new rhino.Mesh(); + const faces = _geometry.faces(); + mesh = new rhino.Mesh(); - for ( var faceIndex = 0; faceIndex < faces.count; faceIndex ++ ) { + for ( let faceIndex = 0; faceIndex < faces.count; faceIndex ++ ) { - var face = faces.get( faceIndex ); - var _mesh = face.getMesh( rhino.MeshType.Any ); + const face = faces.get( faceIndex ); + const _mesh = face.getMesh( rhino.MeshType.Any ); if ( _mesh ) { @@ -1173,7 +1173,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { case rhino.ObjectType.Extrusion: - var mesh = _geometry.getMesh( rhino.MeshType.Any ); + mesh = _geometry.getMesh( rhino.MeshType.Any ); if ( mesh ) { @@ -1208,7 +1208,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { // TODO: precalculate resulting vertices and faces and warn on excessive results _geometry.subdivide( 3 ); - var mesh = rhino.Mesh.createFromSubDControlNet( _geometry ); + mesh = rhino.Mesh.createFromSubDControlNet( _geometry ); if ( mesh ) { geometry = mesh.toThreejsJSON(); @@ -1232,7 +1232,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { if ( geometry ) { - var attributes = extractProperties( _attributes ); + attributes = extractProperties( _attributes ); attributes.geometry = extractProperties( _geometry ); if ( _attributes.groupCount > 0 ) { @@ -1270,11 +1270,11 @@ Rhino3dmLoader.Rhino3dmWorker = function () { function extractProperties( object ) { - var result = {}; + const result = {}; - for ( var property in object ) { + for ( const property in object ) { - var value = object[ property ]; + const value = object[ property ]; if ( typeof value !== 'function' ) { @@ -1303,9 +1303,9 @@ Rhino3dmLoader.Rhino3dmWorker = function () { function curveToPoints( curve, pointLimit ) { - var pointCount = pointLimit; - var rc = []; - var ts = []; + let pointCount = pointLimit; + let rc = []; + const ts = []; if ( curve instanceof rhino.LineCurve ) { @@ -1316,7 +1316,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { if ( curve instanceof rhino.PolylineCurve ) { pointCount = curve.pointCount; - for ( var i = 0; i < pointCount; i ++ ) { + for ( let i = 0; i < pointCount; i ++ ) { rc.push( curve.point( i ) ); @@ -1328,12 +1328,12 @@ Rhino3dmLoader.Rhino3dmWorker = function () { if ( curve instanceof rhino.PolyCurve ) { - var segmentCount = curve.segmentCount; + const segmentCount = curve.segmentCount; - for ( var i = 0; i < segmentCount; i ++ ) { + for ( let i = 0; i < segmentCount; i ++ ) { - var segment = curve.segmentCurve( i ); - var segmentArray = curveToPoints( segment, pointCount ); + const segment = curve.segmentCurve( i ); + const segmentArray = curveToPoints( segment, pointCount ); rc = rc.concat( segmentArray ); segment.delete(); @@ -1355,7 +1355,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { const pLine = curve.tryGetPolyline(); - for ( var i = 0; i < pLine.count; i ++ ) { + for ( let i = 0; i < pLine.count; i ++ ) { rc.push( pLine.get( i ) ); @@ -1367,12 +1367,12 @@ Rhino3dmLoader.Rhino3dmWorker = function () { } - var domain = curve.domain; - var divisions = pointCount - 1.0; + const domain = curve.domain; + const divisions = pointCount - 1.0; - for ( var j = 0; j < pointCount; j ++ ) { + for ( let j = 0; j < pointCount; j ++ ) { - var t = domain[ 0 ] + ( j / divisions ) * ( domain[ 1 ] - domain[ 0 ] ); + const t = domain[ 0 ] + ( j / divisions ) * ( domain[ 1 ] - domain[ 0 ] ); if ( t === domain[ 0 ] || t === domain[ 1 ] ) { @@ -1381,18 +1381,18 @@ Rhino3dmLoader.Rhino3dmWorker = function () { } - var tan = curve.tangentAt( t ); - var prevTan = curve.tangentAt( ts.slice( - 1 )[ 0 ] ); + const tan = curve.tangentAt( t ); + const prevTan = curve.tangentAt( ts.slice( - 1 )[ 0 ] ); // Duplicated from THREE.Vector3 // How to pass imports to worker? - var tS = tan[ 0 ] * tan[ 0 ] + tan[ 1 ] * tan[ 1 ] + tan[ 2 ] * tan[ 2 ]; - var ptS = prevTan[ 0 ] * prevTan[ 0 ] + prevTan[ 1 ] * prevTan[ 1 ] + prevTan[ 2 ] * prevTan[ 2 ]; + const tS = tan[ 0 ] * tan[ 0 ] + tan[ 1 ] * tan[ 1 ] + tan[ 2 ] * tan[ 2 ]; + const ptS = prevTan[ 0 ] * prevTan[ 0 ] + prevTan[ 1 ] * prevTan[ 1 ] + prevTan[ 2 ] * prevTan[ 2 ]; - var denominator = Math.sqrt( tS * ptS ); + const denominator = Math.sqrt( tS * ptS ); - var angle; + let angle; if ( denominator === 0 ) { @@ -1400,7 +1400,7 @@ Rhino3dmLoader.Rhino3dmWorker = function () { } else { - var theta = ( tan.x * prevTan.x + tan.y * prevTan.y + tan.z * prevTan.z ) / denominator; + const theta = ( tan.x * prevTan.x + tan.y * prevTan.y + tan.z * prevTan.z ) / denominator; angle = Math.acos( Math.max( - 1, Math.min( 1, theta ) ) ); } @@ -1416,6 +1416,6 @@ Rhino3dmLoader.Rhino3dmWorker = function () { } -}; +} export { Rhino3dmLoader }; diff --git a/examples/jsm/loaders/3MFLoader.js b/examples/jsm/loaders/3MFLoader.js index 7fda0036e62ae8..cc18f70a9106c0 100644 --- a/examples/jsm/loaders/3MFLoader.js +++ b/examples/jsm/loaders/3MFLoader.js @@ -20,7 +20,7 @@ import { TextureLoader, sRGBEncoding } from '../../../build/three.module.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; /** * @@ -40,22 +40,20 @@ import * as fflate from '../libs/fflate.module.min.js'; * - Metallic Display Properties (PBR) */ -var ThreeMFLoader = function ( manager ) { +class ThreeMFLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.availableExtensions = []; + super( manager ); -}; + this.availableExtensions = []; -ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: ThreeMFLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; - var loader = new FileLoader( scope.manager ); + const scope = this; + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -84,31 +82,30 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { - var scope = this; - var textureLoader = new TextureLoader( this.manager ); + const scope = this; + const textureLoader = new TextureLoader( this.manager ); function loadDocument( data ) { - var zip = null; - var file = null; + let zip = null; + let file = null; - var relsName; - var modelRelsName; - var modelPartNames = []; - var printTicketPartNames = []; - var texturesPartNames = []; - var otherPartNames = []; + let relsName; + let modelRelsName; + const modelPartNames = []; + const printTicketPartNames = []; + const texturesPartNames = []; + const otherPartNames = []; - var rels; - var modelRels; - var modelParts = {}; - var printTicketParts = {}; - var texturesParts = {}; - var otherParts = {}; + let modelRels; + const modelParts = {}; + const printTicketParts = {}; + const texturesParts = {}; + const otherParts = {}; try { @@ -157,29 +154,29 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var relsView = zip[ relsName ]; - var relsFileText = LoaderUtils.decodeText( relsView ); - rels = parseRelsXml( relsFileText ); + const relsView = zip[ relsName ]; + const relsFileText = LoaderUtils.decodeText( relsView ); + const rels = parseRelsXml( relsFileText ); // if ( modelRelsName ) { - var relsView = zip[ modelRelsName ]; - var relsFileText = LoaderUtils.decodeText( relsView ); + const relsView = zip[ modelRelsName ]; + const relsFileText = LoaderUtils.decodeText( relsView ); modelRels = parseRelsXml( relsFileText ); } // - for ( var i = 0; i < modelPartNames.length; i ++ ) { + for ( let i = 0; i < modelPartNames.length; i ++ ) { - var modelPart = modelPartNames[ i ]; - var view = zip[ modelPart ]; + const modelPart = modelPartNames[ i ]; + const view = zip[ modelPart ]; - var fileText = LoaderUtils.decodeText( view ); - var xmlData = new DOMParser().parseFromString( fileText, 'application/xml' ); + const fileText = LoaderUtils.decodeText( view ); + const xmlData = new DOMParser().parseFromString( fileText, 'application/xml' ); if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) { @@ -187,12 +184,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var modelNode = xmlData.querySelector( 'model' ); - var extensions = {}; + const modelNode = xmlData.querySelector( 'model' ); + const extensions = {}; - for ( var i = 0; i < modelNode.attributes.length; i ++ ) { + for ( let i = 0; i < modelNode.attributes.length; i ++ ) { - var attr = modelNode.attributes[ i ]; + const attr = modelNode.attributes[ i ]; if ( attr.name.match( /^xmlns:(.+)$/ ) ) { extensions[ attr.value ] = RegExp.$1; @@ -201,7 +198,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var modelData = parseModelNode( modelNode ); + const modelData = parseModelNode( modelNode ); modelData[ 'xml' ] = modelNode; if ( 0 < Object.keys( extensions ).length ) { @@ -216,9 +213,9 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - for ( var i = 0; i < texturesPartNames.length; i ++ ) { + for ( let i = 0; i < texturesPartNames.length; i ++ ) { - var texturesPartName = texturesPartNames[ i ]; + const texturesPartName = texturesPartNames[ i ]; texturesParts[ texturesPartName ] = zip[ texturesPartName ].buffer; } @@ -236,17 +233,17 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseRelsXml( relsFileText ) { - var relationships = []; + const relationships = []; - var relsXmlData = new DOMParser().parseFromString( relsFileText, 'application/xml' ); + const relsXmlData = new DOMParser().parseFromString( relsFileText, 'application/xml' ); - var relsNodes = relsXmlData.querySelectorAll( 'Relationship' ); + const relsNodes = relsXmlData.querySelectorAll( 'Relationship' ); - for ( var i = 0; i < relsNodes.length; i ++ ) { + for ( let i = 0; i < relsNodes.length; i ++ ) { - var relsNode = relsNodes[ i ]; + const relsNode = relsNodes[ i ]; - var relationship = { + const relationship = { target: relsNode.getAttribute( 'Target' ), //required id: relsNode.getAttribute( 'Id' ), //required type: relsNode.getAttribute( 'Type' ) //required @@ -262,13 +259,13 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseMetadataNodes( metadataNodes ) { - var metadataData = {}; + const metadataData = {}; - for ( var i = 0; i < metadataNodes.length; i ++ ) { + for ( let i = 0; i < metadataNodes.length; i ++ ) { - var metadataNode = metadataNodes[ i ]; - var name = metadataNode.getAttribute( 'name' ); - var validNames = [ + const metadataNode = metadataNodes[ i ]; + const name = metadataNode.getAttribute( 'name' ); + const validNames = [ 'Title', 'Designer', 'Description', @@ -293,17 +290,17 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseBasematerialsNode( basematerialsNode ) { - var basematerialsData = { + const basematerialsData = { id: basematerialsNode.getAttribute( 'id' ), // required basematerials: [] }; - var basematerialNodes = basematerialsNode.querySelectorAll( 'base' ); + const basematerialNodes = basematerialsNode.querySelectorAll( 'base' ); - for ( var i = 0; i < basematerialNodes.length; i ++ ) { + for ( let i = 0; i < basematerialNodes.length; i ++ ) { - var basematerialNode = basematerialNodes[ i ]; - var basematerialData = parseBasematerialNode( basematerialNode ); + const basematerialNode = basematerialNodes[ i ]; + const basematerialData = parseBasematerialNode( basematerialNode ); basematerialData.index = i; // the order and count of the material nodes form an implicit 0-based index basematerialsData.basematerials.push( basematerialData ); @@ -315,7 +312,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseTexture2DNode( texture2DNode ) { - var texture2dData = { + const texture2dData = { id: texture2DNode.getAttribute( 'id' ), // required path: texture2DNode.getAttribute( 'path' ), // required contenttype: texture2DNode.getAttribute( 'contenttype' ), // required @@ -330,21 +327,21 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseTextures2DGroupNode( texture2DGroupNode ) { - var texture2DGroupData = { + const texture2DGroupData = { id: texture2DGroupNode.getAttribute( 'id' ), // required texid: texture2DGroupNode.getAttribute( 'texid' ), // required displaypropertiesid: texture2DGroupNode.getAttribute( 'displaypropertiesid' ) }; - var tex2coordNodes = texture2DGroupNode.querySelectorAll( 'tex2coord' ); + const tex2coordNodes = texture2DGroupNode.querySelectorAll( 'tex2coord' ); - var uvs = []; + const uvs = []; - for ( var i = 0; i < tex2coordNodes.length; i ++ ) { + for ( let i = 0; i < tex2coordNodes.length; i ++ ) { - var tex2coordNode = tex2coordNodes[ i ]; - var u = tex2coordNode.getAttribute( 'u' ); - var v = tex2coordNode.getAttribute( 'v' ); + const tex2coordNode = tex2coordNodes[ i ]; + const u = tex2coordNode.getAttribute( 'u' ); + const v = tex2coordNode.getAttribute( 'v' ); uvs.push( parseFloat( u ), parseFloat( v ) ); @@ -358,20 +355,20 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseColorGroupNode( colorGroupNode ) { - var colorGroupData = { + const colorGroupData = { id: colorGroupNode.getAttribute( 'id' ), // required displaypropertiesid: colorGroupNode.getAttribute( 'displaypropertiesid' ) }; - var colorNodes = colorGroupNode.querySelectorAll( 'color' ); + const colorNodes = colorGroupNode.querySelectorAll( 'color' ); - var colors = []; - var colorObject = new Color(); + const colors = []; + const colorObject = new Color(); - for ( var i = 0; i < colorNodes.length; i ++ ) { + for ( let i = 0; i < colorNodes.length; i ++ ) { - var colorNode = colorNodes[ i ]; - var color = colorNode.getAttribute( 'color' ); + const colorNode = colorNodes[ i ]; + const color = colorNode.getAttribute( 'color' ); colorObject.setStyle( color.substring( 0, 7 ) ); colorObject.convertSRGBToLinear(); // color is in sRGB @@ -388,17 +385,17 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseMetallicDisplaypropertiesNode( metallicDisplaypropetiesNode ) { - var metallicDisplaypropertiesData = { + const metallicDisplaypropertiesData = { id: metallicDisplaypropetiesNode.getAttribute( 'id' ) // required }; - var metallicNodes = metallicDisplaypropetiesNode.querySelectorAll( 'pbmetallic' ); + const metallicNodes = metallicDisplaypropetiesNode.querySelectorAll( 'pbmetallic' ); - var metallicData = []; + const metallicData = []; - for ( var i = 0; i < metallicNodes.length; i ++ ) { + for ( let i = 0; i < metallicNodes.length; i ++ ) { - var metallicNode = metallicNodes[ i ]; + const metallicNode = metallicNodes[ i ]; metallicData.push( { name: metallicNode.getAttribute( 'name' ), // required @@ -416,7 +413,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseBasematerialNode( basematerialNode ) { - var basematerialData = {}; + const basematerialData = {}; basematerialData[ 'name' ] = basematerialNode.getAttribute( 'name' ); // required basematerialData[ 'displaycolor' ] = basematerialNode.getAttribute( 'displaycolor' ); // required @@ -428,17 +425,17 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseMeshNode( meshNode ) { - var meshData = {}; + const meshData = {}; - var vertices = []; - var vertexNodes = meshNode.querySelectorAll( 'vertices vertex' ); + const vertices = []; + const vertexNodes = meshNode.querySelectorAll( 'vertices vertex' ); - for ( var i = 0; i < vertexNodes.length; i ++ ) { + for ( let i = 0; i < vertexNodes.length; i ++ ) { - var vertexNode = vertexNodes[ i ]; - var x = vertexNode.getAttribute( 'x' ); - var y = vertexNode.getAttribute( 'y' ); - var z = vertexNode.getAttribute( 'z' ); + const vertexNode = vertexNodes[ i ]; + const x = vertexNode.getAttribute( 'x' ); + const y = vertexNode.getAttribute( 'y' ); + const z = vertexNode.getAttribute( 'z' ); vertices.push( parseFloat( x ), parseFloat( y ), parseFloat( z ) ); @@ -446,22 +443,22 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { meshData[ 'vertices' ] = new Float32Array( vertices ); - var triangleProperties = []; - var triangles = []; - var triangleNodes = meshNode.querySelectorAll( 'triangles triangle' ); + const triangleProperties = []; + const triangles = []; + const triangleNodes = meshNode.querySelectorAll( 'triangles triangle' ); - for ( var i = 0; i < triangleNodes.length; i ++ ) { + for ( let i = 0; i < triangleNodes.length; i ++ ) { - var triangleNode = triangleNodes[ i ]; - var v1 = triangleNode.getAttribute( 'v1' ); - var v2 = triangleNode.getAttribute( 'v2' ); - var v3 = triangleNode.getAttribute( 'v3' ); - var p1 = triangleNode.getAttribute( 'p1' ); - var p2 = triangleNode.getAttribute( 'p2' ); - var p3 = triangleNode.getAttribute( 'p3' ); - var pid = triangleNode.getAttribute( 'pid' ); + const triangleNode = triangleNodes[ i ]; + const v1 = triangleNode.getAttribute( 'v1' ); + const v2 = triangleNode.getAttribute( 'v2' ); + const v3 = triangleNode.getAttribute( 'v3' ); + const p1 = triangleNode.getAttribute( 'p1' ); + const p2 = triangleNode.getAttribute( 'p2' ); + const p3 = triangleNode.getAttribute( 'p3' ); + const pid = triangleNode.getAttribute( 'pid' ); - var triangleProperty = {}; + const triangleProperty = {}; triangleProperty[ 'v1' ] = parseInt( v1, 10 ); triangleProperty[ 'v2' ] = parseInt( v2, 10 ); @@ -512,14 +509,14 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseComponentsNode( componentsNode ) { - var components = []; + const components = []; - var componentNodes = componentsNode.querySelectorAll( 'component' ); + const componentNodes = componentsNode.querySelectorAll( 'component' ); - for ( var i = 0; i < componentNodes.length; i ++ ) { + for ( let i = 0; i < componentNodes.length; i ++ ) { - var componentNode = componentNodes[ i ]; - var componentData = parseComponentNode( componentNode ); + const componentNode = componentNodes[ i ]; + const componentData = parseComponentNode( componentNode ); components.push( componentData ); } @@ -530,11 +527,11 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseComponentNode( componentNode ) { - var componentData = {}; + const componentData = {}; componentData[ 'objectId' ] = componentNode.getAttribute( 'objectid' ); // required - var transform = componentNode.getAttribute( 'transform' ); + const transform = componentNode.getAttribute( 'transform' ); if ( transform ) { @@ -548,14 +545,14 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseTransform( transform ) { - var t = []; + const t = []; transform.split( ' ' ).forEach( function ( s ) { t.push( parseFloat( s ) ); } ); - var matrix = new Matrix4(); + const matrix = new Matrix4(); matrix.set( t[ 0 ], t[ 3 ], t[ 6 ], t[ 9 ], t[ 1 ], t[ 4 ], t[ 7 ], t[ 10 ], @@ -569,11 +566,11 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseObjectNode( objectNode ) { - var objectData = { + const objectData = { type: objectNode.getAttribute( 'type' ) }; - var id = objectNode.getAttribute( 'id' ); + const id = objectNode.getAttribute( 'id' ); if ( id ) { @@ -581,7 +578,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var pid = objectNode.getAttribute( 'pid' ); + const pid = objectNode.getAttribute( 'pid' ); if ( pid ) { @@ -589,7 +586,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var pindex = objectNode.getAttribute( 'pindex' ); + const pindex = objectNode.getAttribute( 'pindex' ); if ( pindex ) { @@ -597,7 +594,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var thumbnail = objectNode.getAttribute( 'thumbnail' ); + const thumbnail = objectNode.getAttribute( 'thumbnail' ); if ( thumbnail ) { @@ -605,7 +602,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var partnumber = objectNode.getAttribute( 'partnumber' ); + const partnumber = objectNode.getAttribute( 'partnumber' ); if ( partnumber ) { @@ -613,7 +610,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var name = objectNode.getAttribute( 'name' ); + const name = objectNode.getAttribute( 'name' ); if ( name ) { @@ -621,7 +618,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var meshNode = objectNode.querySelector( 'mesh' ); + const meshNode = objectNode.querySelector( 'mesh' ); if ( meshNode ) { @@ -629,7 +626,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var componentsNode = objectNode.querySelector( 'components' ); + const componentsNode = objectNode.querySelector( 'components' ); if ( componentsNode ) { @@ -643,15 +640,15 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseResourcesNode( resourcesNode ) { - var resourcesData = {}; + const resourcesData = {}; resourcesData[ 'basematerials' ] = {}; - var basematerialsNodes = resourcesNode.querySelectorAll( 'basematerials' ); + const basematerialsNodes = resourcesNode.querySelectorAll( 'basematerials' ); - for ( var i = 0; i < basematerialsNodes.length; i ++ ) { + for ( let i = 0; i < basematerialsNodes.length; i ++ ) { - var basematerialsNode = basematerialsNodes[ i ]; - var basematerialsData = parseBasematerialsNode( basematerialsNode ); + const basematerialsNode = basematerialsNodes[ i ]; + const basematerialsData = parseBasematerialsNode( basematerialsNode ); resourcesData[ 'basematerials' ][ basematerialsData[ 'id' ] ] = basematerialsData; } @@ -659,12 +656,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // resourcesData[ 'texture2d' ] = {}; - var textures2DNodes = resourcesNode.querySelectorAll( 'texture2d' ); + const textures2DNodes = resourcesNode.querySelectorAll( 'texture2d' ); - for ( var i = 0; i < textures2DNodes.length; i ++ ) { + for ( let i = 0; i < textures2DNodes.length; i ++ ) { - var textures2DNode = textures2DNodes[ i ]; - var texture2DData = parseTexture2DNode( textures2DNode ); + const textures2DNode = textures2DNodes[ i ]; + const texture2DData = parseTexture2DNode( textures2DNode ); resourcesData[ 'texture2d' ][ texture2DData[ 'id' ] ] = texture2DData; } @@ -672,12 +669,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // resourcesData[ 'colorgroup' ] = {}; - var colorGroupNodes = resourcesNode.querySelectorAll( 'colorgroup' ); + const colorGroupNodes = resourcesNode.querySelectorAll( 'colorgroup' ); - for ( var i = 0; i < colorGroupNodes.length; i ++ ) { + for ( let i = 0; i < colorGroupNodes.length; i ++ ) { - var colorGroupNode = colorGroupNodes[ i ]; - var colorGroupData = parseColorGroupNode( colorGroupNode ); + const colorGroupNode = colorGroupNodes[ i ]; + const colorGroupData = parseColorGroupNode( colorGroupNode ); resourcesData[ 'colorgroup' ][ colorGroupData[ 'id' ] ] = colorGroupData; } @@ -685,12 +682,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // resourcesData[ 'pbmetallicdisplayproperties' ] = {}; - var pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll( 'pbmetallicdisplayproperties' ); + const pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll( 'pbmetallicdisplayproperties' ); - for ( var i = 0; i < pbmetallicdisplaypropertiesNodes.length; i ++ ) { + for ( let i = 0; i < pbmetallicdisplaypropertiesNodes.length; i ++ ) { - var pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[ i ]; - var pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode( pbmetallicdisplaypropertiesNode ); + const pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[ i ]; + const pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode( pbmetallicdisplaypropertiesNode ); resourcesData[ 'pbmetallicdisplayproperties' ][ pbmetallicdisplaypropertiesData[ 'id' ] ] = pbmetallicdisplaypropertiesData; } @@ -698,12 +695,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // resourcesData[ 'texture2dgroup' ] = {}; - var textures2DGroupNodes = resourcesNode.querySelectorAll( 'texture2dgroup' ); + const textures2DGroupNodes = resourcesNode.querySelectorAll( 'texture2dgroup' ); - for ( var i = 0; i < textures2DGroupNodes.length; i ++ ) { + for ( let i = 0; i < textures2DGroupNodes.length; i ++ ) { - var textures2DGroupNode = textures2DGroupNodes[ i ]; - var textures2DGroupData = parseTextures2DGroupNode( textures2DGroupNode ); + const textures2DGroupNode = textures2DGroupNodes[ i ]; + const textures2DGroupData = parseTextures2DGroupNode( textures2DGroupNode ); resourcesData[ 'texture2dgroup' ][ textures2DGroupData[ 'id' ] ] = textures2DGroupData; } @@ -711,12 +708,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // resourcesData[ 'object' ] = {}; - var objectNodes = resourcesNode.querySelectorAll( 'object' ); + const objectNodes = resourcesNode.querySelectorAll( 'object' ); - for ( var i = 0; i < objectNodes.length; i ++ ) { + for ( let i = 0; i < objectNodes.length; i ++ ) { - var objectNode = objectNodes[ i ]; - var objectData = parseObjectNode( objectNode ); + const objectNode = objectNodes[ i ]; + const objectData = parseObjectNode( objectNode ); resourcesData[ 'object' ][ objectData[ 'id' ] ] = objectData; } @@ -727,16 +724,16 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseBuildNode( buildNode ) { - var buildData = []; - var itemNodes = buildNode.querySelectorAll( 'item' ); + const buildData = []; + const itemNodes = buildNode.querySelectorAll( 'item' ); - for ( var i = 0; i < itemNodes.length; i ++ ) { + for ( let i = 0; i < itemNodes.length; i ++ ) { - var itemNode = itemNodes[ i ]; - var buildItem = { + const itemNode = itemNodes[ i ]; + const buildItem = { objectId: itemNode.getAttribute( 'objectid' ) }; - var transform = itemNode.getAttribute( 'transform' ); + const transform = itemNode.getAttribute( 'transform' ); if ( transform ) { @@ -754,8 +751,8 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseModelNode( modelNode ) { - var modelData = { unit: modelNode.getAttribute( 'unit' ) || 'millimeter' }; - var metadataNodes = modelNode.querySelectorAll( 'metadata' ); + const modelData = { unit: modelNode.getAttribute( 'unit' ) || 'millimeter' }; + const metadataNodes = modelNode.querySelectorAll( 'metadata' ); if ( metadataNodes ) { @@ -763,7 +760,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var resourcesNode = modelNode.querySelector( 'resources' ); + const resourcesNode = modelNode.querySelector( 'resources' ); if ( resourcesNode ) { @@ -771,7 +768,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var buildNode = modelNode.querySelector( 'build' ); + const buildNode = modelNode.querySelector( 'build' ); if ( buildNode ) { @@ -785,19 +782,19 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildTexture( texture2dgroup, objects, modelData, textureData ) { - var texid = texture2dgroup.texid; - var texture2ds = modelData.resources.texture2d; - var texture2d = texture2ds[ texid ]; + const texid = texture2dgroup.texid; + const texture2ds = modelData.resources.texture2d; + const texture2d = texture2ds[ texid ]; if ( texture2d ) { - var data = textureData[ texture2d.path ]; - var type = texture2d.contenttype; + const data = textureData[ texture2d.path ]; + const type = texture2d.contenttype; - var blob = new Blob( [ data ], { type: type } ); - var sourceURI = URL.createObjectURL( blob ); + const blob = new Blob( [ data ], { type: type } ); + const sourceURI = URL.createObjectURL( blob ); - var texture = textureLoader.load( sourceURI, function () { + const texture = textureLoader.load( sourceURI, function () { URL.revokeObjectURL( sourceURI ); @@ -880,16 +877,16 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - function buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData ) { + function buildBasematerialsMeshes( basematerials, triangleProperties, meshData, objects, modelData, textureData, objectData ) { - var objectPindex = objectData.pindex; + const objectPindex = objectData.pindex; - var materialMap = {}; + const materialMap = {}; - for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) { + for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { - var triangleProperty = triangleProperties[ i ]; - var pindex = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectPindex; + const triangleProperty = triangleProperties[ i ]; + const pindex = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectPindex; if ( materialMap[ pindex ] === undefined ) materialMap[ pindex ] = []; @@ -899,27 +896,27 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var keys = Object.keys( materialMap ); - var meshes = []; + const keys = Object.keys( materialMap ); + const meshes = []; - for ( var i = 0, l = keys.length; i < l; i ++ ) { + for ( let i = 0, l = keys.length; i < l; i ++ ) { - var materialIndex = keys[ i ]; - var trianglePropertiesProps = materialMap[ materialIndex ]; - var basematerialData = basematerials.basematerials[ materialIndex ]; - var material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial ); + const materialIndex = keys[ i ]; + const trianglePropertiesProps = materialMap[ materialIndex ]; + const basematerialData = basematerials.basematerials[ materialIndex ]; + const material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial ); // - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); - var positionData = []; + const positionData = []; - var vertices = meshData.vertices; + const vertices = meshData.vertices; - for ( var j = 0, jl = trianglePropertiesProps.length; j < jl; j ++ ) { + for ( let j = 0, jl = trianglePropertiesProps.length; j < jl; j ++ ) { - var triangleProperty = trianglePropertiesProps[ j ]; + const triangleProperty = trianglePropertiesProps[ j ]; positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] ); positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] ); @@ -940,7 +937,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var mesh = new Mesh( geometry, material ); + const mesh = new Mesh( geometry, material ); meshes.push( mesh ); } @@ -949,21 +946,21 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - function buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData, objectData ) { + function buildTexturedMesh( texture2dgroup, triangleProperties, meshData, objects, modelData, textureData, objectData ) { // geometry - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); - var positionData = []; - var uvData = []; + const positionData = []; + const uvData = []; - var vertices = meshData.vertices; - var uvs = texture2dgroup.uvs; + const vertices = meshData.vertices; + const uvs = texture2dgroup.uvs; - for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) { + for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { - var triangleProperty = triangleProperties[ i ]; + const triangleProperty = triangleProperties[ i ]; positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] ); positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] ); @@ -995,37 +992,37 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // material - var texture = getBuild( texture2dgroup, objects, modelData, textureData, objectData, buildTexture ); + const texture = getBuild( texture2dgroup, objects, modelData, textureData, objectData, buildTexture ); - var material = new MeshPhongMaterial( { map: texture, flatShading: true } ); + const material = new MeshPhongMaterial( { map: texture, flatShading: true } ); // mesh - var mesh = new Mesh( geometry, material ); + const mesh = new Mesh( geometry, material ); return mesh; } - function buildVertexColorMesh( colorgroup, triangleProperties, modelData, meshData, objectData ) { + function buildVertexColorMesh( colorgroup, triangleProperties, meshData, objects, modelData, objectData ) { // geometry - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); - var positionData = []; - var colorData = []; + const positionData = []; + const colorData = []; - var vertices = meshData.vertices; - var colors = colorgroup.colors; + const vertices = meshData.vertices; + const colors = colorgroup.colors; - for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) { + for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { - var triangleProperty = triangleProperties[ i ]; + const triangleProperty = triangleProperties[ i ]; - var v1 = triangleProperty.v1; - var v2 = triangleProperty.v2; - var v3 = triangleProperty.v3; + const v1 = triangleProperty.v1; + const v2 = triangleProperty.v2; + const v3 = triangleProperty.v3; positionData.push( vertices[ ( v1 * 3 ) + 0 ] ); positionData.push( vertices[ ( v1 * 3 ) + 1 ] ); @@ -1041,9 +1038,9 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var p1 = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectData.pindex; - var p2 = ( triangleProperty.p2 !== undefined ) ? triangleProperty.p2 : p1; - var p3 = ( triangleProperty.p3 !== undefined ) ? triangleProperty.p3 : p1; + const p1 = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectData.pindex; + const p2 = ( triangleProperty.p2 !== undefined ) ? triangleProperty.p2 : p1; + const p3 = ( triangleProperty.p3 !== undefined ) ? triangleProperty.p3 : p1; colorData.push( colors[ ( p1 * 3 ) + 0 ] ); colorData.push( colors[ ( p1 * 3 ) + 1 ] ); @@ -1064,11 +1061,11 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // material - var material = new MeshPhongMaterial( { vertexColors: true, flatShading: true } ); + const material = new MeshPhongMaterial( { vertexColors: true, flatShading: true } ); // mesh - var mesh = new Mesh( geometry, material ); + const mesh = new Mesh( geometry, material ); return mesh; @@ -1076,36 +1073,36 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildDefaultMesh( meshData ) { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setIndex( new BufferAttribute( meshData[ 'triangles' ], 1 ) ); geometry.setAttribute( 'position', new BufferAttribute( meshData[ 'vertices' ], 3 ) ); - var material = new MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } ); + const material = new MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } ); - var mesh = new Mesh( geometry, material ); + const mesh = new Mesh( geometry, material ); return mesh; } - function buildMeshes( resourceMap, modelData, meshData, textureData, objectData ) { + function buildMeshes( resourceMap, meshData, objects, modelData, textureData, objectData ) { - var keys = Object.keys( resourceMap ); - var meshes = []; + const keys = Object.keys( resourceMap ); + const meshes = []; - for ( var i = 0, il = keys.length; i < il; i ++ ) { + for ( let i = 0, il = keys.length; i < il; i ++ ) { - var resourceId = keys[ i ]; - var triangleProperties = resourceMap[ resourceId ]; - var resourceType = getResourceType( resourceId, modelData ); + const resourceId = keys[ i ]; + const triangleProperties = resourceMap[ resourceId ]; + const resourceType = getResourceType( resourceId, modelData ); switch ( resourceType ) { case 'material': - var basematerials = modelData.resources.basematerials[ resourceId ]; - var newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData ); + const basematerials = modelData.resources.basematerials[ resourceId ]; + const newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, meshData, objects, modelData, textureData, objectData ); - for ( var j = 0, jl = newMeshes.length; j < jl; j ++ ) { + for ( let j = 0, jl = newMeshes.length; j < jl; j ++ ) { meshes.push( newMeshes[ j ] ); @@ -1114,13 +1111,13 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'texture': - var texture2dgroup = modelData.resources.texture2dgroup[ resourceId ]; - meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData, objectData ) ); + const texture2dgroup = modelData.resources.texture2dgroup[ resourceId ]; + meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, meshData, objects, modelData, textureData, objectData ) ); break; case 'vertexColors': - var colorgroup = modelData.resources.colorgroup[ resourceId ]; - meshes.push( buildVertexColorMesh( colorgroup, triangleProperties, modelData, meshData, objectData ) ); + const colorgroup = modelData.resources.colorgroup[ resourceId ]; + meshes.push( buildVertexColorMesh( colorgroup, triangleProperties, meshData, objects, modelData, objectData ) ); break; case 'default': @@ -1166,16 +1163,16 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function analyzeObject( modelData, meshData, objectData ) { - var resourceMap = {}; + const resourceMap = {}; - var triangleProperties = meshData[ 'triangleProperties' ]; + const triangleProperties = meshData[ 'triangleProperties' ]; - var objectPid = objectData.pid; + const objectPid = objectData.pid; - for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) { + for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) { - var triangleProperty = triangleProperties[ i ]; - var pid = ( triangleProperty.pid !== undefined ) ? triangleProperty.pid : objectPid; + const triangleProperty = triangleProperties[ i ]; + let pid = ( triangleProperty.pid !== undefined ) ? triangleProperty.pid : objectPid; if ( pid === undefined ) pid = 'default'; @@ -1191,12 +1188,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildGroup( meshData, objects, modelData, textureData, objectData ) { - var group = new Group(); + const group = new Group(); - var resourceMap = analyzeObject( modelData, meshData, objectData ); - var meshes = buildMeshes( resourceMap, modelData, meshData, textureData, objectData ); + const resourceMap = analyzeObject( modelData, meshData, objectData ); + const meshes = buildMeshes( resourceMap, meshData, objects, modelData, textureData, objectData ); - for ( var i = 0, l = meshes.length; i < l; i ++ ) { + for ( let i = 0, l = meshes.length; i < l; i ++ ) { group.add( meshes[ i ] ); @@ -1214,16 +1211,16 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var availableExtensions = []; - var keys = Object.keys( extensions ); + const availableExtensions = []; + const keys = Object.keys( extensions ); - for ( var i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length; i ++ ) { - var ns = keys[ i ]; + const ns = keys[ i ]; - for ( var j = 0; j < scope.availableExtensions.length; j ++ ) { + for ( let j = 0; j < scope.availableExtensions.length; j ++ ) { - var extension = scope.availableExtensions[ j ]; + const extension = scope.availableExtensions[ j ]; if ( extension.ns === ns ) { @@ -1235,9 +1232,9 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - for ( var i = 0; i < availableExtensions.length; i ++ ) { + for ( let i = 0; i < availableExtensions.length; i ++ ) { - var extension = availableExtensions[ i ]; + const extension = availableExtensions[ i ]; extension.apply( modelXml, extensions[ extension[ 'ns' ] ], meshData ); } @@ -1256,17 +1253,17 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildBasematerial( materialData, objects, modelData ) { - var material; + let material; - var displaypropertiesid = materialData.displaypropertiesid; - var pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties; + const displaypropertiesid = materialData.displaypropertiesid; + const pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties; if ( displaypropertiesid !== null && pbmetallicdisplayproperties[ displaypropertiesid ] !== undefined ) { // metallic display property, use StandardMaterial - var pbmetallicdisplayproperty = pbmetallicdisplayproperties[ displaypropertiesid ]; - var metallicData = pbmetallicdisplayproperty.data[ materialData.index ]; + const pbmetallicdisplayproperty = pbmetallicdisplayproperties[ displaypropertiesid ]; + const metallicData = pbmetallicdisplayproperty.data[ materialData.index ]; material = new MeshStandardMaterial( { flatShading: true, roughness: metallicData.roughness, metalness: metallicData.metallicness } ); @@ -1282,9 +1279,9 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // displaycolor MUST be specified with a value of a 6 or 8 digit hexadecimal number, e.g. "#RRGGBB" or "#RRGGBBAA" - var displaycolor = materialData.displaycolor; + const displaycolor = materialData.displaycolor; - var color = displaycolor.substring( 0, 7 ); + const color = displaycolor.substring( 0, 7 ); material.color.setStyle( color ); material.color.convertSRGBToLinear(); // displaycolor is in sRGB @@ -1302,12 +1299,12 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildComposite( compositeData, objects, modelData, textureData ) { - var composite = new Group(); + const composite = new Group(); - for ( var j = 0; j < compositeData.length; j ++ ) { + for ( let j = 0; j < compositeData.length; j ++ ) { - var component = compositeData[ j ]; - var build = objects[ component.objectId ]; + const component = compositeData[ j ]; + let build = objects[ component.objectId ]; if ( build === undefined ) { @@ -1316,11 +1313,11 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var object3D = build.clone(); + const object3D = build.clone(); // apply component transform - var transform = component.transform; + const transform = component.transform; if ( transform ) { @@ -1338,14 +1335,14 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildObject( objectId, objects, modelData, textureData ) { - var objectData = modelData[ 'resources' ][ 'object' ][ objectId ]; + const objectData = modelData[ 'resources' ][ 'object' ][ objectId ]; if ( objectData[ 'mesh' ] ) { - var meshData = objectData[ 'mesh' ]; + const meshData = objectData[ 'mesh' ]; - var extensions = modelData[ 'extensions' ]; - var modelXml = modelData[ 'xml' ]; + const extensions = modelData[ 'extensions' ]; + const modelXml = modelData[ 'xml' ]; applyExtensions( extensions, meshData, modelXml ); @@ -1353,7 +1350,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else { - var compositeData = objectData[ 'components' ]; + const compositeData = objectData[ 'components' ]; objects[ objectData.id ] = getBuild( compositeData, objects, modelData, textureData, objectData, buildComposite ); @@ -1363,20 +1360,20 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildObjects( data3mf ) { - var modelsData = data3mf.model; - var modelRels = data3mf.modelRels; - var objects = {}; - var modelsKeys = Object.keys( modelsData ); - var textureData = {}; + const modelsData = data3mf.model; + const modelRels = data3mf.modelRels; + const objects = {}; + const modelsKeys = Object.keys( modelsData ); + const textureData = {}; // evaluate model relationships to textures if ( modelRels ) { - for ( var i = 0, l = modelRels.length; i < l; i ++ ) { + for ( let i = 0, l = modelRels.length; i < l; i ++ ) { - var modelRel = modelRels[ i ]; - var textureKey = modelRel.target.substring( 1 ); + const modelRel = modelRels[ i ]; + const textureKey = modelRel.target.substring( 1 ); if ( data3mf.texture[ textureKey ] ) { @@ -1390,16 +1387,16 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // start build - for ( var i = 0; i < modelsKeys.length; i ++ ) { + for ( let i = 0; i < modelsKeys.length; i ++ ) { - var modelsKey = modelsKeys[ i ]; - var modelData = modelsData[ modelsKey ]; + const modelsKey = modelsKeys[ i ]; + const modelData = modelsData[ modelsKey ]; - var objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] ); + const objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] ); - for ( var j = 0; j < objectIds.length; j ++ ) { + for ( let j = 0; j < objectIds.length; j ++ ) { - var objectId = objectIds[ j ]; + const objectId = objectIds[ j ]; buildObject( objectId, objects, modelData, textureData ); @@ -1413,10 +1410,10 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function fetch3DModelPart( rels ) { - for ( var i = 0; i < rels.length; i ++ ) { + for ( let i = 0; i < rels.length; i ++ ) { - var rel = rels[ i ]; - var extension = rel.target.split( '.' ).pop(); + const rel = rels[ i ]; + const extension = rel.target.split( '.' ).pop(); if ( extension.toLowerCase() === 'model' ) return rel; @@ -1426,19 +1423,19 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function build( objects, data3mf ) { - var group = new Group(); + const group = new Group(); - var relationship = fetch3DModelPart( data3mf[ 'rels' ] ); - var buildData = data3mf.model[ relationship[ 'target' ].substring( 1 ) ][ 'build' ]; + const relationship = fetch3DModelPart( data3mf[ 'rels' ] ); + const buildData = data3mf.model[ relationship[ 'target' ].substring( 1 ) ][ 'build' ]; - for ( var i = 0; i < buildData.length; i ++ ) { + for ( let i = 0; i < buildData.length; i ++ ) { - var buildItem = buildData[ i ]; - var object3D = objects[ buildItem[ 'objectId' ] ]; + const buildItem = buildData[ i ]; + const object3D = objects[ buildItem[ 'objectId' ] ]; // apply transform - var transform = buildItem[ 'transform' ]; + const transform = buildItem[ 'transform' ]; if ( transform ) { @@ -1454,19 +1451,19 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var data3mf = loadDocument( data ); - var objects = buildObjects( data3mf ); + const data3mf = loadDocument( data ); + const objects = buildObjects( data3mf ); return build( objects, data3mf ); - }, + } - addExtension: function ( extension ) { + addExtension( extension ) { this.availableExtensions.push( extension ); } -} ); +} export { ThreeMFLoader }; diff --git a/examples/jsm/loaders/AMFLoader.js b/examples/jsm/loaders/AMFLoader.js index 683c6395f1c9c8..19379fb94314df 100644 --- a/examples/jsm/loaders/AMFLoader.js +++ b/examples/jsm/loaders/AMFLoader.js @@ -9,7 +9,7 @@ import { Mesh, MeshPhongMaterial } from '../../../build/three.module.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; /** * Description: Early release of an AMF Loader following the pattern of the @@ -18,7 +18,7 @@ import * as fflate from '../libs/fflate.module.min.js'; * More information about the AMF format: http://amf.wikispaces.com * * Usage: - * var loader = new AMFLoader(); + * const loader = new AMFLoader(); * loader.load('/path/to/project.amf', function(objecttree) { * scene.add(objecttree); * }); @@ -29,21 +29,19 @@ import * as fflate from '../libs/fflate.module.min.js'; * */ -var AMFLoader = function ( manager ) { +class AMFLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: AMFLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -72,19 +70,19 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { function loadDocument( data ) { - var view = new DataView( data ); - var magic = String.fromCharCode( view.getUint8( 0 ), view.getUint8( 1 ) ); + let view = new DataView( data ); + const magic = String.fromCharCode( view.getUint8( 0 ), view.getUint8( 1 ) ); if ( magic === 'PK' ) { - var zip = null; - var file = null; + let zip = null; + let file = null; console.log( 'THREE.AMFLoader: Loading Zip' ); @@ -103,7 +101,7 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - for ( var file in zip ) { + for ( file in zip ) { if ( file.toLowerCase().substr( - 4 ) === '.amf' ) { @@ -118,8 +116,8 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var fileText = LoaderUtils.decodeText( view ); - var xmlData = new DOMParser().parseFromString( fileText, 'application/xml' ); + const fileText = LoaderUtils.decodeText( view ); + const xmlData = new DOMParser().parseFromString( fileText, 'application/xml' ); if ( xmlData.documentElement.nodeName.toLowerCase() !== 'amf' ) { @@ -134,8 +132,8 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function loadDocumentScale( node ) { - var scale = 1.0; - var unit = 'millimeter'; + let scale = 1.0; + let unit = 'millimeter'; if ( node.documentElement.attributes.unit !== undefined ) { @@ -143,7 +141,7 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var scaleUnits = { + const scaleUnits = { millimeter: 1.0, inch: 25.4, feet: 304.8, @@ -164,15 +162,15 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function loadMaterials( node ) { - var matName = 'AMF Material'; - var matId = node.attributes.id.textContent; - var color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }; + let matName = 'AMF Material'; + const matId = node.attributes.id.textContent; + let color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }; - var loadedMaterial = null; + let loadedMaterial = null; - for ( var i = 0; i < node.childNodes.length; i ++ ) { + for ( let i = 0; i < node.childNodes.length; i ++ ) { - var matChildEl = node.childNodes[ i ]; + const matChildEl = node.childNodes[ i ]; if ( matChildEl.nodeName === 'metadata' && matChildEl.attributes.type !== undefined ) { @@ -209,11 +207,11 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function loadColor( node ) { - var color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }; + const color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 }; - for ( var i = 0; i < node.childNodes.length; i ++ ) { + for ( let i = 0; i < node.childNodes.length; i ++ ) { - var matColor = node.childNodes[ i ]; + const matColor = node.childNodes[ i ]; if ( matColor.nodeName === 'r' ) { @@ -241,9 +239,9 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function loadMeshVolume( node ) { - var volume = { name: '', triangles: [], materialid: null }; + const volume = { name: '', triangles: [], materialid: null }; - var currVolumeNode = node.firstElementChild; + let currVolumeNode = node.firstElementChild; if ( node.attributes.materialid !== undefined ) { @@ -267,9 +265,9 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( currVolumeNode.nodeName === 'triangle' ) { - var v1 = currVolumeNode.getElementsByTagName( 'v1' )[ 0 ].textContent; - var v2 = currVolumeNode.getElementsByTagName( 'v2' )[ 0 ].textContent; - var v3 = currVolumeNode.getElementsByTagName( 'v3' )[ 0 ].textContent; + const v1 = currVolumeNode.getElementsByTagName( 'v1' )[ 0 ].textContent; + const v2 = currVolumeNode.getElementsByTagName( 'v2' )[ 0 ].textContent; + const v3 = currVolumeNode.getElementsByTagName( 'v3' )[ 0 ].textContent; volume.triangles.push( v1, v2, v3 ); @@ -285,31 +283,31 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function loadMeshVertices( node ) { - var vertArray = []; - var normalArray = []; - var currVerticesNode = node.firstElementChild; + const vertArray = []; + const normalArray = []; + let currVerticesNode = node.firstElementChild; while ( currVerticesNode ) { if ( currVerticesNode.nodeName === 'vertex' ) { - var vNode = currVerticesNode.firstElementChild; + let vNode = currVerticesNode.firstElementChild; while ( vNode ) { if ( vNode.nodeName === 'coordinates' ) { - var x = vNode.getElementsByTagName( 'x' )[ 0 ].textContent; - var y = vNode.getElementsByTagName( 'y' )[ 0 ].textContent; - var z = vNode.getElementsByTagName( 'z' )[ 0 ].textContent; + const x = vNode.getElementsByTagName( 'x' )[ 0 ].textContent; + const y = vNode.getElementsByTagName( 'y' )[ 0 ].textContent; + const z = vNode.getElementsByTagName( 'z' )[ 0 ].textContent; vertArray.push( x, y, z ); } else if ( vNode.nodeName === 'normal' ) { - var nx = vNode.getElementsByTagName( 'nx' )[ 0 ].textContent; - var ny = vNode.getElementsByTagName( 'ny' )[ 0 ].textContent; - var nz = vNode.getElementsByTagName( 'nz' )[ 0 ].textContent; + const nx = vNode.getElementsByTagName( 'nx' )[ 0 ].textContent; + const ny = vNode.getElementsByTagName( 'ny' )[ 0 ].textContent; + const nz = vNode.getElementsByTagName( 'nz' )[ 0 ].textContent; normalArray.push( nx, ny, nz ); @@ -331,10 +329,10 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function loadObject( node ) { - var objId = node.attributes.id.textContent; - var loadedObject = { name: 'amfobject', meshes: [] }; - var currColor = null; - var currObjNode = node.firstElementChild; + const objId = node.attributes.id.textContent; + const loadedObject = { name: 'amfobject', meshes: [] }; + let currColor = null; + let currObjNode = node.firstElementChild; while ( currObjNode ) { @@ -356,14 +354,14 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( currObjNode.nodeName === 'mesh' ) { - var currMeshNode = currObjNode.firstElementChild; - var mesh = { vertices: [], normals: [], volumes: [], color: currColor }; + let currMeshNode = currObjNode.firstElementChild; + const mesh = { vertices: [], normals: [], volumes: [], color: currColor }; while ( currMeshNode ) { if ( currMeshNode.nodeName === 'vertices' ) { - var loadedVertices = loadMeshVertices( currMeshNode ); + const loadedVertices = loadMeshVertices( currMeshNode ); mesh.normals = mesh.normals.concat( loadedVertices.normals ); mesh.vertices = mesh.vertices.concat( loadedVertices.vertices ); @@ -390,19 +388,19 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var xmlData = loadDocument( data ); - var amfName = ''; - var amfAuthor = ''; - var amfScale = loadDocumentScale( xmlData ); - var amfMaterials = {}; - var amfObjects = {}; - var childNodes = xmlData.documentElement.childNodes; + const xmlData = loadDocument( data ); + let amfName = ''; + let amfAuthor = ''; + const amfScale = loadDocumentScale( xmlData ); + const amfMaterials = {}; + const amfObjects = {}; + const childNodes = xmlData.documentElement.childNodes; - var i, j; + let i, j; for ( i = 0; i < childNodes.length; i ++ ) { - var child = childNodes[ i ]; + const child = childNodes[ i ]; if ( child.nodeName === 'metadata' ) { @@ -422,13 +420,13 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( child.nodeName === 'material' ) { - var loadedMaterial = loadMaterials( child ); + const loadedMaterial = loadMaterials( child ); amfMaterials[ loadedMaterial.id ] = loadedMaterial.material; } else if ( child.nodeName === 'object' ) { - var loadedObject = loadObject( child ); + const loadedObject = loadObject( child ); amfObjects[ loadedObject.id ] = loadedObject.obj; @@ -436,26 +434,26 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var sceneObject = new Group(); - var defaultMaterial = new MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } ); + const sceneObject = new Group(); + const defaultMaterial = new MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } ); sceneObject.name = amfName; sceneObject.userData.author = amfAuthor; sceneObject.userData.loader = 'AMF'; - for ( var id in amfObjects ) { + for ( const id in amfObjects ) { - var part = amfObjects[ id ]; - var meshes = part.meshes; - var newObject = new Group(); + const part = amfObjects[ id ]; + const meshes = part.meshes; + const newObject = new Group(); newObject.name = part.name || ''; for ( i = 0; i < meshes.length; i ++ ) { - var objDefaultMaterial = defaultMaterial; - var mesh = meshes[ i ]; - var vertices = new Float32BufferAttribute( mesh.vertices, 3 ); - var normals = null; + let objDefaultMaterial = defaultMaterial; + const mesh = meshes[ i ]; + const vertices = new Float32BufferAttribute( mesh.vertices, 3 ); + let normals = null; if ( mesh.normals.length ) { @@ -465,7 +463,7 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( mesh.color ) { - var color = mesh.color; + const color = mesh.color; objDefaultMaterial = defaultMaterial.clone(); objDefaultMaterial.color = new Color( color.r, color.g, color.b ); @@ -479,13 +477,13 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var volumes = mesh.volumes; + const volumes = mesh.volumes; for ( j = 0; j < volumes.length; j ++ ) { - var volume = volumes[ j ]; - var newGeometry = new BufferGeometry(); - var material = objDefaultMaterial; + const volume = volumes[ j ]; + const newGeometry = new BufferGeometry(); + let material = objDefaultMaterial; newGeometry.setIndex( volume.triangles ); newGeometry.setAttribute( 'position', vertices.clone() ); @@ -517,6 +515,6 @@ AMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { AMFLoader }; diff --git a/examples/jsm/loaders/BVHLoader.js b/examples/jsm/loaders/BVHLoader.js index 9230767410e0ae..b916e86338496a 100644 --- a/examples/jsm/loaders/BVHLoader.js +++ b/examples/jsm/loaders/BVHLoader.js @@ -17,24 +17,22 @@ import { * */ -var BVHLoader = function ( manager ) { +class BVHLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.animateBonePositions = true; - this.animateBoneRotations = true; + super( manager ); -}; + this.animateBonePositions = true; + this.animateBoneRotations = true; -BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: BVHLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setRequestHeader( scope.requestHeader ); loader.setWithCredentials( scope.withCredentials ); @@ -62,9 +60,9 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( text ) { + parse( text ) { /* reads a string array (lines) from a BVH file @@ -83,8 +81,8 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var list = []; // collects flat array of all bones - var root = readNode( lines, nextLine( lines ), list ); + const list = []; // collects flat array of all bones + const root = readNode( lines, nextLine( lines ), list ); // read motion data @@ -96,8 +94,8 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // number of frames - var tokens = nextLine( lines ).split( /[\s]+/ ); - var numFrames = parseInt( tokens[ 1 ] ); + let tokens = nextLine( lines ).split( /[\s]+/ ); + const numFrames = parseInt( tokens[ 1 ] ); if ( isNaN( numFrames ) ) { @@ -108,7 +106,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // frame time tokens = nextLine( lines ).split( /[\s]+/ ); - var frameTime = parseFloat( tokens[ 2 ] ); + const frameTime = parseFloat( tokens[ 2 ] ); if ( isNaN( frameTime ) ) { @@ -118,7 +116,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // read frame data line by line - for ( var i = 0; i < numFrames; i ++ ) { + for ( let i = 0; i < numFrames; i ++ ) { tokens = nextLine( lines ).split( /[\s]+/ ); readFrameData( tokens, i * frameTime, root ); @@ -147,7 +145,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // add keyframe - var keyframe = { + const keyframe = { time: frameTime, position: new Vector3(), rotation: new Quaternion() @@ -155,15 +153,15 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { bone.frames.push( keyframe ); - var quat = new Quaternion(); + const quat = new Quaternion(); - var vx = new Vector3( 1, 0, 0 ); - var vy = new Vector3( 0, 1, 0 ); - var vz = new Vector3( 0, 0, 1 ); + const vx = new Vector3( 1, 0, 0 ); + const vy = new Vector3( 0, 1, 0 ); + const vz = new Vector3( 0, 0, 1 ); // parse values for each channel in node - for ( var i = 0; i < bone.channels.length; i ++ ) { + for ( let i = 0; i < bone.channels.length; i ++ ) { switch ( bone.channels[ i ] ) { @@ -197,7 +195,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // parse child nodes - for ( var i = 0; i < bone.children.length; i ++ ) { + for ( let i = 0; i < bone.children.length; i ++ ) { readFrameData( data, frameTime, bone.children[ i ] ); @@ -216,12 +214,12 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { */ function readNode( lines, firstline, list ) { - var node = { name: '', type: '', frames: [] }; + const node = { name: '', type: '', frames: [] }; list.push( node ); // parse node type and name - var tokens = firstline.split( /[\s]+/ ); + let tokens = firstline.split( /[\s]+/ ); if ( tokens[ 0 ].toUpperCase() === 'END' && tokens[ 1 ].toUpperCase() === 'SITE' ) { @@ -257,7 +255,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var offset = new Vector3( + const offset = new Vector3( parseFloat( tokens[ 1 ] ), parseFloat( tokens[ 2 ] ), parseFloat( tokens[ 3 ] ) @@ -283,7 +281,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var numChannels = parseInt( tokens[ 1 ] ); + const numChannels = parseInt( tokens[ 1 ] ); node.channels = tokens.splice( 2, numChannels ); node.children = []; @@ -293,7 +291,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { while ( true ) { - var line = nextLine( lines ); + const line = nextLine( lines ); if ( line === '}' ) { @@ -319,7 +317,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { */ function toTHREEBone( source, list ) { - var bone = new Bone(); + const bone = new Bone(); list.push( bone ); bone.position.add( source.offset ); @@ -327,7 +325,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( source.type !== 'ENDSITE' ) { - for ( var i = 0; i < source.children.length; i ++ ) { + for ( let i = 0; i < source.children.length; i ++ ) { bone.add( toTHREEBone( source.children[ i ], list ) ); @@ -348,26 +346,26 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { */ function toTHREEAnimation( bones ) { - var tracks = []; + const tracks = []; // create a position and quaternion animation track for each node - for ( var i = 0; i < bones.length; i ++ ) { + for ( let i = 0; i < bones.length; i ++ ) { - var bone = bones[ i ]; + const bone = bones[ i ]; if ( bone.type === 'ENDSITE' ) continue; // track data - var times = []; - var positions = []; - var rotations = []; + const times = []; + const positions = []; + const rotations = []; - for ( var j = 0; j < bone.frames.length; j ++ ) { + for ( let j = 0; j < bone.frames.length; j ++ ) { - var frame = bone.frames[ j ]; + const frame = bone.frames[ j ]; times.push( frame.time ); @@ -408,7 +406,7 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { */ function nextLine( lines ) { - var line; + let line; // skip empty lines while ( ( line = lines.shift().trim() ).length === 0 ) { } @@ -416,16 +414,16 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var scope = this; + const scope = this; - var lines = text.split( /[\r\n]+/g ); + const lines = text.split( /[\r\n]+/g ); - var bones = readBvh( lines ); + const bones = readBvh( lines ); - var threeBones = []; + const threeBones = []; toTHREEBone( bones[ 0 ], threeBones ); - var threeClip = toTHREEAnimation( bones ); + const threeClip = toTHREEAnimation( bones ); return { skeleton: new Skeleton( threeBones ), @@ -434,6 +432,6 @@ BVHLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { BVHLoader }; diff --git a/examples/jsm/loaders/BasisTextureLoader.js b/examples/jsm/loaders/BasisTextureLoader.js index ca59ec034787c0..65e7f67278acf5 100644 --- a/examples/jsm/loaders/BasisTextureLoader.js +++ b/examples/jsm/loaders/BasisTextureLoader.js @@ -29,45 +29,44 @@ import { * of web workers, before transferring the transcoded compressed texture back * to the main thread. */ -var BasisTextureLoader = function ( manager ) { - Loader.call( this, manager ); +const _taskCache = new WeakMap(); - this.transcoderPath = ''; - this.transcoderBinary = null; - this.transcoderPending = null; +class BasisTextureLoader extends Loader { - this.workerLimit = 4; - this.workerPool = []; - this.workerNextTaskID = 1; - this.workerSourceURL = ''; - this.workerConfig = null; + constructor( manager ) { -}; + super( manager ); -BasisTextureLoader.taskCache = new WeakMap(); + this.transcoderPath = ''; + this.transcoderBinary = null; + this.transcoderPending = null; -BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + this.workerLimit = 4; + this.workerPool = []; + this.workerNextTaskID = 1; + this.workerSourceURL = ''; + this.workerConfig = null; - constructor: BasisTextureLoader, + } - setTranscoderPath: function ( path ) { + setTranscoderPath( path ) { this.transcoderPath = path; return this; - }, + } - setWorkerLimit: function ( workerLimit ) { + setWorkerLimit( workerLimit ) { this.workerLimit = workerLimit; return this; - }, + } - detectSupport: function ( renderer ) { + detectSupport( renderer ) { this.workerConfig = { astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ), @@ -81,24 +80,24 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), return this; - }, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setResponseType( 'arraybuffer' ); loader.setWithCredentials( this.withCredentials ); - var texture = new CompressedTexture(); + const texture = new CompressedTexture(); loader.load( url, ( buffer ) => { // Check for an existing task using this buffer. A transferred buffer cannot be transferred // again from this thread. - if ( BasisTextureLoader.taskCache.has( buffer ) ) { + if ( _taskCache.has( buffer ) ) { - var cachedTask = BasisTextureLoader.taskCache.get( buffer ); + const cachedTask = _taskCache.get( buffer ); return cachedTask.promise.then( onLoad ).catch( onError ); @@ -119,16 +118,16 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), return texture; - }, + } /** Low-level transcoding API, exposed for use by KTX2Loader. */ - parseInternalAsync: function ( options ) { + parseInternalAsync( options ) { - var { levels } = options; + const { levels } = options; - var buffers = new Set(); + const buffers = new Set(); - for ( var i = 0; i < levels.length; i ++ ) { + for ( let i = 0; i < levels.length; i ++ ) { buffers.add( levels[ i ].data.buffer ); @@ -136,28 +135,28 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), return this._createTexture( Array.from( buffers ), { ...options, lowLevel: true } ); - }, + } /** * @param {ArrayBuffer[]} buffers * @param {object?} config * @return {Promise} */ - _createTexture: function ( buffers, config ) { + _createTexture( buffers, config = {} ) { - var worker; - var taskID; + let worker; + let taskID; - var taskConfig = config || {}; - var taskCost = 0; + const taskConfig = config; + let taskCost = 0; - for ( var i = 0; i < buffers.length; i ++ ) { + for ( let i = 0; i < buffers.length; i ++ ) { taskCost += buffers[ i ].byteLength; } - var texturePending = this._allocateWorker( taskCost ) + const texturePending = this._allocateWorker( taskCost ) .then( ( _worker ) => { worker = _worker; @@ -174,9 +173,9 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), } ) .then( ( message ) => { - var { mipmaps, width, height, format } = message; + const { mipmaps, width, height, format } = message; - var texture = new CompressedTexture( mipmaps, width, height, format, UnsignedByteType ); + const texture = new CompressedTexture( mipmaps, width, height, format, UnsignedByteType ); texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter; texture.magFilter = LinearFilter; texture.generateMipmaps = false; @@ -201,32 +200,32 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), } ); // Cache the task result. - BasisTextureLoader.taskCache.set( buffers[ 0 ], { promise: texturePending } ); + _taskCache.set( buffers[ 0 ], { promise: texturePending } ); return texturePending; - }, + } - _initTranscoder: function () { + _initTranscoder() { if ( ! this.transcoderPending ) { // Load transcoder wrapper. - var jsLoader = new FileLoader( this.manager ); + const jsLoader = new FileLoader( this.manager ); jsLoader.setPath( this.transcoderPath ); jsLoader.setWithCredentials( this.withCredentials ); - var jsContent = new Promise( ( resolve, reject ) => { + const jsContent = new Promise( ( resolve, reject ) => { jsLoader.load( 'basis_transcoder.js', resolve, undefined, reject ); } ); // Load transcoder WASM binary. - var binaryLoader = new FileLoader( this.manager ); + const binaryLoader = new FileLoader( this.manager ); binaryLoader.setPath( this.transcoderPath ); binaryLoader.setResponseType( 'arraybuffer' ); binaryLoader.setWithCredentials( this.withCredentials ); - var binaryContent = new Promise( ( resolve, reject ) => { + const binaryContent = new Promise( ( resolve, reject ) => { binaryLoader.load( 'basis_transcoder.wasm', resolve, undefined, reject ); @@ -235,13 +234,13 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), this.transcoderPending = Promise.all( [ jsContent, binaryContent ] ) .then( ( [ jsContent, binaryContent ] ) => { - var fn = BasisTextureLoader.BasisWorker.toString(); + const fn = BasisTextureLoader.BasisWorker.toString(); - var body = [ + const body = [ '/* constants */', - 'var _EngineFormat = ' + JSON.stringify( BasisTextureLoader.EngineFormat ), - 'var _TranscoderFormat = ' + JSON.stringify( BasisTextureLoader.TranscoderFormat ), - 'var _BasisFormat = ' + JSON.stringify( BasisTextureLoader.BasisFormat ), + 'let _EngineFormat = ' + JSON.stringify( BasisTextureLoader.EngineFormat ), + 'let _TranscoderFormat = ' + JSON.stringify( BasisTextureLoader.TranscoderFormat ), + 'let _BasisFormat = ' + JSON.stringify( BasisTextureLoader.BasisFormat ), '/* basis_transcoder.js */', jsContent, '/* worker */', @@ -257,15 +256,15 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), return this.transcoderPending; - }, + } - _allocateWorker: function ( taskCost ) { + _allocateWorker( taskCost ) { return this._initTranscoder().then( () => { if ( this.workerPool.length < this.workerLimit ) { - var worker = new Worker( this.workerSourceURL ); + const worker = new Worker( this.workerSourceURL ); worker._callbacks = {}; worker._taskLoad = 0; @@ -278,7 +277,7 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), worker.onmessage = function ( e ) { - var message = e.data; + const message = e.data; switch ( message.type ) { @@ -309,7 +308,7 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), } - var worker = this.workerPool[ this.workerPool.length - 1 ]; + const worker = this.workerPool[ this.workerPool.length - 1 ]; worker._taskLoad += taskCost; @@ -317,11 +316,11 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), } ); - }, + } - dispose: function () { + dispose() { - for ( var i = 0; i < this.workerPool.length; i ++ ) { + for ( let i = 0; i < this.workerPool.length; i ++ ) { this.workerPool[ i ].terminate(); @@ -333,7 +332,7 @@ BasisTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), } -} ); +} /* CONSTANTS */ @@ -380,17 +379,17 @@ BasisTextureLoader.EngineFormat = { BasisTextureLoader.BasisWorker = function () { - var config; - var transcoderPending; - var BasisModule; + let config; + let transcoderPending; + let BasisModule; - var EngineFormat = _EngineFormat; // eslint-disable-line no-undef - var TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef - var BasisFormat = _BasisFormat; // eslint-disable-line no-undef + const EngineFormat = _EngineFormat; // eslint-disable-line no-undef + const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef + const BasisFormat = _BasisFormat; // eslint-disable-line no-undef onmessage = function ( e ) { - var message = e.data; + const message = e.data; switch ( message.type ) { @@ -404,13 +403,13 @@ BasisTextureLoader.BasisWorker = function () { try { - var { width, height, hasAlpha, mipmaps, format } = message.taskConfig.lowLevel + const { width, height, hasAlpha, mipmaps, format } = message.taskConfig.lowLevel ? transcodeLowLevel( message.taskConfig ) : transcode( message.buffers[ 0 ] ); - var buffers = []; + const buffers = []; - for ( var i = 0; i < mipmaps.length; ++ i ) { + for ( let i = 0; i < mipmaps.length; ++ i ) { buffers.push( mipmaps[ i ].data.buffer ); @@ -450,25 +449,25 @@ BasisTextureLoader.BasisWorker = function () { function transcodeLowLevel( taskConfig ) { - var { basisFormat, width, height, hasAlpha } = taskConfig; + const { basisFormat, width, height, hasAlpha } = taskConfig; - var { transcoderFormat, engineFormat } = getTranscoderFormat( basisFormat, width, height, hasAlpha ); + const { transcoderFormat, engineFormat } = getTranscoderFormat( basisFormat, width, height, hasAlpha ); - var blockByteLength = BasisModule.getBytesPerBlockOrPixel( transcoderFormat ); + const blockByteLength = BasisModule.getBytesPerBlockOrPixel( transcoderFormat ); assert( BasisModule.isFormatSupported( transcoderFormat ), 'THREE.BasisTextureLoader: Unsupported format.' ); - var mipmaps = []; + const mipmaps = []; if ( basisFormat === BasisFormat.ETC1S ) { - var transcoder = new BasisModule.LowLevelETC1SImageTranscoder(); + const transcoder = new BasisModule.LowLevelETC1SImageTranscoder(); - var { endpointCount, endpointsData, selectorCount, selectorsData, tablesData } = taskConfig.globalData; + const { endpointCount, endpointsData, selectorCount, selectorsData, tablesData } = taskConfig.globalData; try { - var ok; + let ok; ok = transcoder.decodePalettes( endpointCount, endpointsData, selectorCount, selectorsData ); @@ -478,13 +477,13 @@ BasisTextureLoader.BasisWorker = function () { assert( ok, 'THREE.BasisTextureLoader: decodeTables() failed.' ); - for ( var i = 0; i < taskConfig.levels.length; i ++ ) { + for ( let i = 0; i < taskConfig.levels.length; i ++ ) { - var level = taskConfig.levels[ i ]; - var imageDesc = taskConfig.globalData.imageDescs[ i ]; + const level = taskConfig.levels[ i ]; + const imageDesc = taskConfig.globalData.imageDescs[ i ]; - var dstByteLength = getTranscodedImageByteLength( transcoderFormat, level.width, level.height ); - var dst = new Uint8Array( dstByteLength ); + const dstByteLength = getTranscodedImageByteLength( transcoderFormat, level.width, level.height ); + const dst = new Uint8Array( dstByteLength ); ok = transcoder.transcodeImage( transcoderFormat, @@ -515,14 +514,14 @@ BasisTextureLoader.BasisWorker = function () { } else { - for ( var i = 0; i < taskConfig.levels.length; i ++ ) { + for ( let i = 0; i < taskConfig.levels.length; i ++ ) { - var level = taskConfig.levels[ i ]; + const level = taskConfig.levels[ i ]; - var dstByteLength = getTranscodedImageByteLength( transcoderFormat, level.width, level.height ); - var dst = new Uint8Array( dstByteLength ); + const dstByteLength = getTranscodedImageByteLength( transcoderFormat, level.width, level.height ); + const dst = new Uint8Array( dstByteLength ); - var ok = BasisModule.transcodeUASTCImage( + const ok = BasisModule.transcodeUASTCImage( transcoderFormat, dst, dstByteLength / blockByteLength, level.data, @@ -552,13 +551,13 @@ BasisTextureLoader.BasisWorker = function () { function transcode( buffer ) { - var basisFile = new BasisModule.BasisFile( new Uint8Array( buffer ) ); + const basisFile = new BasisModule.BasisFile( new Uint8Array( buffer ) ); - var basisFormat = basisFile.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S; - var width = basisFile.getImageWidth( 0, 0 ); - var height = basisFile.getImageHeight( 0, 0 ); - var levels = basisFile.getNumLevels( 0 ); - var hasAlpha = basisFile.getHasAlpha(); + const basisFormat = basisFile.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S; + const width = basisFile.getImageWidth( 0, 0 ); + const height = basisFile.getImageHeight( 0, 0 ); + const levels = basisFile.getNumLevels( 0 ); + const hasAlpha = basisFile.getHasAlpha(); function cleanup() { @@ -567,7 +566,7 @@ BasisTextureLoader.BasisWorker = function () { } - var { transcoderFormat, engineFormat } = getTranscoderFormat( basisFormat, width, height, hasAlpha ); + const { transcoderFormat, engineFormat } = getTranscoderFormat( basisFormat, width, height, hasAlpha ); if ( ! width || ! height || ! levels ) { @@ -583,15 +582,15 @@ BasisTextureLoader.BasisWorker = function () { } - var mipmaps = []; + const mipmaps = []; - for ( var mip = 0; mip < levels; mip ++ ) { + for ( let mip = 0; mip < levels; mip ++ ) { - var mipWidth = basisFile.getImageWidth( 0, mip ); - var mipHeight = basisFile.getImageHeight( 0, mip ); - var dst = new Uint8Array( basisFile.getImageTranscodedSizeInBytes( 0, mip, transcoderFormat ) ); + const mipWidth = basisFile.getImageWidth( 0, mip ); + const mipHeight = basisFile.getImageHeight( 0, mip ); + const dst = new Uint8Array( basisFile.getImageTranscodedSizeInBytes( 0, mip, transcoderFormat ) ); - var status = basisFile.transcodeImage( + const status = basisFile.transcodeImage( dst, 0, mip, @@ -626,7 +625,7 @@ BasisTextureLoader.BasisWorker = function () { // In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at // significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently // chooses RGBA32 only as a last resort and does not expose that option to the caller. - var FORMAT_OPTIONS = [ + const FORMAT_OPTIONS = [ { if: 'astcSupported', basisFormat: [ BasisFormat.UASTC_4x4 ], @@ -683,12 +682,12 @@ BasisTextureLoader.BasisWorker = function () { }, ]; - var ETC1S_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) { + const ETC1S_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) { return a.priorityETC1S - b.priorityETC1S; } ); - var UASTC_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) { + const UASTC_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) { return a.priorityUASTC - b.priorityUASTC; @@ -696,14 +695,14 @@ BasisTextureLoader.BasisWorker = function () { function getTranscoderFormat( basisFormat, width, height, hasAlpha ) { - var transcoderFormat; - var engineFormat; + let transcoderFormat; + let engineFormat; - var options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS; + const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS; - for ( var i = 0; i < options.length; i ++ ) { + for ( let i = 0; i < options.length; i ++ ) { - var opt = options[ i ]; + const opt = options[ i ]; if ( ! config[ opt.if ] ) continue; if ( ! opt.basisFormat.includes( basisFormat ) ) continue; @@ -745,7 +744,7 @@ BasisTextureLoader.BasisWorker = function () { function getTranscodedImageByteLength( transcoderFormat, width, height ) { - var blockByteLength = BasisModule.getBytesPerBlockOrPixel( transcoderFormat ); + const blockByteLength = BasisModule.getBytesPerBlockOrPixel( transcoderFormat ); if ( BasisModule.formatIsUncompressed( transcoderFormat ) ) { @@ -758,8 +757,8 @@ BasisTextureLoader.BasisWorker = function () { // GL requires extra padding for very small textures: // https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt - var paddedWidth = ( width + 3 ) & ~ 3; - var paddedHeight = ( height + 3 ) & ~ 3; + const paddedWidth = ( width + 3 ) & ~ 3; + const paddedHeight = ( height + 3 ) & ~ 3; return ( Math.max( 8, paddedWidth ) * Math.max( 8, paddedHeight ) * 4 + 7 ) / 8; diff --git a/examples/jsm/loaders/ColladaLoader.js b/examples/jsm/loaders/ColladaLoader.js index be9a4749178bb0..e78ac4a14fa941 100644 --- a/examples/jsm/loaders/ColladaLoader.js +++ b/examples/jsm/loaders/ColladaLoader.js @@ -38,23 +38,21 @@ import { } from '../../../build/three.module.js'; import { TGALoader } from '../loaders/TGALoader.js'; -var ColladaLoader = function ( manager ) { +class ColladaLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: ColladaLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; + const path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setRequestHeader( scope.requestHeader ); loader.setWithCredentials( scope.withCredentials ); @@ -82,30 +80,20 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, - - options: { - - set convertUpAxis( value ) { - - console.warn( 'THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.' ); - - } - - }, + } - parse: function ( text, path ) { + parse( text, path ) { function getElementsByTagName( xml, name ) { // Non recursive xml.getElementsByTagName() ... - var array = []; - var childNodes = xml.childNodes; + const array = []; + const childNodes = xml.childNodes; - for ( var i = 0, l = childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = childNodes.length; i < l; i ++ ) { - var child = childNodes[ i ]; + const child = childNodes[ i ]; if ( child.nodeName === name ) { @@ -123,10 +111,10 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( text.length === 0 ) return []; - var parts = text.trim().split( /\s+/ ); - var array = new Array( parts.length ); + const parts = text.trim().split( /\s+/ ); + const array = new Array( parts.length ); - for ( var i = 0, l = parts.length; i < l; i ++ ) { + for ( let i = 0, l = parts.length; i < l; i ++ ) { array[ i ] = parts[ i ]; @@ -140,10 +128,10 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( text.length === 0 ) return []; - var parts = text.trim().split( /\s+/ ); - var array = new Array( parts.length ); + const parts = text.trim().split( /\s+/ ); + const array = new Array( parts.length ); - for ( var i = 0, l = parts.length; i < l; i ++ ) { + for ( let i = 0, l = parts.length; i < l; i ++ ) { array[ i ] = parseFloat( parts[ i ] ); @@ -157,10 +145,10 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( text.length === 0 ) return []; - var parts = text.trim().split( /\s+/ ); - var array = new Array( parts.length ); + const parts = text.trim().split( /\s+/ ); + const array = new Array( parts.length ); - for ( var i = 0, l = parts.length; i < l; i ++ ) { + for ( let i = 0, l = parts.length; i < l; i ++ ) { array[ i ] = parseInt( parts[ i ] ); @@ -223,13 +211,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseLibrary( xml, libraryName, nodeName, parser ) { - var library = getElementsByTagName( xml, libraryName )[ 0 ]; + const library = getElementsByTagName( xml, libraryName )[ 0 ]; if ( library !== undefined ) { - var elements = getElementsByTagName( library, nodeName ); + const elements = getElementsByTagName( library, nodeName ); - for ( var i = 0; i < elements.length; i ++ ) { + for ( let i = 0; i < elements.length; i ++ ) { parser( elements[ i ] ); @@ -241,9 +229,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildLibrary( data, builder ) { - for ( var name in data ) { + for ( const name in data ) { - var object = data[ name ]; + const object = data[ name ]; object.build = builder( data[ name ] ); } @@ -266,21 +254,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseAnimation( xml ) { - var data = { + const data = { sources: {}, samplers: {}, channels: {} }; - var hasChildren = false; + let hasChildren = false; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; - var id; + let id; switch ( child.nodeName ) { @@ -324,21 +312,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseAnimationSampler( xml ) { - var data = { + const data = { inputs: {}, }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'input': - var id = parseId( child.getAttribute( 'source' ) ); - var semantic = child.getAttribute( 'semantic' ); + const id = parseId( child.getAttribute( 'source' ) ); + const semantic = child.getAttribute( 'semantic' ); data.inputs[ semantic ] = id; break; @@ -352,21 +340,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseAnimationChannel( xml ) { - var data = {}; + const data = {}; - var target = xml.getAttribute( 'target' ); + const target = xml.getAttribute( 'target' ); // parsing SID Addressing Syntax - var parts = target.split( '/' ); + let parts = target.split( '/' ); - var id = parts.shift(); - var sid = parts.shift(); + const id = parts.shift(); + let sid = parts.shift(); // check selection syntax - var arraySyntax = ( sid.indexOf( '(' ) !== - 1 ); - var memberSyntax = ( sid.indexOf( '.' ) !== - 1 ); + const arraySyntax = ( sid.indexOf( '(' ) !== - 1 ); + const memberSyntax = ( sid.indexOf( '.' ) !== - 1 ); if ( memberSyntax ) { @@ -380,10 +368,10 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices. - var indices = sid.split( '(' ); + const indices = sid.split( '(' ); sid = indices.shift(); - for ( var i = 0; i < indices.length; i ++ ) { + for ( let i = 0; i < indices.length; i ++ ) { indices[ i ] = parseInt( indices[ i ].replace( /\)/, '' ) ); @@ -407,26 +395,26 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildAnimation( data ) { - var tracks = []; + const tracks = []; - var channels = data.channels; - var samplers = data.samplers; - var sources = data.sources; + const channels = data.channels; + const samplers = data.samplers; + const sources = data.sources; - for ( var target in channels ) { + for ( const target in channels ) { if ( channels.hasOwnProperty( target ) ) { - var channel = channels[ target ]; - var sampler = samplers[ channel.sampler ]; + const channel = channels[ target ]; + const sampler = samplers[ channel.sampler ]; - var inputId = sampler.inputs.INPUT; - var outputId = sampler.inputs.OUTPUT; + const inputId = sampler.inputs.INPUT; + const outputId = sampler.inputs.OUTPUT; - var inputSource = sources[ inputId ]; - var outputSource = sources[ outputId ]; + const inputSource = sources[ inputId ]; + const outputSource = sources[ outputId ]; - var animation = buildAnimationChannel( channel, inputSource, outputSource ); + const animation = buildAnimationChannel( channel, inputSource, outputSource ); createKeyframeTracks( animation, tracks ); @@ -446,16 +434,16 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildAnimationChannel( channel, inputSource, outputSource ) { - var node = library.nodes[ channel.id ]; - var object3D = getNode( node.id ); + const node = library.nodes[ channel.id ]; + const object3D = getNode( node.id ); - var transform = node.transforms[ channel.sid ]; - var defaultMatrix = node.matrix.clone().transpose(); + const transform = node.transforms[ channel.sid ]; + const defaultMatrix = node.matrix.clone().transpose(); - var time, stride; - var i, il, j, jl; + let time, stride; + let i, il, j, jl; - var data = {}; + const data = {}; // the collada spec allows the animation of data in various ways. // depending on the transform type (matrix, translate, rotate, scale), we execute different logic @@ -473,8 +461,8 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( channel.arraySyntax === true ) { - var value = outputSource.array[ stride ]; - var index = channel.indices[ 0 ] + 4 * channel.indices[ 1 ]; + const value = outputSource.array[ stride ]; + const index = channel.indices[ 0 ] + 4 * channel.indices[ 1 ]; data[ time ][ index ] = value; @@ -506,9 +494,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var keyframes = prepareAnimationData( data, defaultMatrix ); + const keyframes = prepareAnimationData( data, defaultMatrix ); - var animation = { + const animation = { name: object3D.uuid, keyframes: keyframes }; @@ -519,11 +507,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function prepareAnimationData( data, defaultMatrix ) { - var keyframes = []; + const keyframes = []; // transfer data into a sortable array - for ( var time in data ) { + for ( const time in data ) { keyframes.push( { time: parseFloat( time ), value: data[ time ] } ); @@ -535,7 +523,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // now we clean up all animation data, so we can use them for keyframe tracks - for ( var i = 0; i < 16; i ++ ) { + for ( let i = 0; i < 16; i ++ ) { transformAnimationData( keyframes, i, defaultMatrix.elements[ i ] ); @@ -553,26 +541,26 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var position = new Vector3(); - var scale = new Vector3(); - var quaternion = new Quaternion(); + const position = new Vector3(); + const scale = new Vector3(); + const quaternion = new Quaternion(); function createKeyframeTracks( animation, tracks ) { - var keyframes = animation.keyframes; - var name = animation.name; + const keyframes = animation.keyframes; + const name = animation.name; - var times = []; - var positionData = []; - var quaternionData = []; - var scaleData = []; + const times = []; + const positionData = []; + const quaternionData = []; + const scaleData = []; - for ( var i = 0, l = keyframes.length; i < l; i ++ ) { + for ( let i = 0, l = keyframes.length; i < l; i ++ ) { - var keyframe = keyframes[ i ]; + const keyframe = keyframes[ i ]; - var time = keyframe.time; - var value = keyframe.value; + const time = keyframe.time; + const value = keyframe.value; matrix.fromArray( value ).transpose(); matrix.decompose( position, quaternion, scale ); @@ -594,10 +582,10 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function transformAnimationData( keyframes, property, defaultValue ) { - var keyframe; + let keyframe; - var empty = true; - var i, l; + let empty = true; + let i, l; // check, if values of a property are missing in our keyframes @@ -641,11 +629,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function createMissingKeyframes( keyframes, property ) { - var prev, next; + let prev, next; - for ( var i = 0, l = keyframes.length; i < l; i ++ ) { + for ( let i = 0, l = keyframes.length; i < l; i ++ ) { - var keyframe = keyframes[ i ]; + const keyframe = keyframes[ i ]; if ( keyframe.value[ property ] === null ) { @@ -678,7 +666,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { while ( i >= 0 ) { - var keyframe = keyframes[ i ]; + const keyframe = keyframes[ i ]; if ( keyframe.value[ property ] !== null ) return keyframe; @@ -694,7 +682,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { while ( i < keyframes.length ) { - var keyframe = keyframes[ i ]; + const keyframe = keyframes[ i ]; if ( keyframe.value[ property ] !== null ) return keyframe; @@ -723,16 +711,16 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseAnimationClip( xml ) { - var data = { + const data = { name: xml.getAttribute( 'id' ) || 'default', start: parseFloat( xml.getAttribute( 'start' ) || 0 ), end: parseFloat( xml.getAttribute( 'end' ) || 0 ), animations: [] }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -752,17 +740,17 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildAnimationClip( data ) { - var tracks = []; + const tracks = []; - var name = data.name; - var duration = ( data.end - data.start ) || - 1; - var animations = data.animations; + const name = data.name; + const duration = ( data.end - data.start ) || - 1; + const animations = data.animations; - for ( var i = 0, il = animations.length; i < il; i ++ ) { + for ( let i = 0, il = animations.length; i < il; i ++ ) { - var animationTracks = getAnimation( animations[ i ] ); + const animationTracks = getAnimation( animations[ i ] ); - for ( var j = 0, jl = animationTracks.length; j < jl; j ++ ) { + for ( let j = 0, jl = animationTracks.length; j < jl; j ++ ) { tracks.push( animationTracks[ j ] ); @@ -784,11 +772,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseController( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -815,13 +803,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseSkin( xml ) { - var data = { + const data = { sources: {} }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -832,7 +820,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'source': - var id = child.getAttribute( 'id' ); + const id = child.getAttribute( 'id' ); data.sources[ id ] = parseSource( child ); break; @@ -854,21 +842,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseJoints( xml ) { - var data = { + const data = { inputs: {} }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'input': - var semantic = child.getAttribute( 'semantic' ); - var id = parseId( child.getAttribute( 'source' ) ); + const semantic = child.getAttribute( 'semantic' ); + const id = parseId( child.getAttribute( 'source' ) ); data.inputs[ semantic ] = id; break; @@ -882,22 +870,22 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseVertexWeights( xml ) { - var data = { + const data = { inputs: {} }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'input': - var semantic = child.getAttribute( 'semantic' ); - var id = parseId( child.getAttribute( 'source' ) ); - var offset = parseInt( child.getAttribute( 'offset' ) ); + const semantic = child.getAttribute( 'semantic' ); + const id = parseId( child.getAttribute( 'source' ) ); + const offset = parseInt( child.getAttribute( 'offset' ) ); data.inputs[ semantic ] = { id: id, offset: offset }; break; @@ -919,11 +907,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildController( data ) { - var build = { + const build = { id: data.id }; - var geometry = library.geometries[ build.id ]; + const geometry = library.geometries[ build.id ]; if ( data.skin !== undefined ) { @@ -942,9 +930,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildSkin( data ) { - var BONE_LIMIT = 4; + const BONE_LIMIT = 4; - var build = { + const build = { joints: [], // this must be an array to preserve the joint order indices: { array: [], @@ -956,34 +944,34 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } }; - var sources = data.sources; - var vertexWeights = data.vertexWeights; + const sources = data.sources; + const vertexWeights = data.vertexWeights; - var vcount = vertexWeights.vcount; - var v = vertexWeights.v; - var jointOffset = vertexWeights.inputs.JOINT.offset; - var weightOffset = vertexWeights.inputs.WEIGHT.offset; + const vcount = vertexWeights.vcount; + const v = vertexWeights.v; + const jointOffset = vertexWeights.inputs.JOINT.offset; + const weightOffset = vertexWeights.inputs.WEIGHT.offset; - var jointSource = data.sources[ data.joints.inputs.JOINT ]; - var inverseSource = data.sources[ data.joints.inputs.INV_BIND_MATRIX ]; + const jointSource = data.sources[ data.joints.inputs.JOINT ]; + const inverseSource = data.sources[ data.joints.inputs.INV_BIND_MATRIX ]; - var weights = sources[ vertexWeights.inputs.WEIGHT.id ].array; - var stride = 0; + const weights = sources[ vertexWeights.inputs.WEIGHT.id ].array; + let stride = 0; - var i, j, l; + let i, j, l; // procces skin data for each vertex for ( i = 0, l = vcount.length; i < l; i ++ ) { - var jointCount = vcount[ i ]; // this is the amount of joints that affect a single vertex - var vertexSkinData = []; + const jointCount = vcount[ i ]; // this is the amount of joints that affect a single vertex + const vertexSkinData = []; for ( j = 0; j < jointCount; j ++ ) { - var skinIndex = v[ stride + jointOffset ]; - var weightId = v[ stride + weightOffset ]; - var skinWeight = weights[ weightId ]; + const skinIndex = v[ stride + jointOffset ]; + const weightId = v[ stride + weightOffset ]; + const skinWeight = weights[ weightId ]; vertexSkinData.push( { index: skinIndex, weight: skinWeight } ); @@ -1001,7 +989,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { for ( j = 0; j < BONE_LIMIT; j ++ ) { - var d = vertexSkinData[ j ]; + const d = vertexSkinData[ j ]; if ( d !== undefined ) { @@ -1035,8 +1023,8 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { for ( i = 0, l = jointSource.array.length; i < l; i ++ ) { - var name = jointSource.array[ i ]; - var boneInverse = new Matrix4().fromArray( inverseSource.array, i * inverseSource.stride ).transpose(); + const name = jointSource.array[ i ]; + const boneInverse = new Matrix4().fromArray( inverseSource.array, i * inverseSource.stride ).transpose(); build.joints.push( { name: name, boneInverse: boneInverse } ); @@ -1064,7 +1052,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseImage( xml ) { - var data = { + const data = { init_from: getElementsByTagName( xml, 'init_from' )[ 0 ].textContent }; @@ -1082,7 +1070,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getImage( id ) { - var data = library.images[ id ]; + const data = library.images[ id ]; if ( data !== undefined ) { @@ -1100,11 +1088,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffect( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1124,14 +1112,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectProfileCOMMON( xml ) { - var data = { + const data = { surfaces: {}, samplers: {} }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1159,11 +1147,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectNewparam( xml, data ) { - var sid = xml.getAttribute( 'sid' ); + const sid = xml.getAttribute( 'sid' ); - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1185,11 +1173,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectSurface( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1209,11 +1197,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectSampler( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1233,11 +1221,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectTechnique( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1261,11 +1249,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectParameters( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1297,11 +1285,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectParameter( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1329,13 +1317,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectParameterTexture( xml ) { - var data = { + const data = { technique: {} }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1355,9 +1343,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectParameterTextureExtra( xml, data ) { - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1375,9 +1363,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectParameterTextureExtraTechnique( xml, data ) { - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1419,11 +1407,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectExtra( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1443,11 +1431,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEffectExtraTechnique( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1481,13 +1469,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseMaterial( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ) }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1507,9 +1495,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getTextureLoader( image ) { - var loader; + let loader; - var extension = image.slice( ( image.lastIndexOf( '.' ) - 1 >>> 0 ) + 2 ); // http://www.jstips.co/en/javascript/get-file-extension/ + let extension = image.slice( ( image.lastIndexOf( '.' ) - 1 >>> 0 ) + 2 ); // http://www.jstips.co/en/javascript/get-file-extension/ extension = extension.toLowerCase(); switch ( extension ) { @@ -1529,11 +1517,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildMaterial( data ) { - var effect = getEffect( data.url ); - var technique = effect.profile.technique; - var extra = effect.profile.extra; + const effect = getEffect( data.url ); + const technique = effect.profile.technique; + const extra = effect.profile.extra; - var material; + let material; switch ( technique.type ) { @@ -1556,14 +1544,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getTexture( textureObject ) { - var sampler = effect.profile.samplers[ textureObject.id ]; - var image = null; + const sampler = effect.profile.samplers[ textureObject.id ]; + let image = null; // get image if ( sampler !== undefined ) { - var surface = effect.profile.surfaces[ sampler.source ]; + const surface = effect.profile.surfaces[ sampler.source ]; image = getImage( surface.init_from ); } else { @@ -1577,17 +1565,17 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( image !== null ) { - var loader = getTextureLoader( image ); + const loader = getTextureLoader( image ); if ( loader !== undefined ) { - var texture = loader.load( image ); + const texture = loader.load( image ); - var extra = textureObject.extra; + const extra = textureObject.extra; if ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) { - var technique = extra.technique; + const technique = extra.technique; texture.wrapS = technique.wrapU ? RepeatWrapping : ClampToEdgeWrapping; texture.wrapT = technique.wrapV ? RepeatWrapping : ClampToEdgeWrapping; @@ -1622,11 +1610,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var parameters = technique.parameters; + const parameters = technique.parameters; - for ( var key in parameters ) { + for ( const key in parameters ) { - var parameter = parameters[ key ]; + const parameter = parameters[ key ]; switch ( key ) { @@ -1658,8 +1646,8 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var transparent = parameters[ 'transparent' ]; - var transparency = parameters[ 'transparency' ]; + let transparent = parameters[ 'transparent' ]; + let transparency = parameters[ 'transparency' ]; // does not exist but @@ -1695,7 +1683,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else { - var color = transparent.data.color; + const color = transparent.data.color; switch ( transparent.opaque ) { @@ -1744,13 +1732,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseCamera( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ) }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1770,9 +1758,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseCameraOptics( xml ) { - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; switch ( child.nodeName ) { @@ -1789,11 +1777,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseCameraTechnique( xml ) { - var data = {}; + const data = {}; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; switch ( child.nodeName ) { @@ -1815,11 +1803,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseCameraParameters( xml ) { - var data = {}; + const data = {}; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; switch ( child.nodeName ) { @@ -1843,7 +1831,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildCamera( data ) { - var camera; + let camera; switch ( data.optics.technique ) { @@ -1857,9 +1845,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'orthographic': - var ymag = data.optics.parameters.ymag; - var xmag = data.optics.parameters.xmag; - var aspectRatio = data.optics.parameters.aspect_ratio; + let ymag = data.optics.parameters.ymag; + let xmag = data.optics.parameters.xmag; + const aspectRatio = data.optics.parameters.aspect_ratio; xmag = ( xmag === undefined ) ? ( ymag * aspectRatio ) : xmag; ymag = ( ymag === undefined ) ? ( xmag / aspectRatio ) : ymag; @@ -1888,7 +1876,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getCamera( id ) { - var data = library.cameras[ id ]; + const data = library.cameras[ id ]; if ( data !== undefined ) { @@ -1906,11 +1894,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseLight( xml ) { - var data = {}; + let data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1930,11 +1918,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseLightTechnique( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -1958,18 +1946,18 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseLightParameters( xml ) { - var data = {}; + const data = {}; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'color': - var array = parseFloats( child.textContent ); + const array = parseFloats( child.textContent ); data.color = new Color().fromArray( array ); break; @@ -1978,7 +1966,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'quadratic_attenuation': - var f = parseFloat( child.textContent ); + const f = parseFloat( child.textContent ); data.distance = f ? Math.sqrt( 1 / f ) : 0; break; @@ -1992,7 +1980,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildLight( data ) { - var light; + let light; switch ( data.technique ) { @@ -2023,7 +2011,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getLight( id ) { - var data = library.lights[ id ]; + const data = library.lights[ id ]; if ( data !== undefined ) { @@ -2041,25 +2029,25 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseGeometry( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ), sources: {}, vertices: {}, primitives: [] }; - var mesh = getElementsByTagName( xml, 'mesh' )[ 0 ]; + const mesh = getElementsByTagName( xml, 'mesh' )[ 0 ]; // the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep if ( mesh === undefined ) return; - for ( var i = 0; i < mesh.childNodes.length; i ++ ) { + for ( let i = 0; i < mesh.childNodes.length; i ++ ) { - var child = mesh.childNodes[ i ]; + const child = mesh.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; - var id = child.getAttribute( 'id' ); + const id = child.getAttribute( 'id' ); switch ( child.nodeName ) { @@ -2096,14 +2084,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseSource( xml ) { - var data = { + const data = { array: [], stride: 3 }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2118,7 +2106,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'technique_common': - var accessor = getElementsByTagName( child, 'accessor' )[ 0 ]; + const accessor = getElementsByTagName( child, 'accessor' )[ 0 ]; if ( accessor !== undefined ) { @@ -2138,11 +2126,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseGeometryVertices( xml ) { - var data = {}; + const data = {}; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2156,7 +2144,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseGeometryPrimitive( xml ) { - var primitive = { + const primitive = { type: xml.nodeName, material: xml.getAttribute( 'material' ), count: parseInt( xml.getAttribute( 'count' ) ), @@ -2165,20 +2153,20 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { hasUV: false }; - for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) { + for ( let i = 0, l = xml.childNodes.length; i < l; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'input': - var id = parseId( child.getAttribute( 'source' ) ); - var semantic = child.getAttribute( 'semantic' ); - var offset = parseInt( child.getAttribute( 'offset' ) ); - var set = parseInt( child.getAttribute( 'set' ) ); - var inputname = ( set > 0 ? semantic + set : semantic ); + const id = parseId( child.getAttribute( 'source' ) ); + const semantic = child.getAttribute( 'semantic' ); + const offset = parseInt( child.getAttribute( 'offset' ) ); + const set = parseInt( child.getAttribute( 'set' ) ); + const inputname = ( set > 0 ? semantic + set : semantic ); primitive.inputs[ inputname ] = { id: id, offset: offset }; primitive.stride = Math.max( primitive.stride, offset + 1 ); if ( semantic === 'TEXCOORD' ) primitive.hasUV = true; @@ -2202,11 +2190,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function groupPrimitives( primitives ) { - var build = {}; + const build = {}; - for ( var i = 0; i < primitives.length; i ++ ) { + for ( let i = 0; i < primitives.length; i ++ ) { - var primitive = primitives[ i ]; + const primitive = primitives[ i ]; if ( build[ primitive.type ] === undefined ) build[ primitive.type ] = []; @@ -2220,11 +2208,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function checkUVCoordinates( primitives ) { - var count = 0; + let count = 0; - for ( var i = 0, l = primitives.length; i < l; i ++ ) { + for ( let i = 0, l = primitives.length; i < l; i ++ ) { - var primitive = primitives[ i ]; + const primitive = primitives[ i ]; if ( primitive.hasUV === true ) { @@ -2244,22 +2232,22 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildGeometry( data ) { - var build = {}; + const build = {}; - var sources = data.sources; - var vertices = data.vertices; - var primitives = data.primitives; + const sources = data.sources; + const vertices = data.vertices; + const primitives = data.primitives; if ( primitives.length === 0 ) return {}; // our goal is to create one buffer geometry for a single type of primitives // first, we group all primitives by their type - var groupedPrimitives = groupPrimitives( primitives ); + const groupedPrimitives = groupPrimitives( primitives ); - for ( var type in groupedPrimitives ) { + for ( const type in groupedPrimitives ) { - var primitiveType = groupedPrimitives[ type ]; + const primitiveType = groupedPrimitives[ type ]; // second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines) @@ -2277,31 +2265,31 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildGeometryType( primitives, sources, vertices ) { - var build = {}; + const build = {}; - var position = { array: [], stride: 0 }; - var normal = { array: [], stride: 0 }; - var uv = { array: [], stride: 0 }; - var uv2 = { array: [], stride: 0 }; - var color = { array: [], stride: 0 }; + const position = { array: [], stride: 0 }; + const normal = { array: [], stride: 0 }; + const uv = { array: [], stride: 0 }; + const uv2 = { array: [], stride: 0 }; + const color = { array: [], stride: 0 }; - var skinIndex = { array: [], stride: 4 }; - var skinWeight = { array: [], stride: 4 }; + const skinIndex = { array: [], stride: 4 }; + const skinWeight = { array: [], stride: 4 }; - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); - var materialKeys = []; + const materialKeys = []; - var start = 0; + let start = 0; - for ( var p = 0; p < primitives.length; p ++ ) { + for ( let p = 0; p < primitives.length; p ++ ) { - var primitive = primitives[ p ]; - var inputs = primitive.inputs; + const primitive = primitives[ p ]; + const inputs = primitive.inputs; // groups - var count = 0; + let count = 0; switch ( primitive.type ) { @@ -2316,9 +2304,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { case 'polylist': - for ( var g = 0; g < primitive.count; g ++ ) { + for ( let g = 0; g < primitive.count; g ++ ) { - var vc = primitive.vcount[ g ]; + const vc = primitive.vcount[ g ]; switch ( vc ) { @@ -2358,21 +2346,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // geometry data - for ( var name in inputs ) { + for ( const name in inputs ) { - var input = inputs[ name ]; + const input = inputs[ name ]; switch ( name ) { case 'VERTEX': - for ( var key in vertices ) { + for ( const key in vertices ) { - var id = vertices[ key ]; + const id = vertices[ key ]; switch ( key ) { case 'POSITION': - var prevLength = position.array.length; + const prevLength = position.array.length; buildGeometryData( primitive, sources[ id ], input.offset, position.array ); position.stride = sources[ id ].stride; @@ -2387,9 +2375,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( primitive.hasUV === false && primitives.uvsNeedsFix === true ) { - var count = ( position.array.length - prevLength ) / position.stride; + const count = ( position.array.length - prevLength ) / position.stride; - for ( var i = 0; i < count; i ++ ) { + for ( let i = 0; i < count; i ++ ) { // fill missing uv coordinates @@ -2477,14 +2465,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildGeometryData( primitive, source, offset, array ) { - var indices = primitive.p; - var stride = primitive.stride; - var vcount = primitive.vcount; + const indices = primitive.p; + const stride = primitive.stride; + const vcount = primitive.vcount; function pushVector( i ) { - var index = indices[ i + offset ] * sourceStride; - var length = index + sourceStride; + let index = indices[ i + offset ] * sourceStride; + const length = index + sourceStride; for ( ; index < length; index ++ ) { @@ -2494,42 +2482,42 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var sourceArray = source.array; - var sourceStride = source.stride; + const sourceArray = source.array; + const sourceStride = source.stride; if ( primitive.vcount !== undefined ) { - var index = 0; + let index = 0; - for ( var i = 0, l = vcount.length; i < l; i ++ ) { + for ( let i = 0, l = vcount.length; i < l; i ++ ) { - var count = vcount[ i ]; + const count = vcount[ i ]; if ( count === 4 ) { - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; - var d = index + stride * 3; + const a = index + stride * 0; + const b = index + stride * 1; + const c = index + stride * 2; + const d = index + stride * 3; pushVector( a ); pushVector( b ); pushVector( d ); pushVector( b ); pushVector( c ); pushVector( d ); } else if ( count === 3 ) { - var a = index + stride * 0; - var b = index + stride * 1; - var c = index + stride * 2; + const a = index + stride * 0; + const b = index + stride * 1; + const c = index + stride * 2; pushVector( a ); pushVector( b ); pushVector( c ); } else if ( count > 4 ) { - for ( var k = 1, kl = ( count - 2 ); k <= kl; k ++ ) { + for ( let k = 1, kl = ( count - 2 ); k <= kl; k ++ ) { - var a = index + stride * 0; - var b = index + stride * k; - var c = index + stride * ( k + 1 ); + const a = index + stride * 0; + const b = index + stride * k; + const c = index + stride * ( k + 1 ); pushVector( a ); pushVector( b ); pushVector( c ); @@ -2543,7 +2531,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else { - for ( var i = 0, l = indices.length; i < l; i += stride ) { + for ( let i = 0, l = indices.length; i < l; i += stride ) { pushVector( i ); @@ -2563,15 +2551,15 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsModel( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ) || '', joints: {}, links: [] }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2605,9 +2593,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsTechniqueCommon( xml, data ) { - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2629,11 +2617,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsJoint( xml ) { - var data; + let data; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2652,9 +2640,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - function parseKinematicsJointParameter( xml, data ) { + function parseKinematicsJointParameter( xml ) { - var data = { + const data = { sid: xml.getAttribute( 'sid' ), name: xml.getAttribute( 'name' ) || '', axis: new Vector3(), @@ -2668,21 +2656,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { middlePosition: 0 }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'axis': - var array = parseFloats( child.textContent ); + const array = parseFloats( child.textContent ); data.axis.fromArray( array ); break; case 'limits': - var max = child.getElementsByTagName( 'max' )[ 0 ]; - var min = child.getElementsByTagName( 'min' )[ 0 ]; + const max = child.getElementsByTagName( 'max' )[ 0 ]; + const min = child.getElementsByTagName( 'min' )[ 0 ]; data.limits.max = parseFloat( max.textContent ); data.limits.min = parseFloat( min.textContent ); @@ -2710,16 +2698,16 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsLink( xml ) { - var data = { + const data = { sid: xml.getAttribute( 'sid' ), name: xml.getAttribute( 'name' ) || '', attachments: [], transforms: [] }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2745,15 +2733,15 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsAttachment( xml ) { - var data = { + const data = { joint: xml.getAttribute( 'joint' ).split( '/' ).pop(), transforms: [], links: [] }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2779,11 +2767,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsTransform( xml ) { - var data = { + const data = { type: xml.nodeName }; - var array = parseFloats( xml.textContent ); + const array = parseFloats( xml.textContent ); switch ( data.type ) { @@ -2813,14 +2801,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parsePhysicsModel( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ) || '', rigidBodies: {} }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2841,9 +2829,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parsePhysicsRigidBody( xml, data ) { - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2861,9 +2849,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parsePhysicsTechniqueCommon( xml, data ) { - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2887,13 +2875,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsScene( xml ) { - var data = { + const data = { bindJointAxis: [] }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; @@ -2913,22 +2901,22 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseKinematicsBindJointAxis( xml ) { - var data = { + const data = { target: xml.getAttribute( 'target' ).split( '/' ).pop() }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; switch ( child.nodeName ) { case 'axis': - var param = child.getElementsByTagName( 'param' )[ 0 ]; + const param = child.getElementsByTagName( 'param' )[ 0 ]; data.axis = param.textContent; - var tmpJointIndex = data.axis.split( 'inst_' ).pop().split( 'axis' )[ 0 ]; + const tmpJointIndex = data.axis.split( 'inst_' ).pop().split( 'axis' )[ 0 ]; data.jointIndex = tmpJointIndex.substr( 0, tmpJointIndex.length - 1 ); break; @@ -2956,32 +2944,32 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function setupKinematics() { - var kinematicsModelId = Object.keys( library.kinematicsModels )[ 0 ]; - var kinematicsSceneId = Object.keys( library.kinematicsScenes )[ 0 ]; - var visualSceneId = Object.keys( library.visualScenes )[ 0 ]; + const kinematicsModelId = Object.keys( library.kinematicsModels )[ 0 ]; + const kinematicsSceneId = Object.keys( library.kinematicsScenes )[ 0 ]; + const visualSceneId = Object.keys( library.visualScenes )[ 0 ]; if ( kinematicsModelId === undefined || kinematicsSceneId === undefined ) return; - var kinematicsModel = getKinematicsModel( kinematicsModelId ); - var kinematicsScene = getKinematicsScene( kinematicsSceneId ); - var visualScene = getVisualScene( visualSceneId ); + const kinematicsModel = getKinematicsModel( kinematicsModelId ); + const kinematicsScene = getKinematicsScene( kinematicsSceneId ); + const visualScene = getVisualScene( visualSceneId ); - var bindJointAxis = kinematicsScene.bindJointAxis; - var jointMap = {}; + const bindJointAxis = kinematicsScene.bindJointAxis; + const jointMap = {}; - for ( var i = 0, l = bindJointAxis.length; i < l; i ++ ) { + for ( let i = 0, l = bindJointAxis.length; i < l; i ++ ) { - var axis = bindJointAxis[ i ]; + const axis = bindJointAxis[ i ]; // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix' - var targetElement = collada.querySelector( '[sid="' + axis.target + '"]' ); + const targetElement = collada.querySelector( '[sid="' + axis.target + '"]' ); if ( targetElement ) { // get the parent of the transform element - var parentVisualElement = targetElement.parentElement; + const parentVisualElement = targetElement.parentElement; // connect the joint of the kinematics model with the element in the visual scene @@ -2993,8 +2981,8 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function connect( jointIndex, visualElement ) { - var visualElementName = visualElement.getAttribute( 'name' ); - var joint = kinematicsModel.joints[ jointIndex ]; + const visualElementName = visualElement.getAttribute( 'name' ); + const joint = kinematicsModel.joints[ jointIndex ]; visualScene.traverse( function ( object ) { @@ -3013,7 +3001,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var m0 = new Matrix4(); + const m0 = new Matrix4(); kinematics = { @@ -3021,7 +3009,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { getJointValue: function ( jointIndex ) { - var jointData = jointMap[ jointIndex ]; + const jointData = jointMap[ jointIndex ]; if ( jointData ) { @@ -3037,11 +3025,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { setJointValue: function ( jointIndex, value ) { - var jointData = jointMap[ jointIndex ]; + const jointData = jointMap[ jointIndex ]; if ( jointData ) { - var joint = jointData.joint; + const joint = jointData.joint; if ( value > joint.limits.max || value < joint.limits.min ) { @@ -3053,17 +3041,17 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else { - var object = jointData.object; - var axis = joint.axis; - var transforms = jointData.transforms; + const object = jointData.object; + const axis = joint.axis; + const transforms = jointData.transforms; matrix.identity(); // each update, we have to apply all transforms in the correct order - for ( var i = 0; i < transforms.length; i ++ ) { + for ( let i = 0; i < transforms.length; i ++ ) { - var transform = transforms[ i ]; + const transform = transforms[ i ]; // if there is a connection of the transform node with a joint, apply the joint value @@ -3132,21 +3120,23 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildTransformList( node ) { - var transforms = []; + const transforms = []; - var xml = collada.querySelector( '[id="' + node.id + '"]' ); + const xml = collada.querySelector( '[id="' + node.id + '"]' ); - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; + let array, vector; + switch ( child.nodeName ) { case 'matrix': - var array = parseFloats( child.textContent ); - var matrix = new Matrix4().fromArray( array ).transpose(); + array = parseFloats( child.textContent ); + const matrix = new Matrix4().fromArray( array ).transpose(); transforms.push( { sid: child.getAttribute( 'sid' ), type: child.nodeName, @@ -3156,8 +3146,8 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { case 'translate': case 'scale': - var array = parseFloats( child.textContent ); - var vector = new Vector3().fromArray( array ); + array = parseFloats( child.textContent ); + vector = new Vector3().fromArray( array ); transforms.push( { sid: child.getAttribute( 'sid' ), type: child.nodeName, @@ -3166,9 +3156,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'rotate': - var array = parseFloats( child.textContent ); - var vector = new Vector3().fromArray( array ); - var angle = MathUtils.degToRad( array[ 3 ] ); + array = parseFloats( child.textContent ); + vector = new Vector3().fromArray( array ); + const angle = MathUtils.degToRad( array[ 3 ] ); transforms.push( { sid: child.getAttribute( 'sid' ), type: child.nodeName, @@ -3189,13 +3179,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function prepareNodes( xml ) { - var elements = xml.getElementsByTagName( 'node' ); + const elements = xml.getElementsByTagName( 'node' ); // ensure all node elements have id attributes - for ( var i = 0; i < elements.length; i ++ ) { + for ( let i = 0; i < elements.length; i ++ ) { - var element = elements[ i ]; + const element = elements[ i ]; if ( element.hasAttribute( 'id' ) === false ) { @@ -3207,12 +3197,12 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var matrix = new Matrix4(); - var vector = new Vector3(); + const matrix = new Matrix4(); + const vector = new Vector3(); function parseNode( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ) || '', type: xml.getAttribute( 'type' ), id: xml.getAttribute( 'id' ), @@ -3227,12 +3217,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { transforms: {} }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; if ( child.nodeType !== 1 ) continue; + let array; + switch ( child.nodeName ) { case 'node': @@ -3261,27 +3253,27 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'matrix': - var array = parseFloats( child.textContent ); + array = parseFloats( child.textContent ); data.matrix.multiply( matrix.fromArray( array ).transpose() ); data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; break; case 'translate': - var array = parseFloats( child.textContent ); + array = parseFloats( child.textContent ); vector.fromArray( array ); data.matrix.multiply( matrix.makeTranslation( vector.x, vector.y, vector.z ) ); data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; break; case 'rotate': - var array = parseFloats( child.textContent ); - var angle = MathUtils.degToRad( array[ 3 ] ); + array = parseFloats( child.textContent ); + const angle = MathUtils.degToRad( array[ 3 ] ); data.matrix.multiply( matrix.makeRotationAxis( vector.fromArray( array ), angle ) ); data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; break; case 'scale': - var array = parseFloats( child.textContent ); + array = parseFloats( child.textContent ); data.matrix.scale( vector.fromArray( array ) ); data.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName; break; @@ -3312,26 +3304,26 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseNodeInstance( xml ) { - var data = { + const data = { id: parseId( xml.getAttribute( 'url' ) ), materials: {}, skeletons: [] }; - for ( var i = 0; i < xml.childNodes.length; i ++ ) { + for ( let i = 0; i < xml.childNodes.length; i ++ ) { - var child = xml.childNodes[ i ]; + const child = xml.childNodes[ i ]; switch ( child.nodeName ) { case 'bind_material': - var instances = child.getElementsByTagName( 'instance_material' ); + const instances = child.getElementsByTagName( 'instance_material' ); - for ( var j = 0; j < instances.length; j ++ ) { + for ( let j = 0; j < instances.length; j ++ ) { - var instance = instances[ j ]; - var symbol = instance.getAttribute( 'symbol' ); - var target = instance.getAttribute( 'target' ); + const instance = instances[ j ]; + const symbol = instance.getAttribute( 'symbol' ); + const target = instance.getAttribute( 'target' ); data.materials[ symbol ] = parseId( target ); @@ -3356,19 +3348,19 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildSkeleton( skeletons, joints ) { - var boneData = []; - var sortedBoneData = []; + const boneData = []; + const sortedBoneData = []; - var i, j, data; + let i, j, data; // a skeleton can have multiple root bones. collada expresses this // situtation with multiple "skeleton" tags per controller instance for ( i = 0; i < skeletons.length; i ++ ) { - var skeleton = skeletons[ i ]; + const skeleton = skeletons[ i ]; - var root; + let root; if ( hasNode( skeleton ) ) { @@ -3379,16 +3371,16 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // handle case where the skeleton refers to the visual scene (#13335) - var visualScene = library.visualScenes[ skeleton ]; - var children = visualScene.children; + const visualScene = library.visualScenes[ skeleton ]; + const children = visualScene.children; - for ( var j = 0; j < children.length; j ++ ) { + for ( let j = 0; j < children.length; j ++ ) { - var child = children[ j ]; + const child = children[ j ]; if ( child.type === 'JOINT' ) { - var root = getNode( child.id ); + const root = getNode( child.id ); buildBoneHierarchy( root, joints, boneData ); } @@ -3440,8 +3432,8 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // setup arrays for skeleton creation - var bones = []; - var boneInverses = []; + const bones = []; + const boneInverses = []; for ( i = 0; i < sortedBoneData.length; i ++ ) { @@ -3464,13 +3456,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( object.isBone === true ) { - var boneInverse; + let boneInverse; // retrieve the boneInverse from the controller data - for ( var i = 0; i < joints.length; i ++ ) { + for ( let i = 0; i < joints.length; i ++ ) { - var joint = joints[ i ]; + const joint = joints[ i ]; if ( joint.name === object.name ) { @@ -3503,20 +3495,20 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildNode( data ) { - var objects = []; + const objects = []; - var matrix = data.matrix; - var nodes = data.nodes; - var type = data.type; - var instanceCameras = data.instanceCameras; - var instanceControllers = data.instanceControllers; - var instanceLights = data.instanceLights; - var instanceGeometries = data.instanceGeometries; - var instanceNodes = data.instanceNodes; + const matrix = data.matrix; + const nodes = data.nodes; + const type = data.type; + const instanceCameras = data.instanceCameras; + const instanceControllers = data.instanceControllers; + const instanceLights = data.instanceLights; + const instanceGeometries = data.instanceGeometries; + const instanceNodes = data.instanceNodes; // nodes - for ( var i = 0, l = nodes.length; i < l; i ++ ) { + for ( let i = 0, l = nodes.length; i < l; i ++ ) { objects.push( getNode( nodes[ i ] ) ); @@ -3524,9 +3516,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // instance cameras - for ( var i = 0, l = instanceCameras.length; i < l; i ++ ) { + for ( let i = 0, l = instanceCameras.length; i < l; i ++ ) { - var instanceCamera = getCamera( instanceCameras[ i ] ); + const instanceCamera = getCamera( instanceCameras[ i ] ); if ( instanceCamera !== null ) { @@ -3538,21 +3530,21 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // instance controllers - for ( var i = 0, l = instanceControllers.length; i < l; i ++ ) { + for ( let i = 0, l = instanceControllers.length; i < l; i ++ ) { - var instance = instanceControllers[ i ]; - var controller = getController( instance.id ); - var geometries = getGeometry( controller.id ); - var newObjects = buildObjects( geometries, instance.materials ); + const instance = instanceControllers[ i ]; + const controller = getController( instance.id ); + const geometries = getGeometry( controller.id ); + const newObjects = buildObjects( geometries, instance.materials ); - var skeletons = instance.skeletons; - var joints = controller.skin.joints; + const skeletons = instance.skeletons; + const joints = controller.skin.joints; - var skeleton = buildSkeleton( skeletons, joints ); + const skeleton = buildSkeleton( skeletons, joints ); - for ( var j = 0, jl = newObjects.length; j < jl; j ++ ) { + for ( let j = 0, jl = newObjects.length; j < jl; j ++ ) { - var object = newObjects[ j ]; + const object = newObjects[ j ]; if ( object.isSkinnedMesh ) { @@ -3569,9 +3561,9 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // instance lights - for ( var i = 0, l = instanceLights.length; i < l; i ++ ) { + for ( let i = 0, l = instanceLights.length; i < l; i ++ ) { - var instanceLight = getLight( instanceLights[ i ] ); + const instanceLight = getLight( instanceLights[ i ] ); if ( instanceLight !== null ) { @@ -3583,17 +3575,17 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // instance geometries - for ( var i = 0, l = instanceGeometries.length; i < l; i ++ ) { + for ( let i = 0, l = instanceGeometries.length; i < l; i ++ ) { - var instance = instanceGeometries[ i ]; + const instance = instanceGeometries[ i ]; // a single geometry instance in collada can lead to multiple object3Ds. // this is the case when primitives are combined like triangles and lines - var geometries = getGeometry( instance.id ); - var newObjects = buildObjects( geometries, instance.materials ); + const geometries = getGeometry( instance.id ); + const newObjects = buildObjects( geometries, instance.materials ); - for ( var j = 0, jl = newObjects.length; j < jl; j ++ ) { + for ( let j = 0, jl = newObjects.length; j < jl; j ++ ) { objects.push( newObjects[ j ] ); @@ -3603,13 +3595,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // instance nodes - for ( var i = 0, l = instanceNodes.length; i < l; i ++ ) { + for ( let i = 0, l = instanceNodes.length; i < l; i ++ ) { objects.push( getNode( instanceNodes[ i ] ).clone() ); } - var object; + let object; if ( nodes.length === 0 && objects.length === 1 ) { @@ -3619,7 +3611,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { object = ( type === 'JOINT' ) ? new Bone() : new Group(); - for ( var i = 0; i < objects.length; i ++ ) { + for ( let i = 0; i < objects.length; i ++ ) { object.add( objects[ i ] ); @@ -3635,15 +3627,15 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var fallbackMaterial = new MeshBasicMaterial( { color: 0xff00ff } ); + const fallbackMaterial = new MeshBasicMaterial( { color: 0xff00ff } ); function resolveMaterialBinding( keys, instanceMaterials ) { - var materials = []; + const materials = []; - for ( var i = 0, l = keys.length; i < l; i ++ ) { + for ( let i = 0, l = keys.length; i < l; i ++ ) { - var id = instanceMaterials[ keys[ i ] ]; + const id = instanceMaterials[ keys[ i ] ]; if ( id === undefined ) { @@ -3664,13 +3656,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildObjects( geometries, instanceMaterials ) { - var objects = []; + const objects = []; - for ( var type in geometries ) { + for ( const type in geometries ) { - var geometry = geometries[ type ]; + const geometry = geometries[ type ]; - var materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials ); + const materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials ); // handle case if no materials are defined @@ -3690,11 +3682,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // regard skinning - var skinning = ( geometry.data.attributes.skinIndex !== undefined ); + const skinning = ( geometry.data.attributes.skinIndex !== undefined ); if ( skinning ) { - for ( var i = 0, l = materials.length; i < l; i ++ ) { + for ( let i = 0, l = materials.length; i < l; i ++ ) { materials[ i ].skinning = true; @@ -3704,11 +3696,11 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // choose between a single or multi materials (material array) - var material = ( materials.length === 1 ) ? materials[ 0 ] : materials; + const material = ( materials.length === 1 ) ? materials[ 0 ] : materials; // now create a specific 3D object - var object; + let object; switch ( type ) { @@ -3760,16 +3752,16 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseVisualScene( xml ) { - var data = { + const data = { name: xml.getAttribute( 'name' ), children: [] }; prepareNodes( xml ); - var elements = getElementsByTagName( xml, 'node' ); + const elements = getElementsByTagName( xml, 'node' ); - for ( var i = 0; i < elements.length; i ++ ) { + for ( let i = 0; i < elements.length; i ++ ) { data.children.push( parseNode( elements[ i ] ) ); @@ -3781,14 +3773,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildVisualScene( data ) { - var group = new Group(); + const group = new Group(); group.name = data.name; - var children = data.children; + const children = data.children; - for ( var i = 0; i < children.length; i ++ ) { + for ( let i = 0; i < children.length; i ++ ) { - var child = children[ i ]; + const child = children[ i ]; group.add( getNode( child.id ) ); @@ -3814,14 +3806,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseScene( xml ) { - var instance = getElementsByTagName( xml, 'instance_visual_scene' )[ 0 ]; + const instance = getElementsByTagName( xml, 'instance_visual_scene' )[ 0 ]; return getVisualScene( parseId( instance.getAttribute( 'url' ) ) ); } function setupAnimations() { - var clips = library.clips; + const clips = library.clips; if ( isEmpty( clips ) === true ) { @@ -3829,13 +3821,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // if there are animations but no clips, we create a default clip for playback - var tracks = []; + const tracks = []; - for ( var id in library.animations ) { + for ( const id in library.animations ) { - var animationTracks = getAnimation( id ); + const animationTracks = getAnimation( id ); - for ( var i = 0, l = animationTracks.length; i < l; i ++ ) { + for ( let i = 0, l = animationTracks.length; i < l; i ++ ) { tracks.push( animationTracks[ i ] ); @@ -3849,7 +3841,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else { - for ( var id in clips ) { + for ( const id in clips ) { animations.push( getAnimationClip( id ) ); @@ -3864,12 +3856,12 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parserErrorToText( parserError ) { - var result = ''; - var stack = [ parserError ]; + let result = ''; + const stack = [ parserError ]; while ( stack.length ) { - var node = stack.shift(); + const node = stack.shift(); if ( node.nodeType === Node.TEXT_NODE ) { @@ -3894,17 +3886,17 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var xml = new DOMParser().parseFromString( text, 'application/xml' ); + const xml = new DOMParser().parseFromString( text, 'application/xml' ); - var collada = getElementsByTagName( xml, 'COLLADA' )[ 0 ]; + const collada = getElementsByTagName( xml, 'COLLADA' )[ 0 ]; - var parserError = xml.getElementsByTagName( 'parsererror' )[ 0 ]; + const parserError = xml.getElementsByTagName( 'parsererror' )[ 0 ]; if ( parserError !== undefined ) { // Chrome will return parser error with a div in it - var errorElement = getElementsByTagName( parserError, 'div' )[ 0 ]; - var errorText; + const errorElement = getElementsByTagName( parserError, 'div' )[ 0 ]; + let errorText; if ( errorElement ) { @@ -3924,14 +3916,14 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // metadata - var version = collada.getAttribute( 'version' ); + const version = collada.getAttribute( 'version' ); console.log( 'THREE.ColladaLoader: File version', version ); - var asset = parseAsset( getElementsByTagName( collada, 'asset' )[ 0 ] ); - var textureLoader = new TextureLoader( this.manager ); + const asset = parseAsset( getElementsByTagName( collada, 'asset' )[ 0 ] ); + const textureLoader = new TextureLoader( this.manager ); textureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); - var tgaLoader; + let tgaLoader; if ( TGALoader ) { @@ -3942,13 +3934,13 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var animations = []; - var kinematics = {}; - var count = 0; + const animations = []; + let kinematics = {}; + let count = 0; // - var library = { + const library = { animations: {}, clips: {}, controllers: {}, @@ -3994,7 +3986,7 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { setupAnimations(); setupKinematics(); - var scene = parseScene( getElementsByTagName( collada, 'scene' )[ 0 ] ); + const scene = parseScene( getElementsByTagName( collada, 'scene' )[ 0 ] ); scene.animations = animations; if ( asset.upAxis === 'Z_UP' ) { @@ -4019,6 +4011,6 @@ ColladaLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { ColladaLoader }; diff --git a/examples/jsm/loaders/DDSLoader.js b/examples/jsm/loaders/DDSLoader.js index 673cc5fe3f46ae..4a2eb786a60374 100644 --- a/examples/jsm/loaders/DDSLoader.js +++ b/examples/jsm/loaders/DDSLoader.js @@ -7,19 +7,17 @@ import { RGB_S3TC_DXT1_Format } from '../../../build/three.module.js'; -var DDSLoader = function ( manager ) { +class DDSLoader extends CompressedTextureLoader { - CompressedTextureLoader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), { - - constructor: DDSLoader, + } - parse: function ( buffer, loadMipmaps ) { + parse( buffer, loadMipmaps ) { - var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 }; + const dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 }; // Adapted from @toji's DDS utils // https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js @@ -27,36 +25,36 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot // All values and structures referenced from: // http://msdn.microsoft.com/en-us/library/bb943991.aspx/ - var DDS_MAGIC = 0x20534444; - - // var DDSD_CAPS = 0x1; - // var DDSD_HEIGHT = 0x2; - // var DDSD_WIDTH = 0x4; - // var DDSD_PITCH = 0x8; - // var DDSD_PIXELFORMAT = 0x1000; - var DDSD_MIPMAPCOUNT = 0x20000; - // var DDSD_LINEARSIZE = 0x80000; - // var DDSD_DEPTH = 0x800000; - - // var DDSCAPS_COMPLEX = 0x8; - // var DDSCAPS_MIPMAP = 0x400000; - // var DDSCAPS_TEXTURE = 0x1000; - - var DDSCAPS2_CUBEMAP = 0x200; - var DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; - var DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; - var DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; - var DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; - var DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; - var DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; - // var DDSCAPS2_VOLUME = 0x200000; - - // var DDPF_ALPHAPIXELS = 0x1; - // var DDPF_ALPHA = 0x2; - var DDPF_FOURCC = 0x4; - // var DDPF_RGB = 0x40; - // var DDPF_YUV = 0x200; - // var DDPF_LUMINANCE = 0x20000; + const DDS_MAGIC = 0x20534444; + + // let DDSD_CAPS = 0x1; + // let DDSD_HEIGHT = 0x2; + // let DDSD_WIDTH = 0x4; + // let DDSD_PITCH = 0x8; + // let DDSD_PIXELFORMAT = 0x1000; + const DDSD_MIPMAPCOUNT = 0x20000; + // let DDSD_LINEARSIZE = 0x80000; + // let DDSD_DEPTH = 0x800000; + + // let DDSCAPS_COMPLEX = 0x8; + // let DDSCAPS_MIPMAP = 0x400000; + // let DDSCAPS_TEXTURE = 0x1000; + + const DDSCAPS2_CUBEMAP = 0x200; + const DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; + const DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; + const DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; + const DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; + const DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; + const DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; + // let DDSCAPS2_VOLUME = 0x200000; + + // let DDPF_ALPHAPIXELS = 0x1; + // let DDPF_ALPHA = 0x2; + const DDPF_FOURCC = 0x4; + // let DDPF_RGB = 0x40; + // let DDPF_YUV = 0x200; + // let DDPF_LUMINANCE = 0x20000; function fourCCToInt32( value ) { @@ -80,19 +78,19 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot function loadARGBMip( buffer, dataOffset, width, height ) { - var dataLength = width * height * 4; - var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength ); - var byteArray = new Uint8Array( dataLength ); - var dst = 0; - var src = 0; - for ( var y = 0; y < height; y ++ ) { + const dataLength = width * height * 4; + const srcBuffer = new Uint8Array( buffer, dataOffset, dataLength ); + const byteArray = new Uint8Array( dataLength ); + let dst = 0; + let src = 0; + for ( let y = 0; y < height; y ++ ) { - for ( var x = 0; x < width; x ++ ) { + for ( let x = 0; x < width; x ++ ) { - var b = srcBuffer[ src ]; src ++; - var g = srcBuffer[ src ]; src ++; - var r = srcBuffer[ src ]; src ++; - var a = srcBuffer[ src ]; src ++; + const b = srcBuffer[ src ]; src ++; + const g = srcBuffer[ src ]; src ++; + const r = srcBuffer[ src ]; src ++; + const a = srcBuffer[ src ]; src ++; byteArray[ dst ] = r; dst ++; //r byteArray[ dst ] = g; dst ++; //g byteArray[ dst ] = b; dst ++; //b @@ -106,40 +104,40 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot } - var FOURCC_DXT1 = fourCCToInt32( 'DXT1' ); - var FOURCC_DXT3 = fourCCToInt32( 'DXT3' ); - var FOURCC_DXT5 = fourCCToInt32( 'DXT5' ); - var FOURCC_ETC1 = fourCCToInt32( 'ETC1' ); + const FOURCC_DXT1 = fourCCToInt32( 'DXT1' ); + const FOURCC_DXT3 = fourCCToInt32( 'DXT3' ); + const FOURCC_DXT5 = fourCCToInt32( 'DXT5' ); + const FOURCC_ETC1 = fourCCToInt32( 'ETC1' ); - var headerLengthInt = 31; // The header length in 32 bit ints + const headerLengthInt = 31; // The header length in 32 bit ints // Offsets into the header array - var off_magic = 0; + const off_magic = 0; - var off_size = 1; - var off_flags = 2; - var off_height = 3; - var off_width = 4; + const off_size = 1; + const off_flags = 2; + const off_height = 3; + const off_width = 4; - var off_mipmapCount = 7; + const off_mipmapCount = 7; - var off_pfFlags = 20; - var off_pfFourCC = 21; - var off_RGBBitCount = 22; - var off_RBitMask = 23; - var off_GBitMask = 24; - var off_BBitMask = 25; - var off_ABitMask = 26; + const off_pfFlags = 20; + const off_pfFourCC = 21; + const off_RGBBitCount = 22; + const off_RBitMask = 23; + const off_GBitMask = 24; + const off_BBitMask = 25; + const off_ABitMask = 26; - // var off_caps = 27; - var off_caps2 = 28; - // var off_caps3 = 29; - // var off_caps4 = 30; + // let off_caps = 27; + const off_caps2 = 28; + // let off_caps3 = 29; + // let off_caps4 = 30; // Parse header - var header = new Int32Array( buffer, 0, headerLengthInt ); + const header = new Int32Array( buffer, 0, headerLengthInt ); if ( header[ off_magic ] !== DDS_MAGIC ) { @@ -155,11 +153,11 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot } - var blockBytes; + let blockBytes; - var fourCC = header[ off_pfFourCC ]; + const fourCC = header[ off_pfFourCC ]; - var isRGBAUncompressed = false; + let isRGBAUncompressed = false; switch ( fourCC ) { @@ -216,7 +214,7 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot } - var caps2 = header[ off_caps2 ]; + const caps2 = header[ off_caps2 ]; dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false; if ( dds.isCubemap && ( ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) || @@ -235,32 +233,34 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot dds.width = header[ off_width ]; dds.height = header[ off_height ]; - var dataOffset = header[ off_size ] + 4; + let dataOffset = header[ off_size ] + 4; // Extract mipmaps buffers - var faces = dds.isCubemap ? 6 : 1; + const faces = dds.isCubemap ? 6 : 1; + + for ( let face = 0; face < faces; face ++ ) { - for ( var face = 0; face < faces; face ++ ) { + let width = dds.width; + let height = dds.height; - var width = dds.width; - var height = dds.height; + for ( let i = 0; i < dds.mipmapCount; i ++ ) { - for ( var i = 0; i < dds.mipmapCount; i ++ ) { + let byteArray, dataLength; if ( isRGBAUncompressed ) { - var byteArray = loadARGBMip( buffer, dataOffset, width, height ); - var dataLength = byteArray.length; + byteArray = loadARGBMip( buffer, dataOffset, width, height ); + dataLength = byteArray.length; } else { - var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes; - var byteArray = new Uint8Array( buffer, dataOffset, dataLength ); + dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes; + byteArray = new Uint8Array( buffer, dataOffset, dataLength ); } - var mipmap = { 'data': byteArray, 'width': width, 'height': height }; + const mipmap = { 'data': byteArray, 'width': width, 'height': height }; dds.mipmaps.push( mipmap ); dataOffset += dataLength; @@ -276,6 +276,6 @@ DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot } -} ); +} export { DDSLoader }; diff --git a/examples/jsm/loaders/DRACOLoader.js b/examples/jsm/loaders/DRACOLoader.js index 4b2c6b3b966d12..e9f3ca48a39f8a 100644 --- a/examples/jsm/loaders/DRACOLoader.js +++ b/examples/jsm/loaders/DRACOLoader.js @@ -5,87 +5,66 @@ import { Loader } from '../../../build/three.module.js'; -var DRACOLoader = function ( manager ) { +const _taskCache = new WeakMap(); - Loader.call( this, manager ); +class DRACOLoader extends Loader { - this.decoderPath = ''; - this.decoderConfig = {}; - this.decoderBinary = null; - this.decoderPending = null; + constructor( manager ) { - this.workerLimit = 4; - this.workerPool = []; - this.workerNextTaskID = 1; - this.workerSourceURL = ''; + super( manager ); - this.defaultAttributeIDs = { - position: 'POSITION', - normal: 'NORMAL', - color: 'COLOR', - uv: 'TEX_COORD' - }; - this.defaultAttributeTypes = { - position: 'Float32Array', - normal: 'Float32Array', - color: 'Float32Array', - uv: 'Float32Array' - }; + this.decoderPath = ''; + this.decoderConfig = {}; + this.decoderBinary = null; + this.decoderPending = null; -}; + this.workerLimit = 4; + this.workerPool = []; + this.workerNextTaskID = 1; + this.workerSourceURL = ''; -DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + this.defaultAttributeIDs = { + position: 'POSITION', + normal: 'NORMAL', + color: 'COLOR', + uv: 'TEX_COORD' + }; + this.defaultAttributeTypes = { + position: 'Float32Array', + normal: 'Float32Array', + color: 'Float32Array', + uv: 'Float32Array' + }; - constructor: DRACOLoader, + } - setDecoderPath: function ( path ) { + setDecoderPath( path ) { this.decoderPath = path; return this; - }, + } - setDecoderConfig: function ( config ) { + setDecoderConfig( config ) { this.decoderConfig = config; return this; - }, + } - setWorkerLimit: function ( workerLimit ) { + setWorkerLimit( workerLimit ) { this.workerLimit = workerLimit; return this; - }, - - /** @deprecated */ - setVerbosity: function () { - - console.warn( 'THREE.DRACOLoader: The .setVerbosity() method has been removed.' ); - - }, - - /** @deprecated */ - setDrawMode: function () { - - console.warn( 'THREE.DRACOLoader: The .setDrawMode() method has been removed.' ); - - }, - - /** @deprecated */ - setSkipDequantization: function () { - - console.warn( 'THREE.DRACOLoader: The .setSkipDequantization() method has been removed.' ); - - }, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); @@ -94,7 +73,7 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { loader.load( url, ( buffer ) => { - var taskConfig = { + const taskConfig = { attributeIDs: this.defaultAttributeIDs, attributeTypes: this.defaultAttributeTypes, useUniqueIDs: false @@ -106,12 +85,12 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } /** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */ - decodeDracoFile: function ( buffer, callback, attributeIDs, attributeTypes ) { + decodeDracoFile( buffer, callback, attributeIDs, attributeTypes ) { - var taskConfig = { + const taskConfig = { attributeIDs: attributeIDs || this.defaultAttributeIDs, attributeTypes: attributeTypes || this.defaultAttributeTypes, useUniqueIDs: !! attributeIDs @@ -119,16 +98,16 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.decodeGeometry( buffer, taskConfig ).then( callback ); - }, + } - decodeGeometry: function ( buffer, taskConfig ) { + decodeGeometry( buffer, taskConfig ) { // TODO: For backward-compatibility, support 'attributeTypes' objects containing // references (rather than names) to typed array constructors. These must be // serialized before sending them to the worker. - for ( var attribute in taskConfig.attributeTypes ) { + for ( const attribute in taskConfig.attributeTypes ) { - var type = taskConfig.attributeTypes[ attribute ]; + const type = taskConfig.attributeTypes[ attribute ]; if ( type.BYTES_PER_ELEMENT !== undefined ) { @@ -140,13 +119,13 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var taskKey = JSON.stringify( taskConfig ); + const taskKey = JSON.stringify( taskConfig ); // Check for an existing task using this buffer. A transferred buffer cannot be transferred // again from this thread. - if ( DRACOLoader.taskCache.has( buffer ) ) { + if ( _taskCache.has( buffer ) ) { - var cachedTask = DRACOLoader.taskCache.get( buffer ); + const cachedTask = _taskCache.get( buffer ); if ( cachedTask.key === taskKey ) { @@ -171,13 +150,13 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var worker; - var taskID = this.workerNextTaskID ++; - var taskCost = buffer.byteLength; + let worker; + const taskID = this.workerNextTaskID ++; + const taskCost = buffer.byteLength; // Obtain a worker and assign a task, and construct a geometry instance // when the task completes. - var geometryPending = this._getWorker( taskID, taskCost ) + const geometryPending = this._getWorker( taskID, taskCost ) .then( ( _worker ) => { worker = _worker; @@ -212,7 +191,7 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } ); // Cache the task result. - DRACOLoader.taskCache.set( buffer, { + _taskCache.set( buffer, { key: taskKey, promise: geometryPending @@ -221,11 +200,11 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return geometryPending; - }, + } - _createGeometry: function ( geometryData ) { + _createGeometry( geometryData ) { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); if ( geometryData.index ) { @@ -233,12 +212,12 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - for ( var i = 0; i < geometryData.attributes.length; i ++ ) { + for ( let i = 0; i < geometryData.attributes.length; i ++ ) { - var attribute = geometryData.attributes[ i ]; - var name = attribute.name; - var array = attribute.array; - var itemSize = attribute.itemSize; + const attribute = geometryData.attributes[ i ]; + const name = attribute.name; + const array = attribute.array; + const itemSize = attribute.itemSize; geometry.setAttribute( name, new BufferAttribute( array, itemSize ) ); @@ -246,11 +225,11 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return geometry; - }, + } - _loadLibrary: function ( url, responseType ) { + _loadLibrary( url, responseType ) { - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.decoderPath ); loader.setResponseType( responseType ); loader.setWithCredentials( this.withCredentials ); @@ -261,22 +240,22 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } ); - }, + } - preload: function () { + preload() { this._initDecoder(); return this; - }, + } - _initDecoder: function () { + _initDecoder() { if ( this.decoderPending ) return this.decoderPending; - var useJS = typeof WebAssembly !== 'object' || this.decoderConfig.type === 'js'; - var librariesPending = []; + const useJS = typeof WebAssembly !== 'object' || this.decoderConfig.type === 'js'; + const librariesPending = []; if ( useJS ) { @@ -292,7 +271,7 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.decoderPending = Promise.all( librariesPending ) .then( ( libraries ) => { - var jsContent = libraries[ 0 ]; + const jsContent = libraries[ 0 ]; if ( ! useJS ) { @@ -300,9 +279,9 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var fn = DRACOLoader.DRACOWorker.toString(); + const fn = DRACOWorker.toString(); - var body = [ + const body = [ '/* draco decoder */', jsContent, '', @@ -316,15 +295,15 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return this.decoderPending; - }, + } - _getWorker: function ( taskID, taskCost ) { + _getWorker( taskID, taskCost ) { return this._initDecoder().then( () => { if ( this.workerPool.length < this.workerLimit ) { - var worker = new Worker( this.workerSourceURL ); + const worker = new Worker( this.workerSourceURL ); worker._callbacks = {}; worker._taskCosts = {}; @@ -334,7 +313,7 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { worker.onmessage = function ( e ) { - var message = e.data; + const message = e.data; switch ( message.type ) { @@ -365,32 +344,32 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var worker = this.workerPool[ this.workerPool.length - 1 ]; + const worker = this.workerPool[ this.workerPool.length - 1 ]; worker._taskCosts[ taskID ] = taskCost; worker._taskLoad += taskCost; return worker; } ); - }, + } - _releaseTask: function ( worker, taskID ) { + _releaseTask( worker, taskID ) { worker._taskLoad -= worker._taskCosts[ taskID ]; delete worker._callbacks[ taskID ]; delete worker._taskCosts[ taskID ]; - }, + } - debug: function () { + debug() { console.log( 'Task load: ', this.workerPool.map( ( worker ) => worker._taskLoad ) ); - }, + } - dispose: function () { + dispose() { - for ( var i = 0; i < this.workerPool.length; ++ i ) { + for ( let i = 0; i < this.workerPool.length; ++ i ) { this.workerPool[ i ].terminate(); @@ -402,18 +381,18 @@ DRACOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} /* WEB WORKER */ -DRACOLoader.DRACOWorker = function () { +function DRACOWorker() { - var decoderConfig; - var decoderPending; + let decoderConfig; + let decoderPending; onmessage = function ( e ) { - var message = e.data; + const message = e.data; switch ( message.type ) { @@ -434,20 +413,20 @@ DRACOLoader.DRACOWorker = function () { break; case 'decode': - var buffer = message.buffer; - var taskConfig = message.taskConfig; + const buffer = message.buffer; + const taskConfig = message.taskConfig; decoderPending.then( ( module ) => { - var draco = module.draco; - var decoder = new draco.Decoder(); - var decoderBuffer = new draco.DecoderBuffer(); + const draco = module.draco; + const decoder = new draco.Decoder(); + const decoderBuffer = new draco.DecoderBuffer(); decoderBuffer.Init( new Int8Array( buffer ), buffer.byteLength ); try { - var geometry = decodeGeometry( draco, decoder, decoderBuffer, taskConfig ); + const geometry = decodeGeometry( draco, decoder, decoderBuffer, taskConfig ); - var buffers = geometry.attributes.map( ( attr ) => attr.array.buffer ); + const buffers = geometry.attributes.map( ( attr ) => attr.array.buffer ); if ( geometry.index ) buffers.push( geometry.index.array.buffer ); @@ -475,13 +454,13 @@ DRACOLoader.DRACOWorker = function () { function decodeGeometry( draco, decoder, decoderBuffer, taskConfig ) { - var attributeIDs = taskConfig.attributeIDs; - var attributeTypes = taskConfig.attributeTypes; + const attributeIDs = taskConfig.attributeIDs; + const attributeTypes = taskConfig.attributeTypes; - var dracoGeometry; - var decodingStatus; + let dracoGeometry; + let decodingStatus; - var geometryType = decoder.GetEncodedGeometryType( decoderBuffer ); + const geometryType = decoder.GetEncodedGeometryType( decoderBuffer ); if ( geometryType === draco.TRIANGULAR_MESH ) { @@ -505,15 +484,15 @@ DRACOLoader.DRACOWorker = function () { } - var geometry = { index: null, attributes: [] }; + const geometry = { index: null, attributes: [] }; // Gather all vertex attributes. - for ( var attributeName in attributeIDs ) { + for ( const attributeName in attributeIDs ) { - var attributeType = self[ attributeTypes[ attributeName ] ]; + const attributeType = self[ attributeTypes[ attributeName ] ]; - var attribute; - var attributeID; + let attribute; + let attributeID; // A Draco file may be created with default vertex attributes, whose attribute IDs // are mapped 1:1 from their semantic name (POSITION, NORMAL, ...). Alternatively, @@ -553,13 +532,13 @@ DRACOLoader.DRACOWorker = function () { function decodeIndex( draco, decoder, dracoGeometry ) { - var numFaces = dracoGeometry.num_faces(); - var numIndices = numFaces * 3; - var byteLength = numIndices * 4; + const numFaces = dracoGeometry.num_faces(); + const numIndices = numFaces * 3; + const byteLength = numIndices * 4; - var ptr = draco._malloc( byteLength ); + const ptr = draco._malloc( byteLength ); decoder.GetTrianglesUInt32Array( dracoGeometry, byteLength, ptr ); - var index = new Uint32Array( draco.HEAPF32.buffer, ptr, numIndices ).slice(); + const index = new Uint32Array( draco.HEAPF32.buffer, ptr, numIndices ).slice(); draco._free( ptr ); return { array: index, itemSize: 1 }; @@ -568,15 +547,15 @@ DRACOLoader.DRACOWorker = function () { function decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) { - var numComponents = attribute.num_components(); - var numPoints = dracoGeometry.num_points(); - var numValues = numPoints * numComponents; - var byteLength = numValues * attributeType.BYTES_PER_ELEMENT; - var dataType = getDracoDataType( draco, attributeType ); + const numComponents = attribute.num_components(); + const numPoints = dracoGeometry.num_points(); + const numValues = numPoints * numComponents; + const byteLength = numValues * attributeType.BYTES_PER_ELEMENT; + const dataType = getDracoDataType( draco, attributeType ); - var ptr = draco._malloc( byteLength ); + const ptr = draco._malloc( byteLength ); decoder.GetAttributeDataArrayForAllPoints( dracoGeometry, attribute, dataType, byteLength, ptr ); - var array = new attributeType( draco.HEAPF32.buffer, ptr, numValues ).slice(); + const array = new attributeType( draco.HEAPF32.buffer, ptr, numValues ).slice(); draco._free( ptr ); return { @@ -603,38 +582,6 @@ DRACOLoader.DRACOWorker = function () { } -}; - -DRACOLoader.taskCache = new WeakMap(); - -/** Deprecated static methods */ - -/** @deprecated */ -DRACOLoader.setDecoderPath = function () { - - console.warn( 'THREE.DRACOLoader: The .setDecoderPath() method has been removed. Use instance methods.' ); - -}; - -/** @deprecated */ -DRACOLoader.setDecoderConfig = function () { - - console.warn( 'THREE.DRACOLoader: The .setDecoderConfig() method has been removed. Use instance methods.' ); - -}; - -/** @deprecated */ -DRACOLoader.releaseDecoderModule = function () { - - console.warn( 'THREE.DRACOLoader: The .releaseDecoderModule() method has been removed. Use instance methods.' ); - -}; - -/** @deprecated */ -DRACOLoader.getDecoderModule = function () { - - console.warn( 'THREE.DRACOLoader: The .getDecoderModule() method has been removed. Use instance methods.' ); - -}; +} export { DRACOLoader }; diff --git a/examples/jsm/loaders/EXRLoader.js b/examples/jsm/loaders/EXRLoader.js index 93312a5d1d96ea..f5c28d08e15d64 100644 --- a/examples/jsm/loaders/EXRLoader.js +++ b/examples/jsm/loaders/EXRLoader.js @@ -12,7 +12,7 @@ import { RGBFormat, UnsignedByteType } from '../../../build/three.module.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; /** * OpenEXR loader currently supports uncompressed, ZIP(S), RLE, PIZ and DWA/B compression. @@ -87,19 +87,17 @@ import * as fflate from '../libs/fflate.module.min.js'; // // End of OpenEXR license ------------------------------------------------- -var EXRLoader = function ( manager ) { +class EXRLoader extends DataTextureLoader { - DataTextureLoader.call( this, manager ); + constructor( manager ) { - this.type = FloatType; + super( manager ); -}; + this.type = FloatType; -EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype ), { - - constructor: EXRLoader, + } - parse: function ( buffer ) { + parse( buffer ) { const USHORT_RANGE = ( 1 << 16 ); const BITMAP_SIZE = ( USHORT_RANGE >> 3 ); @@ -2366,16 +2364,16 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype type: this.type }; - }, + } - setDataType: function ( value ) { + setDataType( value ) { this.type = value; return this; - }, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { function onLoadCallback( texture, texData ) { @@ -2406,10 +2404,10 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype } - return DataTextureLoader.prototype.load.call( this, url, onLoadCallback, onProgress, onError ); + return super.load( url, onLoadCallback, onProgress, onError ); } -} ); +} export { EXRLoader }; diff --git a/examples/jsm/loaders/FBXLoader.js b/examples/jsm/loaders/FBXLoader.js index 8b851bb9125918..3432766575b05d 100644 --- a/examples/jsm/loaders/FBXLoader.js +++ b/examples/jsm/loaders/FBXLoader.js @@ -42,7 +42,7 @@ import { VectorKeyframeTrack, sRGBEncoding } from '../../../build/three.module.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; import { NURBSCurve } from '../curves/NURBSCurve.js'; /** @@ -62,205 +62,197 @@ import { NURBSCurve } from '../curves/NURBSCurve.js'; */ -var FBXLoader = ( function () { +let fbxTree; +let connections; +let sceneGraph; - var fbxTree; - var connections; - var sceneGraph; +class FBXLoader extends Loader { - function FBXLoader( manager ) { + constructor( manager ) { - Loader.call( this, manager ); + super( manager ); } - FBXLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + load( url, onLoad, onProgress, onError ) { - constructor: FBXLoader, + const scope = this; - load: function ( url, onLoad, onProgress, onError ) { + const path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; - var scope = this; + const loader = new FileLoader( this.manager ); + loader.setPath( scope.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); - var path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; + loader.load( url, function ( buffer ) { - var loader = new FileLoader( this.manager ); - loader.setPath( scope.path ); - loader.setResponseType( 'arraybuffer' ); - loader.setRequestHeader( scope.requestHeader ); - loader.setWithCredentials( scope.withCredentials ); + try { - loader.load( url, function ( buffer ) { + onLoad( scope.parse( buffer, path ) ); - try { + } catch ( e ) { - onLoad( scope.parse( buffer, path ) ); + if ( onError ) { - } catch ( e ) { + onError( e ); - if ( onError ) { - - onError( e ); + } else { - } else { + console.error( e ); - console.error( e ); + } - } + scope.manager.itemError( url ); - scope.manager.itemError( url ); + } - } + }, onProgress, onError ); - }, onProgress, onError ); + } - }, + parse( FBXBuffer, path ) { - parse: function ( FBXBuffer, path ) { + if ( isFbxFormatBinary( FBXBuffer ) ) { - if ( isFbxFormatBinary( FBXBuffer ) ) { + fbxTree = new BinaryParser().parse( FBXBuffer ); - fbxTree = new BinaryParser().parse( FBXBuffer ); + } else { - } else { + const FBXText = convertArrayBufferToString( FBXBuffer ); - var FBXText = convertArrayBufferToString( FBXBuffer ); + if ( ! isFbxFormatASCII( FBXText ) ) { - if ( ! isFbxFormatASCII( FBXText ) ) { + throw new Error( 'THREE.FBXLoader: Unknown format.' ); - throw new Error( 'THREE.FBXLoader: Unknown format.' ); + } - } + if ( getFbxVersion( FBXText ) < 7000 ) { - if ( getFbxVersion( FBXText ) < 7000 ) { + throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion( FBXText ) ); - throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion( FBXText ) ); + } - } + fbxTree = new TextParser().parse( FBXText ); - fbxTree = new TextParser().parse( FBXText ); + } - } + // console.log( fbxTree ); - // console.log( fbxTree ); + const textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); - var textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); + return new FBXTreeParser( textureLoader, this.manager ).parse( fbxTree ); - return new FBXTreeParser( textureLoader, this.manager ).parse( fbxTree ); + } - } +} - } ); +// Parse the FBXTree object returned by the BinaryParser or TextParser and return a Group +class FBXTreeParser { - // Parse the FBXTree object returned by the BinaryParser or TextParser and return a Group - function FBXTreeParser( textureLoader, manager ) { + constructor( textureLoader, manager ) { this.textureLoader = textureLoader; this.manager = manager; } - FBXTreeParser.prototype = { - - constructor: FBXTreeParser, + parse() { - parse: function () { + connections = this.parseConnections(); - connections = this.parseConnections(); + const images = this.parseImages(); + const textures = this.parseTextures( images ); + const materials = this.parseMaterials( textures ); + const deformers = this.parseDeformers(); + const geometryMap = new GeometryParser().parse( deformers ); - var images = this.parseImages(); - var textures = this.parseTextures( images ); - var materials = this.parseMaterials( textures ); - var deformers = this.parseDeformers(); - var geometryMap = new GeometryParser().parse( deformers ); + this.parseScene( deformers, geometryMap, materials ); - this.parseScene( deformers, geometryMap, materials ); + return sceneGraph; - return sceneGraph; - - }, + } - // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry ) - // and details the connection type - parseConnections: function () { + // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry ) + // and details the connection type + parseConnections() { - var connectionMap = new Map(); + const connectionMap = new Map(); - if ( 'Connections' in fbxTree ) { + if ( 'Connections' in fbxTree ) { - var rawConnections = fbxTree.Connections.connections; + const rawConnections = fbxTree.Connections.connections; - rawConnections.forEach( function ( rawConnection ) { + rawConnections.forEach( function ( rawConnection ) { - var fromID = rawConnection[ 0 ]; - var toID = rawConnection[ 1 ]; - var relationship = rawConnection[ 2 ]; + const fromID = rawConnection[ 0 ]; + const toID = rawConnection[ 1 ]; + const relationship = rawConnection[ 2 ]; - if ( ! connectionMap.has( fromID ) ) { + if ( ! connectionMap.has( fromID ) ) { - connectionMap.set( fromID, { - parents: [], - children: [] - } ); - - } + connectionMap.set( fromID, { + parents: [], + children: [] + } ); - var parentRelationship = { ID: toID, relationship: relationship }; - connectionMap.get( fromID ).parents.push( parentRelationship ); + } - if ( ! connectionMap.has( toID ) ) { + const parentRelationship = { ID: toID, relationship: relationship }; + connectionMap.get( fromID ).parents.push( parentRelationship ); - connectionMap.set( toID, { - parents: [], - children: [] - } ); + if ( ! connectionMap.has( toID ) ) { - } + connectionMap.set( toID, { + parents: [], + children: [] + } ); - var childRelationship = { ID: fromID, relationship: relationship }; - connectionMap.get( toID ).children.push( childRelationship ); + } - } ); + const childRelationship = { ID: fromID, relationship: relationship }; + connectionMap.get( toID ).children.push( childRelationship ); - } + } ); - return connectionMap; + } - }, + return connectionMap; - // Parse FBXTree.Objects.Video for embedded image data - // These images are connected to textures in FBXTree.Objects.Textures - // via FBXTree.Connections. - parseImages: function () { + } - var images = {}; - var blobs = {}; + // Parse FBXTree.Objects.Video for embedded image data + // These images are connected to textures in FBXTree.Objects.Textures + // via FBXTree.Connections. + parseImages() { - if ( 'Video' in fbxTree.Objects ) { + const images = {}; + const blobs = {}; - var videoNodes = fbxTree.Objects.Video; + if ( 'Video' in fbxTree.Objects ) { - for ( var nodeID in videoNodes ) { + const videoNodes = fbxTree.Objects.Video; - var videoNode = videoNodes[ nodeID ]; + for ( const nodeID in videoNodes ) { - var id = parseInt( nodeID ); + const videoNode = videoNodes[ nodeID ]; - images[ id ] = videoNode.RelativeFilename || videoNode.Filename; + const id = parseInt( nodeID ); - // raw image data is in videoNode.Content - if ( 'Content' in videoNode ) { + images[ id ] = videoNode.RelativeFilename || videoNode.Filename; - var arrayBufferContent = ( videoNode.Content instanceof ArrayBuffer ) && ( videoNode.Content.byteLength > 0 ); - var base64Content = ( typeof videoNode.Content === 'string' ) && ( videoNode.Content !== '' ); + // raw image data is in videoNode.Content + if ( 'Content' in videoNode ) { - if ( arrayBufferContent || base64Content ) { + const arrayBufferContent = ( videoNode.Content instanceof ArrayBuffer ) && ( videoNode.Content.byteLength > 0 ); + const base64Content = ( typeof videoNode.Content === 'string' ) && ( videoNode.Content !== '' ); - var image = this.parseImage( videoNodes[ nodeID ] ); + if ( arrayBufferContent || base64Content ) { - blobs[ videoNode.RelativeFilename || videoNode.Filename ] = image; + const image = this.parseImage( videoNodes[ nodeID ] ); - } + blobs[ videoNode.RelativeFilename || videoNode.Filename ] = image; } @@ -268,1170 +260,1170 @@ var FBXLoader = ( function () { } - for ( var id in images ) { + } - var filename = images[ id ]; + for ( const id in images ) { - if ( blobs[ filename ] !== undefined ) images[ id ] = blobs[ filename ]; - else images[ id ] = images[ id ].split( '\\' ).pop(); + const filename = images[ id ]; - } + if ( blobs[ filename ] !== undefined ) images[ id ] = blobs[ filename ]; + else images[ id ] = images[ id ].split( '\\' ).pop(); - return images; + } - }, + return images; - // Parse embedded image data in FBXTree.Video.Content - parseImage: function ( videoNode ) { + } - var content = videoNode.Content; - var fileName = videoNode.RelativeFilename || videoNode.Filename; - var extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase(); + // Parse embedded image data in FBXTree.Video.Content + parseImage( videoNode ) { - var type; + const content = videoNode.Content; + const fileName = videoNode.RelativeFilename || videoNode.Filename; + const extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase(); - switch ( extension ) { + let type; - case 'bmp': + switch ( extension ) { - type = 'image/bmp'; - break; + case 'bmp': - case 'jpg': - case 'jpeg': + type = 'image/bmp'; + break; - type = 'image/jpeg'; - break; + case 'jpg': + case 'jpeg': - case 'png': + type = 'image/jpeg'; + break; - type = 'image/png'; - break; + case 'png': - case 'tif': + type = 'image/png'; + break; - type = 'image/tiff'; - break; + case 'tif': - case 'tga': + type = 'image/tiff'; + break; - if ( this.manager.getHandler( '.tga' ) === null ) { + case 'tga': - console.warn( 'FBXLoader: TGA loader not found, skipping ', fileName ); + if ( this.manager.getHandler( '.tga' ) === null ) { - } + console.warn( 'FBXLoader: TGA loader not found, skipping ', fileName ); - type = 'image/tga'; - break; + } - default: + type = 'image/tga'; + break; - console.warn( 'FBXLoader: Image type "' + extension + '" is not supported.' ); - return; + default: - } + console.warn( 'FBXLoader: Image type "' + extension + '" is not supported.' ); + return; - if ( typeof content === 'string' ) { // ASCII format + } - return 'data:' + type + ';base64,' + content; + if ( typeof content === 'string' ) { // ASCII format - } else { // Binary Format + return 'data:' + type + ';base64,' + content; - var array = new Uint8Array( content ); - return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) ); + } else { // Binary Format - } + const array = new Uint8Array( content ); + return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) ); - }, + } - // Parse nodes in FBXTree.Objects.Texture - // These contain details such as UV scaling, cropping, rotation etc and are connected - // to images in FBXTree.Objects.Video - parseTextures: function ( images ) { + } - var textureMap = new Map(); + // Parse nodes in FBXTree.Objects.Texture + // These contain details such as UV scaling, cropping, rotation etc and are connected + // to images in FBXTree.Objects.Video + parseTextures( images ) { - if ( 'Texture' in fbxTree.Objects ) { + const textureMap = new Map(); - var textureNodes = fbxTree.Objects.Texture; - for ( var nodeID in textureNodes ) { + if ( 'Texture' in fbxTree.Objects ) { - var texture = this.parseTexture( textureNodes[ nodeID ], images ); - textureMap.set( parseInt( nodeID ), texture ); + const textureNodes = fbxTree.Objects.Texture; + for ( const nodeID in textureNodes ) { - } + const texture = this.parseTexture( textureNodes[ nodeID ], images ); + textureMap.set( parseInt( nodeID ), texture ); } - return textureMap; + } - }, + return textureMap; - // Parse individual node in FBXTree.Objects.Texture - parseTexture: function ( textureNode, images ) { + } - var texture = this.loadTexture( textureNode, images ); + // Parse individual node in FBXTree.Objects.Texture + parseTexture( textureNode, images ) { - texture.ID = textureNode.id; + const texture = this.loadTexture( textureNode, images ); - texture.name = textureNode.attrName; + texture.ID = textureNode.id; - var wrapModeU = textureNode.WrapModeU; - var wrapModeV = textureNode.WrapModeV; + texture.name = textureNode.attrName; - var valueU = wrapModeU !== undefined ? wrapModeU.value : 0; - var valueV = wrapModeV !== undefined ? wrapModeV.value : 0; + const wrapModeU = textureNode.WrapModeU; + const wrapModeV = textureNode.WrapModeV; - // http://download.autodesk.com/us/fbx/SDKdocs/FBX_SDK_Help/files/fbxsdkref/class_k_fbx_texture.html#889640e63e2e681259ea81061b85143a - // 0: repeat(default), 1: clamp + const valueU = wrapModeU !== undefined ? wrapModeU.value : 0; + const valueV = wrapModeV !== undefined ? wrapModeV.value : 0; - texture.wrapS = valueU === 0 ? RepeatWrapping : ClampToEdgeWrapping; - texture.wrapT = valueV === 0 ? RepeatWrapping : ClampToEdgeWrapping; + // http://download.autodesk.com/us/fbx/SDKdocs/FBX_SDK_Help/files/fbxsdkref/class_k_fbx_texture.html#889640e63e2e681259ea81061b85143a + // 0: repeat(default), 1: clamp - if ( 'Scaling' in textureNode ) { + texture.wrapS = valueU === 0 ? RepeatWrapping : ClampToEdgeWrapping; + texture.wrapT = valueV === 0 ? RepeatWrapping : ClampToEdgeWrapping; - var values = textureNode.Scaling.value; + if ( 'Scaling' in textureNode ) { - texture.repeat.x = values[ 0 ]; - texture.repeat.y = values[ 1 ]; + const values = textureNode.Scaling.value; - } + texture.repeat.x = values[ 0 ]; + texture.repeat.y = values[ 1 ]; - return texture; + } - }, + return texture; - // load a texture specified as a blob or data URI, or via an external URL using TextureLoader - loadTexture: function ( textureNode, images ) { + } - var fileName; + // load a texture specified as a blob or data URI, or via an external URL using TextureLoader + loadTexture( textureNode, images ) { - var currentPath = this.textureLoader.path; + let fileName; - var children = connections.get( textureNode.id ).children; + const currentPath = this.textureLoader.path; - if ( children !== undefined && children.length > 0 && images[ children[ 0 ].ID ] !== undefined ) { + const children = connections.get( textureNode.id ).children; - fileName = images[ children[ 0 ].ID ]; + if ( children !== undefined && children.length > 0 && images[ children[ 0 ].ID ] !== undefined ) { - if ( fileName.indexOf( 'blob:' ) === 0 || fileName.indexOf( 'data:' ) === 0 ) { + fileName = images[ children[ 0 ].ID ]; - this.textureLoader.setPath( undefined ); + if ( fileName.indexOf( 'blob:' ) === 0 || fileName.indexOf( 'data:' ) === 0 ) { - } + this.textureLoader.setPath( undefined ); } - var texture; + } - var extension = textureNode.FileName.slice( - 3 ).toLowerCase(); + let texture; - if ( extension === 'tga' ) { + const extension = textureNode.FileName.slice( - 3 ).toLowerCase(); - var loader = this.manager.getHandler( '.tga' ); + if ( extension === 'tga' ) { - if ( loader === null ) { + const loader = this.manager.getHandler( '.tga' ); - console.warn( 'FBXLoader: TGA loader not found, creating placeholder texture for', textureNode.RelativeFilename ); - texture = new Texture(); + if ( loader === null ) { - } else { + console.warn( 'FBXLoader: TGA loader not found, creating placeholder texture for', textureNode.RelativeFilename ); + texture = new Texture(); - texture = loader.load( fileName ); + } else { - } + texture = loader.load( fileName ); - } else if ( extension === 'psd' ) { + } - console.warn( 'FBXLoader: PSD textures are not supported, creating placeholder texture for', textureNode.RelativeFilename ); - texture = new Texture(); + } else if ( extension === 'psd' ) { - } else { + console.warn( 'FBXLoader: PSD textures are not supported, creating placeholder texture for', textureNode.RelativeFilename ); + texture = new Texture(); - texture = this.textureLoader.load( fileName ); + } else { - } + texture = this.textureLoader.load( fileName ); - this.textureLoader.setPath( currentPath ); + } - return texture; + this.textureLoader.setPath( currentPath ); - }, + return texture; - // Parse nodes in FBXTree.Objects.Material - parseMaterials: function ( textureMap ) { + } - var materialMap = new Map(); + // Parse nodes in FBXTree.Objects.Material + parseMaterials( textureMap ) { - if ( 'Material' in fbxTree.Objects ) { + const materialMap = new Map(); - var materialNodes = fbxTree.Objects.Material; + if ( 'Material' in fbxTree.Objects ) { - for ( var nodeID in materialNodes ) { + const materialNodes = fbxTree.Objects.Material; - var material = this.parseMaterial( materialNodes[ nodeID ], textureMap ); + for ( const nodeID in materialNodes ) { - if ( material !== null ) materialMap.set( parseInt( nodeID ), material ); + const material = this.parseMaterial( materialNodes[ nodeID ], textureMap ); - } + if ( material !== null ) materialMap.set( parseInt( nodeID ), material ); } - return materialMap; + } - }, + return materialMap; - // Parse single node in FBXTree.Objects.Material - // Materials are connected to texture maps in FBXTree.Objects.Textures - // FBX format currently only supports Lambert and Phong shading models - parseMaterial: function ( materialNode, textureMap ) { + } - var ID = materialNode.id; - var name = materialNode.attrName; - var type = materialNode.ShadingModel; + // Parse single node in FBXTree.Objects.Material + // Materials are connected to texture maps in FBXTree.Objects.Textures + // FBX format currently only supports Lambert and Phong shading models + parseMaterial( materialNode, textureMap ) { - // Case where FBX wraps shading model in property object. - if ( typeof type === 'object' ) { + const ID = materialNode.id; + const name = materialNode.attrName; + let type = materialNode.ShadingModel; - type = type.value; + // Case where FBX wraps shading model in property object. + if ( typeof type === 'object' ) { - } + type = type.value; - // Ignore unused materials which don't have any connections. - if ( ! connections.has( ID ) ) return null; + } - var parameters = this.parseParameters( materialNode, textureMap, ID ); + // Ignore unused materials which don't have any connections. + if ( ! connections.has( ID ) ) return null; - var material; + const parameters = this.parseParameters( materialNode, textureMap, ID ); - switch ( type.toLowerCase() ) { + let material; - case 'phong': - material = new MeshPhongMaterial(); - break; - case 'lambert': - material = new MeshLambertMaterial(); - break; - default: - console.warn( 'THREE.FBXLoader: unknown material type "%s". Defaulting to MeshPhongMaterial.', type ); - material = new MeshPhongMaterial(); - break; + switch ( type.toLowerCase() ) { - } + case 'phong': + material = new MeshPhongMaterial(); + break; + case 'lambert': + material = new MeshLambertMaterial(); + break; + default: + console.warn( 'THREE.FBXLoader: unknown material type "%s". Defaulting to MeshPhongMaterial.', type ); + material = new MeshPhongMaterial(); + break; - material.setValues( parameters ); - material.name = name; + } - return material; + material.setValues( parameters ); + material.name = name; - }, + return material; - // Parse FBX material and return parameters suitable for a three.js material - // Also parse the texture map and return any textures associated with the material - parseParameters: function ( materialNode, textureMap, ID ) { + } - var parameters = {}; + // Parse FBX material and return parameters suitable for a three.js material + // Also parse the texture map and return any textures associated with the material + parseParameters( materialNode, textureMap, ID ) { - if ( materialNode.BumpFactor ) { + const parameters = {}; - parameters.bumpScale = materialNode.BumpFactor.value; + if ( materialNode.BumpFactor ) { - } + parameters.bumpScale = materialNode.BumpFactor.value; - if ( materialNode.Diffuse ) { + } - parameters.color = new Color().fromArray( materialNode.Diffuse.value ); + if ( materialNode.Diffuse ) { - } else if ( materialNode.DiffuseColor && ( materialNode.DiffuseColor.type === 'Color' || materialNode.DiffuseColor.type === 'ColorRGB' ) ) { + parameters.color = new Color().fromArray( materialNode.Diffuse.value ); - // The blender exporter exports diffuse here instead of in materialNode.Diffuse - parameters.color = new Color().fromArray( materialNode.DiffuseColor.value ); + } else if ( materialNode.DiffuseColor && ( materialNode.DiffuseColor.type === 'Color' || materialNode.DiffuseColor.type === 'ColorRGB' ) ) { - } + // The blender exporter exports diffuse here instead of in materialNode.Diffuse + parameters.color = new Color().fromArray( materialNode.DiffuseColor.value ); - if ( materialNode.DisplacementFactor ) { + } - parameters.displacementScale = materialNode.DisplacementFactor.value; + if ( materialNode.DisplacementFactor ) { - } + parameters.displacementScale = materialNode.DisplacementFactor.value; - if ( materialNode.Emissive ) { + } - parameters.emissive = new Color().fromArray( materialNode.Emissive.value ); + if ( materialNode.Emissive ) { - } else if ( materialNode.EmissiveColor && ( materialNode.EmissiveColor.type === 'Color' || materialNode.EmissiveColor.type === 'ColorRGB' ) ) { + parameters.emissive = new Color().fromArray( materialNode.Emissive.value ); - // The blender exporter exports emissive color here instead of in materialNode.Emissive - parameters.emissive = new Color().fromArray( materialNode.EmissiveColor.value ); + } else if ( materialNode.EmissiveColor && ( materialNode.EmissiveColor.type === 'Color' || materialNode.EmissiveColor.type === 'ColorRGB' ) ) { - } + // The blender exporter exports emissive color here instead of in materialNode.Emissive + parameters.emissive = new Color().fromArray( materialNode.EmissiveColor.value ); - if ( materialNode.EmissiveFactor ) { + } - parameters.emissiveIntensity = parseFloat( materialNode.EmissiveFactor.value ); + if ( materialNode.EmissiveFactor ) { - } + parameters.emissiveIntensity = parseFloat( materialNode.EmissiveFactor.value ); - if ( materialNode.Opacity ) { + } - parameters.opacity = parseFloat( materialNode.Opacity.value ); + if ( materialNode.Opacity ) { - } + parameters.opacity = parseFloat( materialNode.Opacity.value ); - if ( parameters.opacity < 1.0 ) { + } - parameters.transparent = true; + if ( parameters.opacity < 1.0 ) { - } + parameters.transparent = true; - if ( materialNode.ReflectionFactor ) { + } - parameters.reflectivity = materialNode.ReflectionFactor.value; + if ( materialNode.ReflectionFactor ) { - } + parameters.reflectivity = materialNode.ReflectionFactor.value; - if ( materialNode.Shininess ) { + } - parameters.shininess = materialNode.Shininess.value; + if ( materialNode.Shininess ) { - } + parameters.shininess = materialNode.Shininess.value; - if ( materialNode.Specular ) { + } - parameters.specular = new Color().fromArray( materialNode.Specular.value ); + if ( materialNode.Specular ) { - } else if ( materialNode.SpecularColor && materialNode.SpecularColor.type === 'Color' ) { + parameters.specular = new Color().fromArray( materialNode.Specular.value ); - // The blender exporter exports specular color here instead of in materialNode.Specular - parameters.specular = new Color().fromArray( materialNode.SpecularColor.value ); + } else if ( materialNode.SpecularColor && materialNode.SpecularColor.type === 'Color' ) { - } + // The blender exporter exports specular color here instead of in materialNode.Specular + parameters.specular = new Color().fromArray( materialNode.SpecularColor.value ); - var scope = this; - connections.get( ID ).children.forEach( function ( child ) { + } - var type = child.relationship; + const scope = this; + connections.get( ID ).children.forEach( function ( child ) { - switch ( type ) { + const type = child.relationship; - case 'Bump': - parameters.bumpMap = scope.getTexture( textureMap, child.ID ); - break; + switch ( type ) { - case 'Maya|TEX_ao_map': - parameters.aoMap = scope.getTexture( textureMap, child.ID ); - break; + case 'Bump': + parameters.bumpMap = scope.getTexture( textureMap, child.ID ); + break; - case 'DiffuseColor': - case 'Maya|TEX_color_map': - parameters.map = scope.getTexture( textureMap, child.ID ); - parameters.map.encoding = sRGBEncoding; - break; + case 'Maya|TEX_ao_map': + parameters.aoMap = scope.getTexture( textureMap, child.ID ); + break; - case 'DisplacementColor': - parameters.displacementMap = scope.getTexture( textureMap, child.ID ); - break; + case 'DiffuseColor': + case 'Maya|TEX_color_map': + parameters.map = scope.getTexture( textureMap, child.ID ); + parameters.map.encoding = sRGBEncoding; + break; - case 'EmissiveColor': - parameters.emissiveMap = scope.getTexture( textureMap, child.ID ); - parameters.emissiveMap.encoding = sRGBEncoding; - break; + case 'DisplacementColor': + parameters.displacementMap = scope.getTexture( textureMap, child.ID ); + break; - case 'NormalMap': - case 'Maya|TEX_normal_map': - parameters.normalMap = scope.getTexture( textureMap, child.ID ); - break; + case 'EmissiveColor': + parameters.emissiveMap = scope.getTexture( textureMap, child.ID ); + parameters.emissiveMap.encoding = sRGBEncoding; + break; - case 'ReflectionColor': - parameters.envMap = scope.getTexture( textureMap, child.ID ); - parameters.envMap.mapping = EquirectangularReflectionMapping; - parameters.envMap.encoding = sRGBEncoding; - break; + case 'NormalMap': + case 'Maya|TEX_normal_map': + parameters.normalMap = scope.getTexture( textureMap, child.ID ); + break; - case 'SpecularColor': - parameters.specularMap = scope.getTexture( textureMap, child.ID ); - parameters.specularMap.encoding = sRGBEncoding; - break; + case 'ReflectionColor': + parameters.envMap = scope.getTexture( textureMap, child.ID ); + parameters.envMap.mapping = EquirectangularReflectionMapping; + parameters.envMap.encoding = sRGBEncoding; + break; - case 'TransparentColor': - case 'TransparencyFactor': - parameters.alphaMap = scope.getTexture( textureMap, child.ID ); - parameters.transparent = true; - break; + case 'SpecularColor': + parameters.specularMap = scope.getTexture( textureMap, child.ID ); + parameters.specularMap.encoding = sRGBEncoding; + break; - case 'AmbientColor': - case 'ShininessExponent': // AKA glossiness map - case 'SpecularFactor': // AKA specularLevel - case 'VectorDisplacementColor': // NOTE: Seems to be a copy of DisplacementColor - default: - console.warn( 'THREE.FBXLoader: %s map is not supported in three.js, skipping texture.', type ); - break; + case 'TransparentColor': + case 'TransparencyFactor': + parameters.alphaMap = scope.getTexture( textureMap, child.ID ); + parameters.transparent = true; + break; - } + case 'AmbientColor': + case 'ShininessExponent': // AKA glossiness map + case 'SpecularFactor': // AKA specularLevel + case 'VectorDisplacementColor': // NOTE: Seems to be a copy of DisplacementColor + default: + console.warn( 'THREE.FBXLoader: %s map is not supported in three.js, skipping texture.', type ); + break; - } ); + } - return parameters; + } ); - }, + return parameters; - // get a texture from the textureMap for use by a material. - getTexture: function ( textureMap, id ) { + } - // if the texture is a layered texture, just use the first layer and issue a warning - if ( 'LayeredTexture' in fbxTree.Objects && id in fbxTree.Objects.LayeredTexture ) { + // get a texture from the textureMap for use by a material. + getTexture( textureMap, id ) { - console.warn( 'THREE.FBXLoader: layered textures are not supported in three.js. Discarding all but first layer.' ); - id = connections.get( id ).children[ 0 ].ID; + // if the texture is a layered texture, just use the first layer and issue a warning + if ( 'LayeredTexture' in fbxTree.Objects && id in fbxTree.Objects.LayeredTexture ) { - } + console.warn( 'THREE.FBXLoader: layered textures are not supported in three.js. Discarding all but first layer.' ); + id = connections.get( id ).children[ 0 ].ID; - return textureMap.get( id ); + } - }, + return textureMap.get( id ); - // Parse nodes in FBXTree.Objects.Deformer - // Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here - // Generates map of Skeleton-like objects for use later when generating and binding skeletons. - parseDeformers: function () { + } - var skeletons = {}; - var morphTargets = {}; + // Parse nodes in FBXTree.Objects.Deformer + // Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here + // Generates map of Skeleton-like objects for use later when generating and binding skeletons. + parseDeformers() { - if ( 'Deformer' in fbxTree.Objects ) { + const skeletons = {}; + const morphTargets = {}; - var DeformerNodes = fbxTree.Objects.Deformer; + if ( 'Deformer' in fbxTree.Objects ) { - for ( var nodeID in DeformerNodes ) { + const DeformerNodes = fbxTree.Objects.Deformer; - var deformerNode = DeformerNodes[ nodeID ]; + for ( const nodeID in DeformerNodes ) { - var relationships = connections.get( parseInt( nodeID ) ); + const deformerNode = DeformerNodes[ nodeID ]; - if ( deformerNode.attrType === 'Skin' ) { + const relationships = connections.get( parseInt( nodeID ) ); - var skeleton = this.parseSkeleton( relationships, DeformerNodes ); - skeleton.ID = nodeID; + if ( deformerNode.attrType === 'Skin' ) { - if ( relationships.parents.length > 1 ) console.warn( 'THREE.FBXLoader: skeleton attached to more than one geometry is not supported.' ); - skeleton.geometryID = relationships.parents[ 0 ].ID; + const skeleton = this.parseSkeleton( relationships, DeformerNodes ); + skeleton.ID = nodeID; - skeletons[ nodeID ] = skeleton; + if ( relationships.parents.length > 1 ) console.warn( 'THREE.FBXLoader: skeleton attached to more than one geometry is not supported.' ); + skeleton.geometryID = relationships.parents[ 0 ].ID; - } else if ( deformerNode.attrType === 'BlendShape' ) { + skeletons[ nodeID ] = skeleton; - var morphTarget = { - id: nodeID, - }; + } else if ( deformerNode.attrType === 'BlendShape' ) { - morphTarget.rawTargets = this.parseMorphTargets( relationships, DeformerNodes ); - morphTarget.id = nodeID; + const morphTarget = { + id: nodeID, + }; - if ( relationships.parents.length > 1 ) console.warn( 'THREE.FBXLoader: morph target attached to more than one geometry is not supported.' ); + morphTarget.rawTargets = this.parseMorphTargets( relationships, DeformerNodes ); + morphTarget.id = nodeID; - morphTargets[ nodeID ] = morphTarget; + if ( relationships.parents.length > 1 ) console.warn( 'THREE.FBXLoader: morph target attached to more than one geometry is not supported.' ); - } + morphTargets[ nodeID ] = morphTarget; } } - return { - - skeletons: skeletons, - morphTargets: morphTargets, - - }; + } - }, + return { - // Parse single nodes in FBXTree.Objects.Deformer - // The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster' - // Each skin node represents a skeleton and each cluster node represents a bone - parseSkeleton: function ( relationships, deformerNodes ) { + skeletons: skeletons, + morphTargets: morphTargets, - var rawBones = []; + }; - relationships.children.forEach( function ( child ) { + } - var boneNode = deformerNodes[ child.ID ]; + // Parse single nodes in FBXTree.Objects.Deformer + // The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster' + // Each skin node represents a skeleton and each cluster node represents a bone + parseSkeleton( relationships, deformerNodes ) { - if ( boneNode.attrType !== 'Cluster' ) return; + const rawBones = []; - var rawBone = { + relationships.children.forEach( function ( child ) { - ID: child.ID, - indices: [], - weights: [], - transformLink: new Matrix4().fromArray( boneNode.TransformLink.a ), - // transform: new Matrix4().fromArray( boneNode.Transform.a ), - // linkMode: boneNode.Mode, + const boneNode = deformerNodes[ child.ID ]; - }; + if ( boneNode.attrType !== 'Cluster' ) return; - if ( 'Indexes' in boneNode ) { + const rawBone = { - rawBone.indices = boneNode.Indexes.a; - rawBone.weights = boneNode.Weights.a; + ID: child.ID, + indices: [], + weights: [], + transformLink: new Matrix4().fromArray( boneNode.TransformLink.a ), + // transform: new Matrix4().fromArray( boneNode.Transform.a ), + // linkMode: boneNode.Mode, - } + }; - rawBones.push( rawBone ); + if ( 'Indexes' in boneNode ) { - } ); + rawBone.indices = boneNode.Indexes.a; + rawBone.weights = boneNode.Weights.a; - return { + } - rawBones: rawBones, - bones: [] + rawBones.push( rawBone ); - }; + } ); - }, + return { - // The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel" - parseMorphTargets: function ( relationships, deformerNodes ) { + rawBones: rawBones, + bones: [] - var rawMorphTargets = []; + }; - for ( var i = 0; i < relationships.children.length; i ++ ) { + } - var child = relationships.children[ i ]; + // The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel" + parseMorphTargets( relationships, deformerNodes ) { - var morphTargetNode = deformerNodes[ child.ID ]; + const rawMorphTargets = []; - var rawMorphTarget = { + for ( let i = 0; i < relationships.children.length; i ++ ) { - name: morphTargetNode.attrName, - initialWeight: morphTargetNode.DeformPercent, - id: morphTargetNode.id, - fullWeights: morphTargetNode.FullWeights.a + const child = relationships.children[ i ]; - }; + const morphTargetNode = deformerNodes[ child.ID ]; - if ( morphTargetNode.attrType !== 'BlendShapeChannel' ) return; + const rawMorphTarget = { - rawMorphTarget.geoID = connections.get( parseInt( child.ID ) ).children.filter( function ( child ) { + name: morphTargetNode.attrName, + initialWeight: morphTargetNode.DeformPercent, + id: morphTargetNode.id, + fullWeights: morphTargetNode.FullWeights.a - return child.relationship === undefined; + }; - } )[ 0 ].ID; + if ( morphTargetNode.attrType !== 'BlendShapeChannel' ) return; - rawMorphTargets.push( rawMorphTarget ); + rawMorphTarget.geoID = connections.get( parseInt( child.ID ) ).children.filter( function ( child ) { - } + return child.relationship === undefined; - return rawMorphTargets; + } )[ 0 ].ID; - }, + rawMorphTargets.push( rawMorphTarget ); - // create the main Group() to be returned by the loader - parseScene: function ( deformers, geometryMap, materialMap ) { + } - sceneGraph = new Group(); + return rawMorphTargets; - var modelMap = this.parseModels( deformers.skeletons, geometryMap, materialMap ); + } - var modelNodes = fbxTree.Objects.Model; + // create the main Group() to be returned by the loader + parseScene( deformers, geometryMap, materialMap ) { - var scope = this; - modelMap.forEach( function ( model ) { + sceneGraph = new Group(); - var modelNode = modelNodes[ model.ID ]; - scope.setLookAtProperties( model, modelNode ); + const modelMap = this.parseModels( deformers.skeletons, geometryMap, materialMap ); - var parentConnections = connections.get( model.ID ).parents; + const modelNodes = fbxTree.Objects.Model; - parentConnections.forEach( function ( connection ) { + const scope = this; + modelMap.forEach( function ( model ) { - var parent = modelMap.get( connection.ID ); - if ( parent !== undefined ) parent.add( model ); + const modelNode = modelNodes[ model.ID ]; + scope.setLookAtProperties( model, modelNode ); - } ); + const parentConnections = connections.get( model.ID ).parents; - if ( model.parent === null ) { + parentConnections.forEach( function ( connection ) { - sceneGraph.add( model ); + const parent = modelMap.get( connection.ID ); + if ( parent !== undefined ) parent.add( model ); - } + } ); + if ( model.parent === null ) { - } ); + sceneGraph.add( model ); - this.bindSkeleton( deformers.skeletons, geometryMap, modelMap ); + } - this.createAmbientLight(); - this.setupMorphMaterials(); + } ); - sceneGraph.traverse( function ( node ) { + this.bindSkeleton( deformers.skeletons, geometryMap, modelMap ); - if ( node.userData.transformData ) { + this.createAmbientLight(); - if ( node.parent ) { + this.setupMorphMaterials(); - node.userData.transformData.parentMatrix = node.parent.matrix; - node.userData.transformData.parentMatrixWorld = node.parent.matrixWorld; + sceneGraph.traverse( function ( node ) { - } + if ( node.userData.transformData ) { - var transform = generateTransform( node.userData.transformData ); + if ( node.parent ) { - node.applyMatrix4( transform ); - node.updateWorldMatrix(); + node.userData.transformData.parentMatrix = node.parent.matrix; + node.userData.transformData.parentMatrixWorld = node.parent.matrixWorld; } - } ); + const transform = generateTransform( node.userData.transformData ); - var animations = new AnimationParser().parse(); + node.applyMatrix4( transform ); + node.updateWorldMatrix(); - // if all the models where already combined in a single group, just return that - if ( sceneGraph.children.length === 1 && sceneGraph.children[ 0 ].isGroup ) { + } - sceneGraph.children[ 0 ].animations = animations; - sceneGraph = sceneGraph.children[ 0 ]; + } ); - } + const animations = new AnimationParser().parse(); - sceneGraph.animations = animations; + // if all the models where already combined in a single group, just return that + if ( sceneGraph.children.length === 1 && sceneGraph.children[ 0 ].isGroup ) { - }, + sceneGraph.children[ 0 ].animations = animations; + sceneGraph = sceneGraph.children[ 0 ]; - // parse nodes in FBXTree.Objects.Model - parseModels: function ( skeletons, geometryMap, materialMap ) { + } - var modelMap = new Map(); - var modelNodes = fbxTree.Objects.Model; + sceneGraph.animations = animations; - for ( var nodeID in modelNodes ) { + } - var id = parseInt( nodeID ); - var node = modelNodes[ nodeID ]; - var relationships = connections.get( id ); + // parse nodes in FBXTree.Objects.Model + parseModels( skeletons, geometryMap, materialMap ) { - var model = this.buildSkeleton( relationships, skeletons, id, node.attrName ); + const modelMap = new Map(); + const modelNodes = fbxTree.Objects.Model; - if ( ! model ) { + for ( const nodeID in modelNodes ) { - switch ( node.attrType ) { + const id = parseInt( nodeID ); + const node = modelNodes[ nodeID ]; + const relationships = connections.get( id ); - case 'Camera': - model = this.createCamera( relationships ); - break; - case 'Light': - model = this.createLight( relationships ); - break; - case 'Mesh': - model = this.createMesh( relationships, geometryMap, materialMap ); - break; - case 'NurbsCurve': - model = this.createCurve( relationships, geometryMap ); - break; - case 'LimbNode': - case 'Root': - model = new Bone(); - break; - case 'Null': - default: - model = new Group(); - break; + let model = this.buildSkeleton( relationships, skeletons, id, node.attrName ); - } + if ( ! model ) { - model.name = node.attrName ? PropertyBinding.sanitizeNodeName( node.attrName ) : ''; + switch ( node.attrType ) { - model.ID = id; + case 'Camera': + model = this.createCamera( relationships ); + break; + case 'Light': + model = this.createLight( relationships ); + break; + case 'Mesh': + model = this.createMesh( relationships, geometryMap, materialMap ); + break; + case 'NurbsCurve': + model = this.createCurve( relationships, geometryMap ); + break; + case 'LimbNode': + case 'Root': + model = new Bone(); + break; + case 'Null': + default: + model = new Group(); + break; } - this.getTransformData( model, node ); - modelMap.set( id, model ); + model.name = node.attrName ? PropertyBinding.sanitizeNodeName( node.attrName ) : ''; + + model.ID = id; } - return modelMap; + this.getTransformData( model, node ); + modelMap.set( id, model ); - }, + } - buildSkeleton: function ( relationships, skeletons, id, name ) { + return modelMap; - var bone = null; + } - relationships.parents.forEach( function ( parent ) { + buildSkeleton( relationships, skeletons, id, name ) { - for ( var ID in skeletons ) { + let bone = null; - var skeleton = skeletons[ ID ]; + relationships.parents.forEach( function ( parent ) { - skeleton.rawBones.forEach( function ( rawBone, i ) { + for ( const ID in skeletons ) { - if ( rawBone.ID === parent.ID ) { + const skeleton = skeletons[ ID ]; - var subBone = bone; - bone = new Bone(); + skeleton.rawBones.forEach( function ( rawBone, i ) { - bone.matrixWorld.copy( rawBone.transformLink ); + if ( rawBone.ID === parent.ID ) { - // set name and id here - otherwise in cases where "subBone" is created it will not have a name / id + const subBone = bone; + bone = new Bone(); - bone.name = name ? PropertyBinding.sanitizeNodeName( name ) : ''; - bone.ID = id; + bone.matrixWorld.copy( rawBone.transformLink ); - skeleton.bones[ i ] = bone; + // set name and id here - otherwise in cases where "subBone" is created it will not have a name / id - // In cases where a bone is shared between multiple meshes - // duplicate the bone here and and it as a child of the first bone - if ( subBone !== null ) { + bone.name = name ? PropertyBinding.sanitizeNodeName( name ) : ''; + bone.ID = id; - bone.add( subBone ); + skeleton.bones[ i ] = bone; - } + // In cases where a bone is shared between multiple meshes + // duplicate the bone here and and it as a child of the first bone + if ( subBone !== null ) { + + bone.add( subBone ); } - } ); + } - } + } ); - } ); + } - return bone; + } ); - }, + return bone; - // create a PerspectiveCamera or OrthographicCamera - createCamera: function ( relationships ) { + } - var model; - var cameraAttribute; + // create a PerspectiveCamera or OrthographicCamera + createCamera( relationships ) { - relationships.children.forEach( function ( child ) { + let model; + let cameraAttribute; - var attr = fbxTree.Objects.NodeAttribute[ child.ID ]; + relationships.children.forEach( function ( child ) { - if ( attr !== undefined ) { + const attr = fbxTree.Objects.NodeAttribute[ child.ID ]; - cameraAttribute = attr; + if ( attr !== undefined ) { - } + cameraAttribute = attr; - } ); + } - if ( cameraAttribute === undefined ) { + } ); - model = new Object3D(); + if ( cameraAttribute === undefined ) { - } else { + model = new Object3D(); - var type = 0; - if ( cameraAttribute.CameraProjectionType !== undefined && cameraAttribute.CameraProjectionType.value === 1 ) { + } else { - type = 1; + let type = 0; + if ( cameraAttribute.CameraProjectionType !== undefined && cameraAttribute.CameraProjectionType.value === 1 ) { - } + type = 1; - var nearClippingPlane = 1; - if ( cameraAttribute.NearPlane !== undefined ) { + } - nearClippingPlane = cameraAttribute.NearPlane.value / 1000; + let nearClippingPlane = 1; + if ( cameraAttribute.NearPlane !== undefined ) { - } + nearClippingPlane = cameraAttribute.NearPlane.value / 1000; - var farClippingPlane = 1000; - if ( cameraAttribute.FarPlane !== undefined ) { + } - farClippingPlane = cameraAttribute.FarPlane.value / 1000; + let farClippingPlane = 1000; + if ( cameraAttribute.FarPlane !== undefined ) { - } + farClippingPlane = cameraAttribute.FarPlane.value / 1000; + } - var width = window.innerWidth; - var height = window.innerHeight; - if ( cameraAttribute.AspectWidth !== undefined && cameraAttribute.AspectHeight !== undefined ) { + let width = window.innerWidth; + let height = window.innerHeight; - width = cameraAttribute.AspectWidth.value; - height = cameraAttribute.AspectHeight.value; + if ( cameraAttribute.AspectWidth !== undefined && cameraAttribute.AspectHeight !== undefined ) { - } + width = cameraAttribute.AspectWidth.value; + height = cameraAttribute.AspectHeight.value; - var aspect = width / height; + } - var fov = 45; - if ( cameraAttribute.FieldOfView !== undefined ) { + const aspect = width / height; - fov = cameraAttribute.FieldOfView.value; + let fov = 45; + if ( cameraAttribute.FieldOfView !== undefined ) { - } + fov = cameraAttribute.FieldOfView.value; - var focalLength = cameraAttribute.FocalLength ? cameraAttribute.FocalLength.value : null; + } - switch ( type ) { + const focalLength = cameraAttribute.FocalLength ? cameraAttribute.FocalLength.value : null; - case 0: // Perspective - model = new PerspectiveCamera( fov, aspect, nearClippingPlane, farClippingPlane ); - if ( focalLength !== null ) model.setFocalLength( focalLength ); - break; + switch ( type ) { - case 1: // Orthographic - model = new OrthographicCamera( - width / 2, width / 2, height / 2, - height / 2, nearClippingPlane, farClippingPlane ); - break; + case 0: // Perspective + model = new PerspectiveCamera( fov, aspect, nearClippingPlane, farClippingPlane ); + if ( focalLength !== null ) model.setFocalLength( focalLength ); + break; - default: - console.warn( 'THREE.FBXLoader: Unknown camera type ' + type + '.' ); - model = new Object3D(); - break; + case 1: // Orthographic + model = new OrthographicCamera( - width / 2, width / 2, height / 2, - height / 2, nearClippingPlane, farClippingPlane ); + break; - } + default: + console.warn( 'THREE.FBXLoader: Unknown camera type ' + type + '.' ); + model = new Object3D(); + break; } - return model; + } - }, + return model; - // Create a DirectionalLight, PointLight or SpotLight - createLight: function ( relationships ) { + } - var model; - var lightAttribute; + // Create a DirectionalLight, PointLight or SpotLight + createLight( relationships ) { - relationships.children.forEach( function ( child ) { + let model; + let lightAttribute; - var attr = fbxTree.Objects.NodeAttribute[ child.ID ]; + relationships.children.forEach( function ( child ) { - if ( attr !== undefined ) { + const attr = fbxTree.Objects.NodeAttribute[ child.ID ]; - lightAttribute = attr; + if ( attr !== undefined ) { - } + lightAttribute = attr; - } ); + } - if ( lightAttribute === undefined ) { + } ); - model = new Object3D(); + if ( lightAttribute === undefined ) { - } else { + model = new Object3D(); - var type; + } else { - // LightType can be undefined for Point lights - if ( lightAttribute.LightType === undefined ) { + let type; - type = 0; + // LightType can be undefined for Point lights + if ( lightAttribute.LightType === undefined ) { - } else { + type = 0; - type = lightAttribute.LightType.value; + } else { - } + type = lightAttribute.LightType.value; - var color = 0xffffff; + } - if ( lightAttribute.Color !== undefined ) { + let color = 0xffffff; - color = new Color().fromArray( lightAttribute.Color.value ); + if ( lightAttribute.Color !== undefined ) { - } + color = new Color().fromArray( lightAttribute.Color.value ); - var intensity = ( lightAttribute.Intensity === undefined ) ? 1 : lightAttribute.Intensity.value / 100; + } - // light disabled - if ( lightAttribute.CastLightOnObject !== undefined && lightAttribute.CastLightOnObject.value === 0 ) { + let intensity = ( lightAttribute.Intensity === undefined ) ? 1 : lightAttribute.Intensity.value / 100; - intensity = 0; + // light disabled + if ( lightAttribute.CastLightOnObject !== undefined && lightAttribute.CastLightOnObject.value === 0 ) { - } + intensity = 0; - var distance = 0; - if ( lightAttribute.FarAttenuationEnd !== undefined ) { + } - if ( lightAttribute.EnableFarAttenuation !== undefined && lightAttribute.EnableFarAttenuation.value === 0 ) { + let distance = 0; + if ( lightAttribute.FarAttenuationEnd !== undefined ) { - distance = 0; + if ( lightAttribute.EnableFarAttenuation !== undefined && lightAttribute.EnableFarAttenuation.value === 0 ) { - } else { + distance = 0; - distance = lightAttribute.FarAttenuationEnd.value; + } else { - } + distance = lightAttribute.FarAttenuationEnd.value; } - // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd? - var decay = 1; + } - switch ( type ) { + // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd? + const decay = 1; - case 0: // Point - model = new PointLight( color, intensity, distance, decay ); - break; + switch ( type ) { - case 1: // Directional - model = new DirectionalLight( color, intensity ); - break; + case 0: // Point + model = new PointLight( color, intensity, distance, decay ); + break; - case 2: // Spot - var angle = Math.PI / 3; + case 1: // Directional + model = new DirectionalLight( color, intensity ); + break; - if ( lightAttribute.InnerAngle !== undefined ) { + case 2: // Spot + let angle = Math.PI / 3; - angle = MathUtils.degToRad( lightAttribute.InnerAngle.value ); + if ( lightAttribute.InnerAngle !== undefined ) { - } + angle = MathUtils.degToRad( lightAttribute.InnerAngle.value ); - var penumbra = 0; - if ( lightAttribute.OuterAngle !== undefined ) { + } - // TODO: this is not correct - FBX calculates outer and inner angle in degrees - // with OuterAngle > InnerAngle && OuterAngle <= Math.PI - // while three.js uses a penumbra between (0, 1) to attenuate the inner angle - penumbra = MathUtils.degToRad( lightAttribute.OuterAngle.value ); - penumbra = Math.max( penumbra, 1 ); + let penumbra = 0; + if ( lightAttribute.OuterAngle !== undefined ) { - } + // TODO: this is not correct - FBX calculates outer and inner angle in degrees + // with OuterAngle > InnerAngle && OuterAngle <= Math.PI + // while three.js uses a penumbra between (0, 1) to attenuate the inner angle + penumbra = MathUtils.degToRad( lightAttribute.OuterAngle.value ); + penumbra = Math.max( penumbra, 1 ); - model = new SpotLight( color, intensity, distance, angle, penumbra, decay ); - break; + } - default: - console.warn( 'THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a PointLight.' ); - model = new PointLight( color, intensity ); - break; + model = new SpotLight( color, intensity, distance, angle, penumbra, decay ); + break; - } + default: + console.warn( 'THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a PointLight.' ); + model = new PointLight( color, intensity ); + break; - if ( lightAttribute.CastShadows !== undefined && lightAttribute.CastShadows.value === 1 ) { + } - model.castShadow = true; + if ( lightAttribute.CastShadows !== undefined && lightAttribute.CastShadows.value === 1 ) { - } + model.castShadow = true; } - return model; + } - }, + return model; - createMesh: function ( relationships, geometryMap, materialMap ) { + } - var model; - var geometry = null; - var material = null; - var materials = []; + createMesh( relationships, geometryMap, materialMap ) { - // get geometry and materials(s) from connections - relationships.children.forEach( function ( child ) { + let model; + let geometry = null; + let material = null; + const materials = []; - if ( geometryMap.has( child.ID ) ) { + // get geometry and materials(s) from connections + relationships.children.forEach( function ( child ) { - geometry = geometryMap.get( child.ID ); + if ( geometryMap.has( child.ID ) ) { - } + geometry = geometryMap.get( child.ID ); - if ( materialMap.has( child.ID ) ) { + } - materials.push( materialMap.get( child.ID ) ); + if ( materialMap.has( child.ID ) ) { - } + materials.push( materialMap.get( child.ID ) ); - } ); + } - if ( materials.length > 1 ) { + } ); - material = materials; + if ( materials.length > 1 ) { - } else if ( materials.length > 0 ) { + material = materials; - material = materials[ 0 ]; + } else if ( materials.length > 0 ) { - } else { + material = materials[ 0 ]; - material = new MeshPhongMaterial( { color: 0xcccccc } ); - materials.push( material ); + } else { - } + material = new MeshPhongMaterial( { color: 0xcccccc } ); + materials.push( material ); - if ( 'color' in geometry.attributes ) { + } - materials.forEach( function ( material ) { + if ( 'color' in geometry.attributes ) { - material.vertexColors = true; + materials.forEach( function ( material ) { - } ); + material.vertexColors = true; - } + } ); - if ( geometry.FBX_Deformer ) { + } - materials.forEach( function ( material ) { + if ( geometry.FBX_Deformer ) { - material.skinning = true; + materials.forEach( function ( material ) { - } ); + material.skinning = true; - model = new SkinnedMesh( geometry, material ); - model.normalizeSkinWeights(); + } ); - } else { + model = new SkinnedMesh( geometry, material ); + model.normalizeSkinWeights(); - model = new Mesh( geometry, material ); + } else { - } + model = new Mesh( geometry, material ); - return model; + } - }, + return model; - createCurve: function ( relationships, geometryMap ) { + } - var geometry = relationships.children.reduce( function ( geo, child ) { + createCurve( relationships, geometryMap ) { - if ( geometryMap.has( child.ID ) ) geo = geometryMap.get( child.ID ); + const geometry = relationships.children.reduce( function ( geo, child ) { - return geo; + if ( geometryMap.has( child.ID ) ) geo = geometryMap.get( child.ID ); - }, null ); + return geo; - // FBX does not list materials for Nurbs lines, so we'll just put our own in here. - var material = new LineBasicMaterial( { color: 0x3300ff, linewidth: 1 } ); - return new Line( geometry, material ); + }, null ); - }, + // FBX does not list materials for Nurbs lines, so we'll just put our own in here. + const material = new LineBasicMaterial( { color: 0x3300ff, linewidth: 1 } ); + return new Line( geometry, material ); - // parse the model node for transform data - getTransformData: function ( model, modelNode ) { + } - var transformData = {}; + // parse the model node for transform data + getTransformData( model, modelNode ) { - if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value ); + const transformData = {}; - if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value ); - else transformData.eulerOrder = 'ZYX'; + if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value ); - if ( 'Lcl_Translation' in modelNode ) transformData.translation = modelNode.Lcl_Translation.value; + if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value ); + else transformData.eulerOrder = 'ZYX'; - if ( 'PreRotation' in modelNode ) transformData.preRotation = modelNode.PreRotation.value; - if ( 'Lcl_Rotation' in modelNode ) transformData.rotation = modelNode.Lcl_Rotation.value; - if ( 'PostRotation' in modelNode ) transformData.postRotation = modelNode.PostRotation.value; + if ( 'Lcl_Translation' in modelNode ) transformData.translation = modelNode.Lcl_Translation.value; - if ( 'Lcl_Scaling' in modelNode ) transformData.scale = modelNode.Lcl_Scaling.value; + if ( 'PreRotation' in modelNode ) transformData.preRotation = modelNode.PreRotation.value; + if ( 'Lcl_Rotation' in modelNode ) transformData.rotation = modelNode.Lcl_Rotation.value; + if ( 'PostRotation' in modelNode ) transformData.postRotation = modelNode.PostRotation.value; - if ( 'ScalingOffset' in modelNode ) transformData.scalingOffset = modelNode.ScalingOffset.value; - if ( 'ScalingPivot' in modelNode ) transformData.scalingPivot = modelNode.ScalingPivot.value; + if ( 'Lcl_Scaling' in modelNode ) transformData.scale = modelNode.Lcl_Scaling.value; - if ( 'RotationOffset' in modelNode ) transformData.rotationOffset = modelNode.RotationOffset.value; - if ( 'RotationPivot' in modelNode ) transformData.rotationPivot = modelNode.RotationPivot.value; + if ( 'ScalingOffset' in modelNode ) transformData.scalingOffset = modelNode.ScalingOffset.value; + if ( 'ScalingPivot' in modelNode ) transformData.scalingPivot = modelNode.ScalingPivot.value; - model.userData.transformData = transformData; + if ( 'RotationOffset' in modelNode ) transformData.rotationOffset = modelNode.RotationOffset.value; + if ( 'RotationPivot' in modelNode ) transformData.rotationPivot = modelNode.RotationPivot.value; - }, + model.userData.transformData = transformData; - setLookAtProperties: function ( model, modelNode ) { + } - if ( 'LookAtProperty' in modelNode ) { + setLookAtProperties( model, modelNode ) { - var children = connections.get( model.ID ).children; + if ( 'LookAtProperty' in modelNode ) { - children.forEach( function ( child ) { + const children = connections.get( model.ID ).children; - if ( child.relationship === 'LookAtProperty' ) { + children.forEach( function ( child ) { - var lookAtTarget = fbxTree.Objects.Model[ child.ID ]; + if ( child.relationship === 'LookAtProperty' ) { - if ( 'Lcl_Translation' in lookAtTarget ) { + const lookAtTarget = fbxTree.Objects.Model[ child.ID ]; - var pos = lookAtTarget.Lcl_Translation.value; + if ( 'Lcl_Translation' in lookAtTarget ) { - // DirectionalLight, SpotLight - if ( model.target !== undefined ) { + const pos = lookAtTarget.Lcl_Translation.value; - model.target.position.fromArray( pos ); - sceneGraph.add( model.target ); + // DirectionalLight, SpotLight + if ( model.target !== undefined ) { - } else { // Cameras and other Object3Ds + model.target.position.fromArray( pos ); + sceneGraph.add( model.target ); - model.lookAt( new Vector3().fromArray( pos ) ); + } else { // Cameras and other Object3Ds - } + model.lookAt( new Vector3().fromArray( pos ) ); } } - } ); + } - } + } ); - }, + } - bindSkeleton: function ( skeletons, geometryMap, modelMap ) { + } - var bindMatrices = this.parsePoseNodes(); + bindSkeleton( skeletons, geometryMap, modelMap ) { - for ( var ID in skeletons ) { + const bindMatrices = this.parsePoseNodes(); - var skeleton = skeletons[ ID ]; + for ( const ID in skeletons ) { - var parents = connections.get( parseInt( skeleton.ID ) ).parents; + const skeleton = skeletons[ ID ]; - parents.forEach( function ( parent ) { + const parents = connections.get( parseInt( skeleton.ID ) ).parents; - if ( geometryMap.has( parent.ID ) ) { + parents.forEach( function ( parent ) { - var geoID = parent.ID; - var geoRelationships = connections.get( geoID ); + if ( geometryMap.has( parent.ID ) ) { - geoRelationships.parents.forEach( function ( geoConnParent ) { + const geoID = parent.ID; + const geoRelationships = connections.get( geoID ); - if ( modelMap.has( geoConnParent.ID ) ) { + geoRelationships.parents.forEach( function ( geoConnParent ) { - var model = modelMap.get( geoConnParent.ID ); + if ( modelMap.has( geoConnParent.ID ) ) { - model.bind( new Skeleton( skeleton.bones ), bindMatrices[ geoConnParent.ID ] ); + const model = modelMap.get( geoConnParent.ID ); - } + model.bind( new Skeleton( skeleton.bones ), bindMatrices[ geoConnParent.ID ] ); - } ); + } - } + } ); - } ); + } - } + } ); - }, + } - parsePoseNodes: function () { + } - var bindMatrices = {}; + parsePoseNodes() { - if ( 'Pose' in fbxTree.Objects ) { + const bindMatrices = {}; - var BindPoseNode = fbxTree.Objects.Pose; + if ( 'Pose' in fbxTree.Objects ) { - for ( var nodeID in BindPoseNode ) { + const BindPoseNode = fbxTree.Objects.Pose; - if ( BindPoseNode[ nodeID ].attrType === 'BindPose' ) { + for ( const nodeID in BindPoseNode ) { - var poseNodes = BindPoseNode[ nodeID ].PoseNode; + if ( BindPoseNode[ nodeID ].attrType === 'BindPose' ) { - if ( Array.isArray( poseNodes ) ) { + const poseNodes = BindPoseNode[ nodeID ].PoseNode; - poseNodes.forEach( function ( poseNode ) { + if ( Array.isArray( poseNodes ) ) { - bindMatrices[ poseNode.Node ] = new Matrix4().fromArray( poseNode.Matrix.a ); + poseNodes.forEach( function ( poseNode ) { - } ); + bindMatrices[ poseNode.Node ] = new Matrix4().fromArray( poseNode.Matrix.a ); - } else { + } ); - bindMatrices[ poseNodes.Node ] = new Matrix4().fromArray( poseNodes.Matrix.a ); + } else { - } + bindMatrices[ poseNodes.Node ] = new Matrix4().fromArray( poseNodes.Matrix.a ); } @@ -1439,2785 +1431,2762 @@ var FBXLoader = ( function () { } - return bindMatrices; + } - }, + return bindMatrices; - // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light - createAmbientLight: function () { + } - if ( 'GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings ) { + // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light + createAmbientLight() { - var ambientColor = fbxTree.GlobalSettings.AmbientColor.value; - var r = ambientColor[ 0 ]; - var g = ambientColor[ 1 ]; - var b = ambientColor[ 2 ]; + if ( 'GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings ) { - if ( r !== 0 || g !== 0 || b !== 0 ) { + const ambientColor = fbxTree.GlobalSettings.AmbientColor.value; + const r = ambientColor[ 0 ]; + const g = ambientColor[ 1 ]; + const b = ambientColor[ 2 ]; - var color = new Color( r, g, b ); - sceneGraph.add( new AmbientLight( color, 1 ) ); + if ( r !== 0 || g !== 0 || b !== 0 ) { - } + const color = new Color( r, g, b ); + sceneGraph.add( new AmbientLight( color, 1 ) ); } - }, + } - setupMorphMaterials: function () { + } - var scope = this; - sceneGraph.traverse( function ( child ) { + setupMorphMaterials() { - if ( child.isMesh ) { + const scope = this; + sceneGraph.traverse( function ( child ) { - if ( child.geometry.morphAttributes.position && child.geometry.morphAttributes.position.length ) { + if ( child.isMesh ) { - if ( Array.isArray( child.material ) ) { + if ( child.geometry.morphAttributes.position && child.geometry.morphAttributes.position.length ) { - child.material.forEach( function ( material, i ) { + if ( Array.isArray( child.material ) ) { - scope.setupMorphMaterial( child, material, i ); + child.material.forEach( function ( material, i ) { - } ); + scope.setupMorphMaterial( child, material, i ); - } else { + } ); - scope.setupMorphMaterial( child, child.material ); + } else { - } + scope.setupMorphMaterial( child, child.material ); } } - } ); - - }, - - setupMorphMaterial: function ( child, material, index ) { + } - var uuid = child.uuid; - var matUuid = material.uuid; + } ); - // if a geometry has morph targets, it cannot share the material with other geometries - var sharedMat = false; + } - sceneGraph.traverse( function ( node ) { + setupMorphMaterial( child, material, index ) { - if ( node.isMesh ) { + const uuid = child.uuid; + const matUuid = material.uuid; - if ( Array.isArray( node.material ) ) { + // if a geometry has morph targets, it cannot share the material with other geometries + let sharedMat = false; - node.material.forEach( function ( mat ) { + sceneGraph.traverse( function ( node ) { - if ( mat.uuid === matUuid && node.uuid !== uuid ) sharedMat = true; + if ( node.isMesh ) { - } ); + if ( Array.isArray( node.material ) ) { - } else if ( node.material.uuid === matUuid && node.uuid !== uuid ) sharedMat = true; + node.material.forEach( function ( mat ) { - } + if ( mat.uuid === matUuid && node.uuid !== uuid ) sharedMat = true; - } ); + } ); - if ( sharedMat === true ) { + } else if ( node.material.uuid === matUuid && node.uuid !== uuid ) sharedMat = true; - var clonedMat = material.clone(); - clonedMat.morphTargets = true; + } - if ( index === undefined ) child.material = clonedMat; - else child.material[ index ] = clonedMat; + } ); - } else material.morphTargets = true; + if ( sharedMat === true ) { - } + const clonedMat = material.clone(); + clonedMat.morphTargets = true; - }; + if ( index === undefined ) child.material = clonedMat; + else child.material[ index ] = clonedMat; - // parse Geometry data from FBXTree and return map of BufferGeometries - function GeometryParser() {} + } else material.morphTargets = true; - GeometryParser.prototype = { + } - constructor: GeometryParser, +} - // Parse nodes in FBXTree.Objects.Geometry - parse: function ( deformers ) { +// parse Geometry data from FBXTree and return map of BufferGeometries +class GeometryParser { - var geometryMap = new Map(); + // Parse nodes in FBXTree.Objects.Geometry + parse( deformers ) { - if ( 'Geometry' in fbxTree.Objects ) { + const geometryMap = new Map(); - var geoNodes = fbxTree.Objects.Geometry; + if ( 'Geometry' in fbxTree.Objects ) { - for ( var nodeID in geoNodes ) { + const geoNodes = fbxTree.Objects.Geometry; - var relationships = connections.get( parseInt( nodeID ) ); - var geo = this.parseGeometry( relationships, geoNodes[ nodeID ], deformers ); + for ( const nodeID in geoNodes ) { - geometryMap.set( parseInt( nodeID ), geo ); + const relationships = connections.get( parseInt( nodeID ) ); + const geo = this.parseGeometry( relationships, geoNodes[ nodeID ], deformers ); - } + geometryMap.set( parseInt( nodeID ), geo ); } - return geometryMap; - - }, + } - // Parse single node in FBXTree.Objects.Geometry - parseGeometry: function ( relationships, geoNode, deformers ) { + return geometryMap; - switch ( geoNode.attrType ) { + } - case 'Mesh': - return this.parseMeshGeometry( relationships, geoNode, deformers ); - break; + // Parse single node in FBXTree.Objects.Geometry + parseGeometry( relationships, geoNode, deformers ) { - case 'NurbsCurve': - return this.parseNurbsGeometry( geoNode ); - break; + switch ( geoNode.attrType ) { - } + case 'Mesh': + return this.parseMeshGeometry( relationships, geoNode, deformers ); + break; - }, + case 'NurbsCurve': + return this.parseNurbsGeometry( geoNode ); + break; + } - // Parse single node mesh geometry in FBXTree.Objects.Geometry - parseMeshGeometry: function ( relationships, geoNode, deformers ) { + } - var skeletons = deformers.skeletons; - var morphTargets = []; + // Parse single node mesh geometry in FBXTree.Objects.Geometry + parseMeshGeometry( relationships, geoNode, deformers ) { - var modelNodes = relationships.parents.map( function ( parent ) { + const skeletons = deformers.skeletons; + const morphTargets = []; - return fbxTree.Objects.Model[ parent.ID ]; + const modelNodes = relationships.parents.map( function ( parent ) { - } ); + return fbxTree.Objects.Model[ parent.ID ]; - // don't create geometry if it is not associated with any models - if ( modelNodes.length === 0 ) return; + } ); - var skeleton = relationships.children.reduce( function ( skeleton, child ) { + // don't create geometry if it is not associated with any models + if ( modelNodes.length === 0 ) return; - if ( skeletons[ child.ID ] !== undefined ) skeleton = skeletons[ child.ID ]; + const skeleton = relationships.children.reduce( function ( skeleton, child ) { - return skeleton; + if ( skeletons[ child.ID ] !== undefined ) skeleton = skeletons[ child.ID ]; - }, null ); + return skeleton; - relationships.children.forEach( function ( child ) { + }, null ); - if ( deformers.morphTargets[ child.ID ] !== undefined ) { + relationships.children.forEach( function ( child ) { - morphTargets.push( deformers.morphTargets[ child.ID ] ); + if ( deformers.morphTargets[ child.ID ] !== undefined ) { - } + morphTargets.push( deformers.morphTargets[ child.ID ] ); - } ); + } - // Assume one model and get the preRotation from that - // if there is more than one model associated with the geometry this may cause problems - var modelNode = modelNodes[ 0 ]; + } ); - var transformData = {}; + // Assume one model and get the preRotation from that + // if there is more than one model associated with the geometry this may cause problems + const modelNode = modelNodes[ 0 ]; - if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value ); - if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value ); + const transformData = {}; - if ( 'GeometricTranslation' in modelNode ) transformData.translation = modelNode.GeometricTranslation.value; - if ( 'GeometricRotation' in modelNode ) transformData.rotation = modelNode.GeometricRotation.value; - if ( 'GeometricScaling' in modelNode ) transformData.scale = modelNode.GeometricScaling.value; + if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value ); + if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value ); - var transform = generateTransform( transformData ); + if ( 'GeometricTranslation' in modelNode ) transformData.translation = modelNode.GeometricTranslation.value; + if ( 'GeometricRotation' in modelNode ) transformData.rotation = modelNode.GeometricRotation.value; + if ( 'GeometricScaling' in modelNode ) transformData.scale = modelNode.GeometricScaling.value; - return this.genGeometry( geoNode, skeleton, morphTargets, transform ); + const transform = generateTransform( transformData ); - }, + return this.genGeometry( geoNode, skeleton, morphTargets, transform ); - // Generate a BufferGeometry from a node in FBXTree.Objects.Geometry - genGeometry: function ( geoNode, skeleton, morphTargets, preTransform ) { + } - var geo = new BufferGeometry(); - if ( geoNode.attrName ) geo.name = geoNode.attrName; + // Generate a BufferGeometry from a node in FBXTree.Objects.Geometry + genGeometry( geoNode, skeleton, morphTargets, preTransform ) { - var geoInfo = this.parseGeoNode( geoNode, skeleton ); - var buffers = this.genBuffers( geoInfo ); + const geo = new BufferGeometry(); + if ( geoNode.attrName ) geo.name = geoNode.attrName; - var positionAttribute = new Float32BufferAttribute( buffers.vertex, 3 ); + const geoInfo = this.parseGeoNode( geoNode, skeleton ); + const buffers = this.genBuffers( geoInfo ); - positionAttribute.applyMatrix4( preTransform ); + const positionAttribute = new Float32BufferAttribute( buffers.vertex, 3 ); - geo.setAttribute( 'position', positionAttribute ); + positionAttribute.applyMatrix4( preTransform ); - if ( buffers.colors.length > 0 ) { + geo.setAttribute( 'position', positionAttribute ); - geo.setAttribute( 'color', new Float32BufferAttribute( buffers.colors, 3 ) ); + if ( buffers.colors.length > 0 ) { - } + geo.setAttribute( 'color', new Float32BufferAttribute( buffers.colors, 3 ) ); - if ( skeleton ) { + } - geo.setAttribute( 'skinIndex', new Uint16BufferAttribute( buffers.weightsIndices, 4 ) ); + if ( skeleton ) { - geo.setAttribute( 'skinWeight', new Float32BufferAttribute( buffers.vertexWeights, 4 ) ); + geo.setAttribute( 'skinIndex', new Uint16BufferAttribute( buffers.weightsIndices, 4 ) ); - // used later to bind the skeleton to the model - geo.FBX_Deformer = skeleton; + geo.setAttribute( 'skinWeight', new Float32BufferAttribute( buffers.vertexWeights, 4 ) ); - } + // used later to bind the skeleton to the model + geo.FBX_Deformer = skeleton; - if ( buffers.normal.length > 0 ) { + } - var normalMatrix = new Matrix3().getNormalMatrix( preTransform ); + if ( buffers.normal.length > 0 ) { - var normalAttribute = new Float32BufferAttribute( buffers.normal, 3 ); - normalAttribute.applyNormalMatrix( normalMatrix ); + const normalMatrix = new Matrix3().getNormalMatrix( preTransform ); - geo.setAttribute( 'normal', normalAttribute ); + const normalAttribute = new Float32BufferAttribute( buffers.normal, 3 ); + normalAttribute.applyNormalMatrix( normalMatrix ); - } + geo.setAttribute( 'normal', normalAttribute ); - buffers.uvs.forEach( function ( uvBuffer, i ) { + } - // subsequent uv buffers are called 'uv1', 'uv2', ... - var name = 'uv' + ( i + 1 ).toString(); + buffers.uvs.forEach( function ( uvBuffer, i ) { - // the first uv buffer is just called 'uv' - if ( i === 0 ) { + // subsequent uv buffers are called 'uv1', 'uv2', ... + let name = 'uv' + ( i + 1 ).toString(); - name = 'uv'; + // the first uv buffer is just called 'uv' + if ( i === 0 ) { - } + name = 'uv'; - geo.setAttribute( name, new Float32BufferAttribute( buffers.uvs[ i ], 2 ) ); + } - } ); + geo.setAttribute( name, new Float32BufferAttribute( buffers.uvs[ i ], 2 ) ); - if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) { + } ); - // Convert the material indices of each vertex into rendering groups on the geometry. - var prevMaterialIndex = buffers.materialIndex[ 0 ]; - var startIndex = 0; + if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) { - buffers.materialIndex.forEach( function ( currentIndex, i ) { + // Convert the material indices of each vertex into rendering groups on the geometry. + let prevMaterialIndex = buffers.materialIndex[ 0 ]; + let startIndex = 0; - if ( currentIndex !== prevMaterialIndex ) { + buffers.materialIndex.forEach( function ( currentIndex, i ) { - geo.addGroup( startIndex, i - startIndex, prevMaterialIndex ); + if ( currentIndex !== prevMaterialIndex ) { - prevMaterialIndex = currentIndex; - startIndex = i; + geo.addGroup( startIndex, i - startIndex, prevMaterialIndex ); - } + prevMaterialIndex = currentIndex; + startIndex = i; - } ); + } - // the loop above doesn't add the last group, do that here. - if ( geo.groups.length > 0 ) { + } ); - var lastGroup = geo.groups[ geo.groups.length - 1 ]; - var lastIndex = lastGroup.start + lastGroup.count; + // the loop above doesn't add the last group, do that here. + if ( geo.groups.length > 0 ) { - if ( lastIndex !== buffers.materialIndex.length ) { + const lastGroup = geo.groups[ geo.groups.length - 1 ]; + const lastIndex = lastGroup.start + lastGroup.count; - geo.addGroup( lastIndex, buffers.materialIndex.length - lastIndex, prevMaterialIndex ); + if ( lastIndex !== buffers.materialIndex.length ) { - } + geo.addGroup( lastIndex, buffers.materialIndex.length - lastIndex, prevMaterialIndex ); } - // case where there are multiple materials but the whole geometry is only - // using one of them - if ( geo.groups.length === 0 ) { + } - geo.addGroup( 0, buffers.materialIndex.length, buffers.materialIndex[ 0 ] ); + // case where there are multiple materials but the whole geometry is only + // using one of them + if ( geo.groups.length === 0 ) { - } + geo.addGroup( 0, buffers.materialIndex.length, buffers.materialIndex[ 0 ] ); } - this.addMorphTargets( geo, geoNode, morphTargets, preTransform ); - - return geo; + } - }, + this.addMorphTargets( geo, geoNode, morphTargets, preTransform ); - parseGeoNode: function ( geoNode, skeleton ) { + return geo; - var geoInfo = {}; + } - geoInfo.vertexPositions = ( geoNode.Vertices !== undefined ) ? geoNode.Vertices.a : []; - geoInfo.vertexIndices = ( geoNode.PolygonVertexIndex !== undefined ) ? geoNode.PolygonVertexIndex.a : []; + parseGeoNode( geoNode, skeleton ) { - if ( geoNode.LayerElementColor ) { + const geoInfo = {}; - geoInfo.color = this.parseVertexColors( geoNode.LayerElementColor[ 0 ] ); + geoInfo.vertexPositions = ( geoNode.Vertices !== undefined ) ? geoNode.Vertices.a : []; + geoInfo.vertexIndices = ( geoNode.PolygonVertexIndex !== undefined ) ? geoNode.PolygonVertexIndex.a : []; - } + if ( geoNode.LayerElementColor ) { - if ( geoNode.LayerElementMaterial ) { + geoInfo.color = this.parseVertexColors( geoNode.LayerElementColor[ 0 ] ); - geoInfo.material = this.parseMaterialIndices( geoNode.LayerElementMaterial[ 0 ] ); + } - } + if ( geoNode.LayerElementMaterial ) { - if ( geoNode.LayerElementNormal ) { + geoInfo.material = this.parseMaterialIndices( geoNode.LayerElementMaterial[ 0 ] ); - geoInfo.normal = this.parseNormals( geoNode.LayerElementNormal[ 0 ] ); + } - } + if ( geoNode.LayerElementNormal ) { - if ( geoNode.LayerElementUV ) { + geoInfo.normal = this.parseNormals( geoNode.LayerElementNormal[ 0 ] ); - geoInfo.uv = []; + } - var i = 0; - while ( geoNode.LayerElementUV[ i ] ) { + if ( geoNode.LayerElementUV ) { - if ( geoNode.LayerElementUV[ i ].UV ) { + geoInfo.uv = []; - geoInfo.uv.push( this.parseUVs( geoNode.LayerElementUV[ i ] ) ); + let i = 0; + while ( geoNode.LayerElementUV[ i ] ) { - } + if ( geoNode.LayerElementUV[ i ].UV ) { - i ++; + geoInfo.uv.push( this.parseUVs( geoNode.LayerElementUV[ i ] ) ); } + i ++; + } - geoInfo.weightTable = {}; + } - if ( skeleton !== null ) { + geoInfo.weightTable = {}; - geoInfo.skeleton = skeleton; + if ( skeleton !== null ) { - skeleton.rawBones.forEach( function ( rawBone, i ) { + geoInfo.skeleton = skeleton; - // loop over the bone's vertex indices and weights - rawBone.indices.forEach( function ( index, j ) { + skeleton.rawBones.forEach( function ( rawBone, i ) { - if ( geoInfo.weightTable[ index ] === undefined ) geoInfo.weightTable[ index ] = []; + // loop over the bone's vertex indices and weights + rawBone.indices.forEach( function ( index, j ) { - geoInfo.weightTable[ index ].push( { + if ( geoInfo.weightTable[ index ] === undefined ) geoInfo.weightTable[ index ] = []; - id: i, - weight: rawBone.weights[ j ], + geoInfo.weightTable[ index ].push( { - } ); + id: i, + weight: rawBone.weights[ j ], } ); } ); - } - - return geoInfo; - - }, + } ); - genBuffers: function ( geoInfo ) { + } - var buffers = { - vertex: [], - normal: [], - colors: [], - uvs: [], - materialIndex: [], - vertexWeights: [], - weightsIndices: [], - }; + return geoInfo; - var polygonIndex = 0; - var faceLength = 0; - var displayedWeightsWarning = false; + } - // these will hold data for a single face - var facePositionIndexes = []; - var faceNormals = []; - var faceColors = []; - var faceUVs = []; - var faceWeights = []; - var faceWeightIndices = []; + genBuffers( geoInfo ) { + + const buffers = { + vertex: [], + normal: [], + colors: [], + uvs: [], + materialIndex: [], + vertexWeights: [], + weightsIndices: [], + }; + + let polygonIndex = 0; + let faceLength = 0; + let displayedWeightsWarning = false; + + // these will hold data for a single face + let facePositionIndexes = []; + let faceNormals = []; + let faceColors = []; + let faceUVs = []; + let faceWeights = []; + let faceWeightIndices = []; + + const scope = this; + geoInfo.vertexIndices.forEach( function ( vertexIndex, polygonVertexIndex ) { + + let materialIndex; + let endOfFace = false; + + // Face index and vertex index arrays are combined in a single array + // A cube with quad faces looks like this: + // PolygonVertexIndex: *24 { + // a: 0, 1, 3, -3, 2, 3, 5, -5, 4, 5, 7, -7, 6, 7, 1, -1, 1, 7, 5, -4, 6, 0, 2, -5 + // } + // Negative numbers mark the end of a face - first face here is 0, 1, 3, -3 + // to find index of last vertex bit shift the index: ^ - 1 + if ( vertexIndex < 0 ) { + + vertexIndex = vertexIndex ^ - 1; // equivalent to ( x * -1 ) - 1 + endOfFace = true; - var scope = this; - geoInfo.vertexIndices.forEach( function ( vertexIndex, polygonVertexIndex ) { + } - var endOfFace = false; + let weightIndices = []; + let weights = []; - // Face index and vertex index arrays are combined in a single array - // A cube with quad faces looks like this: - // PolygonVertexIndex: *24 { - // a: 0, 1, 3, -3, 2, 3, 5, -5, 4, 5, 7, -7, 6, 7, 1, -1, 1, 7, 5, -4, 6, 0, 2, -5 - // } - // Negative numbers mark the end of a face - first face here is 0, 1, 3, -3 - // to find index of last vertex bit shift the index: ^ - 1 - if ( vertexIndex < 0 ) { + facePositionIndexes.push( vertexIndex * 3, vertexIndex * 3 + 1, vertexIndex * 3 + 2 ); - vertexIndex = vertexIndex ^ - 1; // equivalent to ( x * -1 ) - 1 - endOfFace = true; + if ( geoInfo.color ) { - } + const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.color ); - var weightIndices = []; - var weights = []; + faceColors.push( data[ 0 ], data[ 1 ], data[ 2 ] ); - facePositionIndexes.push( vertexIndex * 3, vertexIndex * 3 + 1, vertexIndex * 3 + 2 ); + } - if ( geoInfo.color ) { + if ( geoInfo.skeleton ) { - var data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.color ); + if ( geoInfo.weightTable[ vertexIndex ] !== undefined ) { - faceColors.push( data[ 0 ], data[ 1 ], data[ 2 ] ); + geoInfo.weightTable[ vertexIndex ].forEach( function ( wt ) { - } + weights.push( wt.weight ); + weightIndices.push( wt.id ); - if ( geoInfo.skeleton ) { + } ); - if ( geoInfo.weightTable[ vertexIndex ] !== undefined ) { - geoInfo.weightTable[ vertexIndex ].forEach( function ( wt ) { + } - weights.push( wt.weight ); - weightIndices.push( wt.id ); + if ( weights.length > 4 ) { - } ); + if ( ! displayedWeightsWarning ) { + console.warn( 'THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights.' ); + displayedWeightsWarning = true; } - if ( weights.length > 4 ) { - - if ( ! displayedWeightsWarning ) { - - console.warn( 'THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights.' ); - displayedWeightsWarning = true; - - } - - var wIndex = [ 0, 0, 0, 0 ]; - var Weight = [ 0, 0, 0, 0 ]; + const wIndex = [ 0, 0, 0, 0 ]; + const Weight = [ 0, 0, 0, 0 ]; - weights.forEach( function ( weight, weightIndex ) { + weights.forEach( function ( weight, weightIndex ) { - var currentWeight = weight; - var currentIndex = weightIndices[ weightIndex ]; + let currentWeight = weight; + let currentIndex = weightIndices[ weightIndex ]; - Weight.forEach( function ( comparedWeight, comparedWeightIndex, comparedWeightArray ) { + Weight.forEach( function ( comparedWeight, comparedWeightIndex, comparedWeightArray ) { - if ( currentWeight > comparedWeight ) { + if ( currentWeight > comparedWeight ) { - comparedWeightArray[ comparedWeightIndex ] = currentWeight; - currentWeight = comparedWeight; + comparedWeightArray[ comparedWeightIndex ] = currentWeight; + currentWeight = comparedWeight; - var tmp = wIndex[ comparedWeightIndex ]; - wIndex[ comparedWeightIndex ] = currentIndex; - currentIndex = tmp; + const tmp = wIndex[ comparedWeightIndex ]; + wIndex[ comparedWeightIndex ] = currentIndex; + currentIndex = tmp; - } - - } ); + } } ); - weightIndices = wIndex; - weights = Weight; + } ); - } + weightIndices = wIndex; + weights = Weight; - // if the weight array is shorter than 4 pad with 0s - while ( weights.length < 4 ) { + } - weights.push( 0 ); - weightIndices.push( 0 ); + // if the weight array is shorter than 4 pad with 0s + while ( weights.length < 4 ) { - } + weights.push( 0 ); + weightIndices.push( 0 ); - for ( var i = 0; i < 4; ++ i ) { + } - faceWeights.push( weights[ i ] ); - faceWeightIndices.push( weightIndices[ i ] ); + for ( let i = 0; i < 4; ++ i ) { - } + faceWeights.push( weights[ i ] ); + faceWeightIndices.push( weightIndices[ i ] ); } - if ( geoInfo.normal ) { + } - var data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.normal ); + if ( geoInfo.normal ) { - faceNormals.push( data[ 0 ], data[ 1 ], data[ 2 ] ); + const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.normal ); - } + faceNormals.push( data[ 0 ], data[ 1 ], data[ 2 ] ); - if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) { + } - var materialIndex = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material )[ 0 ]; + if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) { - } + materialIndex = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material )[ 0 ]; - if ( geoInfo.uv ) { + } - geoInfo.uv.forEach( function ( uv, i ) { + if ( geoInfo.uv ) { - var data = getData( polygonVertexIndex, polygonIndex, vertexIndex, uv ); + geoInfo.uv.forEach( function ( uv, i ) { - if ( faceUVs[ i ] === undefined ) { + const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, uv ); - faceUVs[ i ] = []; + if ( faceUVs[ i ] === undefined ) { - } + faceUVs[ i ] = []; - faceUVs[ i ].push( data[ 0 ] ); - faceUVs[ i ].push( data[ 1 ] ); + } - } ); + faceUVs[ i ].push( data[ 0 ] ); + faceUVs[ i ].push( data[ 1 ] ); - } + } ); - faceLength ++; + } - if ( endOfFace ) { + faceLength ++; - scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ); + if ( endOfFace ) { - polygonIndex ++; - faceLength = 0; + scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ); - // reset arrays for the next face - facePositionIndexes = []; - faceNormals = []; - faceColors = []; - faceUVs = []; - faceWeights = []; - faceWeightIndices = []; + polygonIndex ++; + faceLength = 0; - } + // reset arrays for the next face + facePositionIndexes = []; + faceNormals = []; + faceColors = []; + faceUVs = []; + faceWeights = []; + faceWeightIndices = []; - } ); + } - return buffers; + } ); - }, + return buffers; - // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris - genFace: function ( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) { + } - for ( var i = 2; i < faceLength; i ++ ) { + // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris + genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) { - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 0 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 1 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 2 ] ] ); + for ( let i = 2; i < faceLength; i ++ ) { - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 1 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 2 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 0 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 1 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 2 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 1 ] ] ); - buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 2 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 1 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 2 ] ] ); - if ( geoInfo.skeleton ) { + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 1 ] ] ); + buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 2 ] ] ); - buffers.vertexWeights.push( faceWeights[ 0 ] ); - buffers.vertexWeights.push( faceWeights[ 1 ] ); - buffers.vertexWeights.push( faceWeights[ 2 ] ); - buffers.vertexWeights.push( faceWeights[ 3 ] ); + if ( geoInfo.skeleton ) { - buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 ] ); - buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 1 ] ); - buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 2 ] ); - buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 3 ] ); + buffers.vertexWeights.push( faceWeights[ 0 ] ); + buffers.vertexWeights.push( faceWeights[ 1 ] ); + buffers.vertexWeights.push( faceWeights[ 2 ] ); + buffers.vertexWeights.push( faceWeights[ 3 ] ); - buffers.vertexWeights.push( faceWeights[ i * 4 ] ); - buffers.vertexWeights.push( faceWeights[ i * 4 + 1 ] ); - buffers.vertexWeights.push( faceWeights[ i * 4 + 2 ] ); - buffers.vertexWeights.push( faceWeights[ i * 4 + 3 ] ); + buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 ] ); + buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 1 ] ); + buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 2 ] ); + buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 3 ] ); - buffers.weightsIndices.push( faceWeightIndices[ 0 ] ); - buffers.weightsIndices.push( faceWeightIndices[ 1 ] ); - buffers.weightsIndices.push( faceWeightIndices[ 2 ] ); - buffers.weightsIndices.push( faceWeightIndices[ 3 ] ); + buffers.vertexWeights.push( faceWeights[ i * 4 ] ); + buffers.vertexWeights.push( faceWeights[ i * 4 + 1 ] ); + buffers.vertexWeights.push( faceWeights[ i * 4 + 2 ] ); + buffers.vertexWeights.push( faceWeights[ i * 4 + 3 ] ); - buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 ] ); - buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 1 ] ); - buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 2 ] ); - buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 3 ] ); + buffers.weightsIndices.push( faceWeightIndices[ 0 ] ); + buffers.weightsIndices.push( faceWeightIndices[ 1 ] ); + buffers.weightsIndices.push( faceWeightIndices[ 2 ] ); + buffers.weightsIndices.push( faceWeightIndices[ 3 ] ); - buffers.weightsIndices.push( faceWeightIndices[ i * 4 ] ); - buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 1 ] ); - buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 2 ] ); - buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 3 ] ); + buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 ] ); + buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 1 ] ); + buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 2 ] ); + buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 3 ] ); - } + buffers.weightsIndices.push( faceWeightIndices[ i * 4 ] ); + buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 1 ] ); + buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 2 ] ); + buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 3 ] ); - if ( geoInfo.color ) { + } - buffers.colors.push( faceColors[ 0 ] ); - buffers.colors.push( faceColors[ 1 ] ); - buffers.colors.push( faceColors[ 2 ] ); + if ( geoInfo.color ) { - buffers.colors.push( faceColors[ ( i - 1 ) * 3 ] ); - buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 1 ] ); - buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 2 ] ); + buffers.colors.push( faceColors[ 0 ] ); + buffers.colors.push( faceColors[ 1 ] ); + buffers.colors.push( faceColors[ 2 ] ); - buffers.colors.push( faceColors[ i * 3 ] ); - buffers.colors.push( faceColors[ i * 3 + 1 ] ); - buffers.colors.push( faceColors[ i * 3 + 2 ] ); + buffers.colors.push( faceColors[ ( i - 1 ) * 3 ] ); + buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 1 ] ); + buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 2 ] ); - } + buffers.colors.push( faceColors[ i * 3 ] ); + buffers.colors.push( faceColors[ i * 3 + 1 ] ); + buffers.colors.push( faceColors[ i * 3 + 2 ] ); - if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) { + } - buffers.materialIndex.push( materialIndex ); - buffers.materialIndex.push( materialIndex ); - buffers.materialIndex.push( materialIndex ); + if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) { - } + buffers.materialIndex.push( materialIndex ); + buffers.materialIndex.push( materialIndex ); + buffers.materialIndex.push( materialIndex ); - if ( geoInfo.normal ) { + } - buffers.normal.push( faceNormals[ 0 ] ); - buffers.normal.push( faceNormals[ 1 ] ); - buffers.normal.push( faceNormals[ 2 ] ); + if ( geoInfo.normal ) { - buffers.normal.push( faceNormals[ ( i - 1 ) * 3 ] ); - buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 1 ] ); - buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 2 ] ); + buffers.normal.push( faceNormals[ 0 ] ); + buffers.normal.push( faceNormals[ 1 ] ); + buffers.normal.push( faceNormals[ 2 ] ); - buffers.normal.push( faceNormals[ i * 3 ] ); - buffers.normal.push( faceNormals[ i * 3 + 1 ] ); - buffers.normal.push( faceNormals[ i * 3 + 2 ] ); + buffers.normal.push( faceNormals[ ( i - 1 ) * 3 ] ); + buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 1 ] ); + buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 2 ] ); - } + buffers.normal.push( faceNormals[ i * 3 ] ); + buffers.normal.push( faceNormals[ i * 3 + 1 ] ); + buffers.normal.push( faceNormals[ i * 3 + 2 ] ); - if ( geoInfo.uv ) { + } - geoInfo.uv.forEach( function ( uv, j ) { + if ( geoInfo.uv ) { - if ( buffers.uvs[ j ] === undefined ) buffers.uvs[ j ] = []; + geoInfo.uv.forEach( function ( uv, j ) { - buffers.uvs[ j ].push( faceUVs[ j ][ 0 ] ); - buffers.uvs[ j ].push( faceUVs[ j ][ 1 ] ); + if ( buffers.uvs[ j ] === undefined ) buffers.uvs[ j ] = []; - buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 ] ); - buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 + 1 ] ); + buffers.uvs[ j ].push( faceUVs[ j ][ 0 ] ); + buffers.uvs[ j ].push( faceUVs[ j ][ 1 ] ); - buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 ] ); - buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 + 1 ] ); + buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 ] ); + buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 + 1 ] ); - } ); + buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 ] ); + buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 + 1 ] ); - } + } ); } - }, + } - addMorphTargets: function ( parentGeo, parentGeoNode, morphTargets, preTransform ) { + } - if ( morphTargets.length === 0 ) return; + addMorphTargets( parentGeo, parentGeoNode, morphTargets, preTransform ) { - parentGeo.morphTargetsRelative = true; + if ( morphTargets.length === 0 ) return; - parentGeo.morphAttributes.position = []; - // parentGeo.morphAttributes.normal = []; // not implemented + parentGeo.morphTargetsRelative = true; - var scope = this; - morphTargets.forEach( function ( morphTarget ) { + parentGeo.morphAttributes.position = []; + // parentGeo.morphAttributes.normal = []; // not implemented - morphTarget.rawTargets.forEach( function ( rawTarget ) { + const scope = this; + morphTargets.forEach( function ( morphTarget ) { - var morphGeoNode = fbxTree.Objects.Geometry[ rawTarget.geoID ]; + morphTarget.rawTargets.forEach( function ( rawTarget ) { - if ( morphGeoNode !== undefined ) { + const morphGeoNode = fbxTree.Objects.Geometry[ rawTarget.geoID ]; - scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name ); + if ( morphGeoNode !== undefined ) { - } + scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name ); - } ); + } } ); - }, - - // a morph geometry node is similar to a standard node, and the node is also contained - // in FBXTree.Objects.Geometry, however it can only have attributes for position, normal - // and a special attribute Index defining which vertices of the original geometry are affected - // Normal and position attributes only have data for the vertices that are affected by the morph - genMorphGeometry: function ( parentGeo, parentGeoNode, morphGeoNode, preTransform, name ) { - - var vertexIndices = ( parentGeoNode.PolygonVertexIndex !== undefined ) ? parentGeoNode.PolygonVertexIndex.a : []; - - var morphPositionsSparse = ( morphGeoNode.Vertices !== undefined ) ? morphGeoNode.Vertices.a : []; - var indices = ( morphGeoNode.Indexes !== undefined ) ? morphGeoNode.Indexes.a : []; - - var length = parentGeo.attributes.position.count * 3; - var morphPositions = new Float32Array( length ); - - for ( var i = 0; i < indices.length; i ++ ) { - - var morphIndex = indices[ i ] * 3; + } ); - morphPositions[ morphIndex ] = morphPositionsSparse[ i * 3 ]; - morphPositions[ morphIndex + 1 ] = morphPositionsSparse[ i * 3 + 1 ]; - morphPositions[ morphIndex + 2 ] = morphPositionsSparse[ i * 3 + 2 ]; + } - } + // a morph geometry node is similar to a standard node, and the node is also contained + // in FBXTree.Objects.Geometry, however it can only have attributes for position, normal + // and a special attribute Index defining which vertices of the original geometry are affected + // Normal and position attributes only have data for the vertices that are affected by the morph + genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, name ) { - // TODO: add morph normal support - var morphGeoInfo = { - vertexIndices: vertexIndices, - vertexPositions: morphPositions, + const vertexIndices = ( parentGeoNode.PolygonVertexIndex !== undefined ) ? parentGeoNode.PolygonVertexIndex.a : []; - }; + const morphPositionsSparse = ( morphGeoNode.Vertices !== undefined ) ? morphGeoNode.Vertices.a : []; + const indices = ( morphGeoNode.Indexes !== undefined ) ? morphGeoNode.Indexes.a : []; - var morphBuffers = this.genBuffers( morphGeoInfo ); + const length = parentGeo.attributes.position.count * 3; + const morphPositions = new Float32Array( length ); - var positionAttribute = new Float32BufferAttribute( morphBuffers.vertex, 3 ); - positionAttribute.name = name || morphGeoNode.attrName; + for ( let i = 0; i < indices.length; i ++ ) { - positionAttribute.applyMatrix4( preTransform ); + const morphIndex = indices[ i ] * 3; - parentGeo.morphAttributes.position.push( positionAttribute ); + morphPositions[ morphIndex ] = morphPositionsSparse[ i * 3 ]; + morphPositions[ morphIndex + 1 ] = morphPositionsSparse[ i * 3 + 1 ]; + morphPositions[ morphIndex + 2 ] = morphPositionsSparse[ i * 3 + 2 ]; - }, + } - // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists - parseNormals: function ( NormalNode ) { + // TODO: add morph normal support + const morphGeoInfo = { + vertexIndices: vertexIndices, + vertexPositions: morphPositions, - var mappingType = NormalNode.MappingInformationType; - var referenceType = NormalNode.ReferenceInformationType; - var buffer = NormalNode.Normals.a; - var indexBuffer = []; - if ( referenceType === 'IndexToDirect' ) { + }; - if ( 'NormalIndex' in NormalNode ) { + const morphBuffers = this.genBuffers( morphGeoInfo ); - indexBuffer = NormalNode.NormalIndex.a; + const positionAttribute = new Float32BufferAttribute( morphBuffers.vertex, 3 ); + positionAttribute.name = name || morphGeoNode.attrName; - } else if ( 'NormalsIndex' in NormalNode ) { + positionAttribute.applyMatrix4( preTransform ); - indexBuffer = NormalNode.NormalsIndex.a; + parentGeo.morphAttributes.position.push( positionAttribute ); - } + } - } + // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists + parseNormals( NormalNode ) { - return { - dataSize: 3, - buffer: buffer, - indices: indexBuffer, - mappingType: mappingType, - referenceType: referenceType - }; + const mappingType = NormalNode.MappingInformationType; + const referenceType = NormalNode.ReferenceInformationType; + const buffer = NormalNode.Normals.a; + let indexBuffer = []; + if ( referenceType === 'IndexToDirect' ) { - }, + if ( 'NormalIndex' in NormalNode ) { - // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists - parseUVs: function ( UVNode ) { + indexBuffer = NormalNode.NormalIndex.a; - var mappingType = UVNode.MappingInformationType; - var referenceType = UVNode.ReferenceInformationType; - var buffer = UVNode.UV.a; - var indexBuffer = []; - if ( referenceType === 'IndexToDirect' ) { + } else if ( 'NormalsIndex' in NormalNode ) { - indexBuffer = UVNode.UVIndex.a; + indexBuffer = NormalNode.NormalsIndex.a; } - return { - dataSize: 2, - buffer: buffer, - indices: indexBuffer, - mappingType: mappingType, - referenceType: referenceType - }; + } - }, + return { + dataSize: 3, + buffer: buffer, + indices: indexBuffer, + mappingType: mappingType, + referenceType: referenceType + }; - // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists - parseVertexColors: function ( ColorNode ) { + } - var mappingType = ColorNode.MappingInformationType; - var referenceType = ColorNode.ReferenceInformationType; - var buffer = ColorNode.Colors.a; - var indexBuffer = []; - if ( referenceType === 'IndexToDirect' ) { + // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists + parseUVs( UVNode ) { - indexBuffer = ColorNode.ColorIndex.a; + const mappingType = UVNode.MappingInformationType; + const referenceType = UVNode.ReferenceInformationType; + const buffer = UVNode.UV.a; + let indexBuffer = []; + if ( referenceType === 'IndexToDirect' ) { - } + indexBuffer = UVNode.UVIndex.a; - return { - dataSize: 4, - buffer: buffer, - indices: indexBuffer, - mappingType: mappingType, - referenceType: referenceType - }; + } - }, + return { + dataSize: 2, + buffer: buffer, + indices: indexBuffer, + mappingType: mappingType, + referenceType: referenceType + }; - // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists - parseMaterialIndices: function ( MaterialNode ) { + } - var mappingType = MaterialNode.MappingInformationType; - var referenceType = MaterialNode.ReferenceInformationType; + // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists + parseVertexColors( ColorNode ) { - if ( mappingType === 'NoMappingInformation' ) { + const mappingType = ColorNode.MappingInformationType; + const referenceType = ColorNode.ReferenceInformationType; + const buffer = ColorNode.Colors.a; + let indexBuffer = []; + if ( referenceType === 'IndexToDirect' ) { - return { - dataSize: 1, - buffer: [ 0 ], - indices: [ 0 ], - mappingType: 'AllSame', - referenceType: referenceType - }; + indexBuffer = ColorNode.ColorIndex.a; - } + } - var materialIndexBuffer = MaterialNode.Materials.a; + return { + dataSize: 4, + buffer: buffer, + indices: indexBuffer, + mappingType: mappingType, + referenceType: referenceType + }; - // Since materials are stored as indices, there's a bit of a mismatch between FBX and what - // we expect.So we create an intermediate buffer that points to the index in the buffer, - // for conforming with the other functions we've written for other data. - var materialIndices = []; + } - for ( var i = 0; i < materialIndexBuffer.length; ++ i ) { + // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists + parseMaterialIndices( MaterialNode ) { - materialIndices.push( i ); + const mappingType = MaterialNode.MappingInformationType; + const referenceType = MaterialNode.ReferenceInformationType; - } + if ( mappingType === 'NoMappingInformation' ) { return { dataSize: 1, - buffer: materialIndexBuffer, - indices: materialIndices, - mappingType: mappingType, + buffer: [ 0 ], + indices: [ 0 ], + mappingType: 'AllSame', referenceType: referenceType }; - }, - - // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry - parseNurbsGeometry: function ( geoNode ) { - - if ( NURBSCurve === undefined ) { - - console.error( 'THREE.FBXLoader: The loader relies on NURBSCurve for any nurbs present in the model. Nurbs will show up as empty geometry.' ); - return new BufferGeometry(); - - } - - var order = parseInt( geoNode.Order ); - - if ( isNaN( order ) ) { - - console.error( 'THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geoNode.Order, geoNode.id ); - return new BufferGeometry(); + } - } + const materialIndexBuffer = MaterialNode.Materials.a; - var degree = order - 1; + // Since materials are stored as indices, there's a bit of a mismatch between FBX and what + // we expect.So we create an intermediate buffer that points to the index in the buffer, + // for conforming with the other functions we've written for other data. + const materialIndices = []; - var knots = geoNode.KnotVector.a; - var controlPoints = []; - var pointsValues = geoNode.Points.a; + for ( let i = 0; i < materialIndexBuffer.length; ++ i ) { - for ( var i = 0, l = pointsValues.length; i < l; i += 4 ) { + materialIndices.push( i ); - controlPoints.push( new Vector4().fromArray( pointsValues, i ) ); + } - } + return { + dataSize: 1, + buffer: materialIndexBuffer, + indices: materialIndices, + mappingType: mappingType, + referenceType: referenceType + }; - var startKnot, endKnot; + } - if ( geoNode.Form === 'Closed' ) { + // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry + parseNurbsGeometry( geoNode ) { - controlPoints.push( controlPoints[ 0 ] ); + if ( NURBSCurve === undefined ) { - } else if ( geoNode.Form === 'Periodic' ) { + console.error( 'THREE.FBXLoader: The loader relies on NURBSCurve for any nurbs present in the model. Nurbs will show up as empty geometry.' ); + return new BufferGeometry(); - startKnot = degree; - endKnot = knots.length - 1 - startKnot; + } - for ( var i = 0; i < degree; ++ i ) { + const order = parseInt( geoNode.Order ); - controlPoints.push( controlPoints[ i ] ); + if ( isNaN( order ) ) { - } + console.error( 'THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geoNode.Order, geoNode.id ); + return new BufferGeometry(); - } + } - var curve = new NURBSCurve( degree, knots, controlPoints, startKnot, endKnot ); - var vertices = curve.getPoints( controlPoints.length * 7 ); + const degree = order - 1; - var positions = new Float32Array( vertices.length * 3 ); + const knots = geoNode.KnotVector.a; + const controlPoints = []; + const pointsValues = geoNode.Points.a; - vertices.forEach( function ( vertex, i ) { + for ( let i = 0, l = pointsValues.length; i < l; i += 4 ) { - vertex.toArray( positions, i * 3 ); + controlPoints.push( new Vector4().fromArray( pointsValues, i ) ); - } ); + } - var geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); + let startKnot, endKnot; - return geometry; + if ( geoNode.Form === 'Closed' ) { - }, + controlPoints.push( controlPoints[ 0 ] ); - }; + } else if ( geoNode.Form === 'Periodic' ) { - // parse animation data from FBXTree - function AnimationParser() {} + startKnot = degree; + endKnot = knots.length - 1 - startKnot; - AnimationParser.prototype = { + for ( let i = 0; i < degree; ++ i ) { - constructor: AnimationParser, + controlPoints.push( controlPoints[ i ] ); - // take raw animation clips and turn them into three.js animation clips - parse: function () { + } - var animationClips = []; + } - var rawClips = this.parseClips(); + const curve = new NURBSCurve( degree, knots, controlPoints, startKnot, endKnot ); + const vertices = curve.getPoints( controlPoints.length * 7 ); - if ( rawClips !== undefined ) { + const positions = new Float32Array( vertices.length * 3 ); - for ( var key in rawClips ) { + vertices.forEach( function ( vertex, i ) { - var rawClip = rawClips[ key ]; + vertex.toArray( positions, i * 3 ); - var clip = this.addClip( rawClip ); + } ); - animationClips.push( clip ); + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); - } + return geometry; - } + } - return animationClips; +} - }, +// parse animation data from FBXTree +class AnimationParser { - parseClips: function () { + // take raw animation clips and turn them into three.js animation clips + parse() { - // since the actual transformation data is stored in FBXTree.Objects.AnimationCurve, - // if this is undefined we can safely assume there are no animations - if ( fbxTree.Objects.AnimationCurve === undefined ) return undefined; + const animationClips = []; - var curveNodesMap = this.parseAnimationCurveNodes(); + const rawClips = this.parseClips(); - this.parseAnimationCurves( curveNodesMap ); + if ( rawClips !== undefined ) { - var layersMap = this.parseAnimationLayers( curveNodesMap ); - var rawClips = this.parseAnimStacks( layersMap ); + for ( const key in rawClips ) { - return rawClips; + const rawClip = rawClips[ key ]; - }, + const clip = this.addClip( rawClip ); - // parse nodes in FBXTree.Objects.AnimationCurveNode - // each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation ) - // and is referenced by an AnimationLayer - parseAnimationCurveNodes: function () { + animationClips.push( clip ); - var rawCurveNodes = fbxTree.Objects.AnimationCurveNode; + } - var curveNodesMap = new Map(); + } - for ( var nodeID in rawCurveNodes ) { + return animationClips; - var rawCurveNode = rawCurveNodes[ nodeID ]; + } - if ( rawCurveNode.attrName.match( /S|R|T|DeformPercent/ ) !== null ) { + parseClips() { - var curveNode = { + // since the actual transformation data is stored in FBXTree.Objects.AnimationCurve, + // if this is undefined we can safely assume there are no animations + if ( fbxTree.Objects.AnimationCurve === undefined ) return undefined; - id: rawCurveNode.id, - attr: rawCurveNode.attrName, - curves: {}, + const curveNodesMap = this.parseAnimationCurveNodes(); - }; + this.parseAnimationCurves( curveNodesMap ); - curveNodesMap.set( curveNode.id, curveNode ); + const layersMap = this.parseAnimationLayers( curveNodesMap ); + const rawClips = this.parseAnimStacks( layersMap ); - } + return rawClips; - } + } - return curveNodesMap; + // parse nodes in FBXTree.Objects.AnimationCurveNode + // each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation ) + // and is referenced by an AnimationLayer + parseAnimationCurveNodes() { - }, + const rawCurveNodes = fbxTree.Objects.AnimationCurveNode; - // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to - // previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated - // axis ( e.g. times and values of x rotation) - parseAnimationCurves: function ( curveNodesMap ) { + const curveNodesMap = new Map(); - var rawCurves = fbxTree.Objects.AnimationCurve; + for ( const nodeID in rawCurveNodes ) { - // TODO: Many values are identical up to roundoff error, but won't be optimised - // e.g. position times: [0, 0.4, 0. 8] - // position values: [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.235384487103147e-7, 93.67520904541016, -0.9982695579528809] - // clearly, this should be optimised to - // times: [0], positions [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809] - // this shows up in nearly every FBX file, and generally time array is length > 100 + const rawCurveNode = rawCurveNodes[ nodeID ]; - for ( var nodeID in rawCurves ) { + if ( rawCurveNode.attrName.match( /S|R|T|DeformPercent/ ) !== null ) { - var animationCurve = { + const curveNode = { - id: rawCurves[ nodeID ].id, - times: rawCurves[ nodeID ].KeyTime.a.map( convertFBXTimeToSeconds ), - values: rawCurves[ nodeID ].KeyValueFloat.a, + id: rawCurveNode.id, + attr: rawCurveNode.attrName, + curves: {}, }; - var relationships = connections.get( animationCurve.id ); + curveNodesMap.set( curveNode.id, curveNode ); - if ( relationships !== undefined ) { - - var animationCurveID = relationships.parents[ 0 ].ID; - var animationCurveRelationship = relationships.parents[ 0 ].relationship; + } - if ( animationCurveRelationship.match( /X/ ) ) { + } - curveNodesMap.get( animationCurveID ).curves[ 'x' ] = animationCurve; + return curveNodesMap; - } else if ( animationCurveRelationship.match( /Y/ ) ) { + } - curveNodesMap.get( animationCurveID ).curves[ 'y' ] = animationCurve; + // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to + // previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated + // axis ( e.g. times and values of x rotation) + parseAnimationCurves( curveNodesMap ) { - } else if ( animationCurveRelationship.match( /Z/ ) ) { + const rawCurves = fbxTree.Objects.AnimationCurve; - curveNodesMap.get( animationCurveID ).curves[ 'z' ] = animationCurve; + // TODO: Many values are identical up to roundoff error, but won't be optimised + // e.g. position times: [0, 0.4, 0. 8] + // position values: [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.235384487103147e-7, 93.67520904541016, -0.9982695579528809] + // clearly, this should be optimised to + // times: [0], positions [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809] + // this shows up in nearly every FBX file, and generally time array is length > 100 - } else if ( animationCurveRelationship.match( /d|DeformPercent/ ) && curveNodesMap.has( animationCurveID ) ) { + for ( const nodeID in rawCurves ) { - curveNodesMap.get( animationCurveID ).curves[ 'morph' ] = animationCurve; + const animationCurve = { - } + id: rawCurves[ nodeID ].id, + times: rawCurves[ nodeID ].KeyTime.a.map( convertFBXTimeToSeconds ), + values: rawCurves[ nodeID ].KeyValueFloat.a, - } + }; - } + const relationships = connections.get( animationCurve.id ); - }, + if ( relationships !== undefined ) { - // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references - // to various AnimationCurveNodes and is referenced by an AnimationStack node - // note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack - parseAnimationLayers: function ( curveNodesMap ) { + const animationCurveID = relationships.parents[ 0 ].ID; + const animationCurveRelationship = relationships.parents[ 0 ].relationship; - var rawLayers = fbxTree.Objects.AnimationLayer; + if ( animationCurveRelationship.match( /X/ ) ) { - var layersMap = new Map(); + curveNodesMap.get( animationCurveID ).curves[ 'x' ] = animationCurve; - for ( var nodeID in rawLayers ) { + } else if ( animationCurveRelationship.match( /Y/ ) ) { - var layerCurveNodes = []; + curveNodesMap.get( animationCurveID ).curves[ 'y' ] = animationCurve; - var connection = connections.get( parseInt( nodeID ) ); + } else if ( animationCurveRelationship.match( /Z/ ) ) { - if ( connection !== undefined ) { + curveNodesMap.get( animationCurveID ).curves[ 'z' ] = animationCurve; - // all the animationCurveNodes used in the layer - var children = connection.children; + } else if ( animationCurveRelationship.match( /d|DeformPercent/ ) && curveNodesMap.has( animationCurveID ) ) { - children.forEach( function ( child, i ) { + curveNodesMap.get( animationCurveID ).curves[ 'morph' ] = animationCurve; - if ( curveNodesMap.has( child.ID ) ) { + } - var curveNode = curveNodesMap.get( child.ID ); + } - // check that the curves are defined for at least one axis, otherwise ignore the curveNode - if ( curveNode.curves.x !== undefined || curveNode.curves.y !== undefined || curveNode.curves.z !== undefined ) { + } - if ( layerCurveNodes[ i ] === undefined ) { + } - var modelID = connections.get( child.ID ).parents.filter( function ( parent ) { + // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references + // to various AnimationCurveNodes and is referenced by an AnimationStack node + // note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack + parseAnimationLayers( curveNodesMap ) { - return parent.relationship !== undefined; + const rawLayers = fbxTree.Objects.AnimationLayer; - } )[ 0 ].ID; + const layersMap = new Map(); - if ( modelID !== undefined ) { + for ( const nodeID in rawLayers ) { - var rawModel = fbxTree.Objects.Model[ modelID.toString() ]; + const layerCurveNodes = []; - if ( rawModel === undefined ) { + const connection = connections.get( parseInt( nodeID ) ); - console.warn( 'THREE.FBXLoader: Encountered a unused curve.', child ); - return; + if ( connection !== undefined ) { - } + // all the animationCurveNodes used in the layer + const children = connection.children; - var node = { + children.forEach( function ( child, i ) { - modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName( rawModel.attrName ) : '', - ID: rawModel.id, - initialPosition: [ 0, 0, 0 ], - initialRotation: [ 0, 0, 0 ], - initialScale: [ 1, 1, 1 ], + if ( curveNodesMap.has( child.ID ) ) { - }; + const curveNode = curveNodesMap.get( child.ID ); - sceneGraph.traverse( function ( child ) { + // check that the curves are defined for at least one axis, otherwise ignore the curveNode + if ( curveNode.curves.x !== undefined || curveNode.curves.y !== undefined || curveNode.curves.z !== undefined ) { - if ( child.ID === rawModel.id ) { + if ( layerCurveNodes[ i ] === undefined ) { - node.transform = child.matrix; + const modelID = connections.get( child.ID ).parents.filter( function ( parent ) { - if ( child.userData.transformData ) node.eulerOrder = child.userData.transformData.eulerOrder; + return parent.relationship !== undefined; - } + } )[ 0 ].ID; - } ); + if ( modelID !== undefined ) { - if ( ! node.transform ) node.transform = new Matrix4(); + const rawModel = fbxTree.Objects.Model[ modelID.toString() ]; - // if the animated model is pre rotated, we'll have to apply the pre rotations to every - // animation value as well - if ( 'PreRotation' in rawModel ) node.preRotation = rawModel.PreRotation.value; - if ( 'PostRotation' in rawModel ) node.postRotation = rawModel.PostRotation.value; + if ( rawModel === undefined ) { - layerCurveNodes[ i ] = node; + console.warn( 'THREE.FBXLoader: Encountered a unused curve.', child ); + return; } - } - - if ( layerCurveNodes[ i ] ) layerCurveNodes[ i ][ curveNode.attr ] = curveNode; - - } else if ( curveNode.curves.morph !== undefined ) { + const node = { - if ( layerCurveNodes[ i ] === undefined ) { + modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName( rawModel.attrName ) : '', + ID: rawModel.id, + initialPosition: [ 0, 0, 0 ], + initialRotation: [ 0, 0, 0 ], + initialScale: [ 1, 1, 1 ], - var deformerID = connections.get( child.ID ).parents.filter( function ( parent ) { + }; - return parent.relationship !== undefined; + sceneGraph.traverse( function ( child ) { - } )[ 0 ].ID; + if ( child.ID === rawModel.id ) { - var morpherID = connections.get( deformerID ).parents[ 0 ].ID; - var geoID = connections.get( morpherID ).parents[ 0 ].ID; + node.transform = child.matrix; - // assuming geometry is not used in more than one model - var modelID = connections.get( geoID ).parents[ 0 ].ID; + if ( child.userData.transformData ) node.eulerOrder = child.userData.transformData.eulerOrder; - var rawModel = fbxTree.Objects.Model[ modelID ]; + } - var node = { + } ); - modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName( rawModel.attrName ) : '', - morphName: fbxTree.Objects.Deformer[ deformerID ].attrName, + if ( ! node.transform ) node.transform = new Matrix4(); - }; + // if the animated model is pre rotated, we'll have to apply the pre rotations to every + // animation value as well + if ( 'PreRotation' in rawModel ) node.preRotation = rawModel.PreRotation.value; + if ( 'PostRotation' in rawModel ) node.postRotation = rawModel.PostRotation.value; layerCurveNodes[ i ] = node; } - layerCurveNodes[ i ][ curveNode.attr ] = curveNode; - } - } + if ( layerCurveNodes[ i ] ) layerCurveNodes[ i ][ curveNode.attr ] = curveNode; - } ); + } else if ( curveNode.curves.morph !== undefined ) { - layersMap.set( parseInt( nodeID ), layerCurveNodes ); + if ( layerCurveNodes[ i ] === undefined ) { - } + const deformerID = connections.get( child.ID ).parents.filter( function ( parent ) { - } + return parent.relationship !== undefined; - return layersMap; + } )[ 0 ].ID; - }, + const morpherID = connections.get( deformerID ).parents[ 0 ].ID; + const geoID = connections.get( morpherID ).parents[ 0 ].ID; - // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation - // hierarchy. Each Stack node will be used to create a AnimationClip - parseAnimStacks: function ( layersMap ) { + // assuming geometry is not used in more than one model + const modelID = connections.get( geoID ).parents[ 0 ].ID; - var rawStacks = fbxTree.Objects.AnimationStack; + const rawModel = fbxTree.Objects.Model[ modelID ]; - // connect the stacks (clips) up to the layers - var rawClips = {}; + const node = { - for ( var nodeID in rawStacks ) { + modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName( rawModel.attrName ) : '', + morphName: fbxTree.Objects.Deformer[ deformerID ].attrName, - var children = connections.get( parseInt( nodeID ) ).children; + }; - if ( children.length > 1 ) { + layerCurveNodes[ i ] = node; - // it seems like stacks will always be associated with a single layer. But just in case there are files - // where there are multiple layers per stack, we'll display a warning - console.warn( 'THREE.FBXLoader: Encountered an animation stack with multiple layers, this is currently not supported. Ignoring subsequent layers.' ); + } - } + layerCurveNodes[ i ][ curveNode.attr ] = curveNode; - var layer = layersMap.get( children[ 0 ].ID ); + } - rawClips[ nodeID ] = { + } - name: rawStacks[ nodeID ].attrName, - layer: layer, + } ); - }; + layersMap.set( parseInt( nodeID ), layerCurveNodes ); } - return rawClips; - - }, - - addClip: function ( rawClip ) { - - var tracks = []; + } - var scope = this; - rawClip.layer.forEach( function ( rawTracks ) { + return layersMap; - tracks = tracks.concat( scope.generateTracks( rawTracks ) ); + } - } ); + // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation + // hierarchy. Each Stack node will be used to create a AnimationClip + parseAnimStacks( layersMap ) { - return new AnimationClip( rawClip.name, - 1, tracks ); + const rawStacks = fbxTree.Objects.AnimationStack; - }, + // connect the stacks (clips) up to the layers + const rawClips = {}; - generateTracks: function ( rawTracks ) { + for ( const nodeID in rawStacks ) { - var tracks = []; + const children = connections.get( parseInt( nodeID ) ).children; - var initialPosition = new Vector3(); - var initialRotation = new Quaternion(); - var initialScale = new Vector3(); + if ( children.length > 1 ) { - if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition, initialRotation, initialScale ); + // it seems like stacks will always be associated with a single layer. But just in case there are files + // where there are multiple layers per stack, we'll display a warning + console.warn( 'THREE.FBXLoader: Encountered an animation stack with multiple layers, this is currently not supported. Ignoring subsequent layers.' ); - initialPosition = initialPosition.toArray(); - initialRotation = new Euler().setFromQuaternion( initialRotation, rawTracks.eulerOrder ).toArray(); - initialScale = initialScale.toArray(); + } - if ( rawTracks.T !== undefined && Object.keys( rawTracks.T.curves ).length > 0 ) { + const layer = layersMap.get( children[ 0 ].ID ); - var positionTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.T.curves, initialPosition, 'position' ); - if ( positionTrack !== undefined ) tracks.push( positionTrack ); + rawClips[ nodeID ] = { - } + name: rawStacks[ nodeID ].attrName, + layer: layer, - if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) { + }; - var rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, initialRotation, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder ); - if ( rotationTrack !== undefined ) tracks.push( rotationTrack ); + } - } + return rawClips; - if ( rawTracks.S !== undefined && Object.keys( rawTracks.S.curves ).length > 0 ) { + } - var scaleTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.S.curves, initialScale, 'scale' ); - if ( scaleTrack !== undefined ) tracks.push( scaleTrack ); + addClip( rawClip ) { - } + let tracks = []; - if ( rawTracks.DeformPercent !== undefined ) { + const scope = this; + rawClip.layer.forEach( function ( rawTracks ) { - var morphTrack = this.generateMorphTrack( rawTracks ); - if ( morphTrack !== undefined ) tracks.push( morphTrack ); + tracks = tracks.concat( scope.generateTracks( rawTracks ) ); - } + } ); - return tracks; + return new AnimationClip( rawClip.name, - 1, tracks ); - }, + } - generateVectorTrack: function ( modelName, curves, initialValue, type ) { + generateTracks( rawTracks ) { - var times = this.getTimesForAllAxes( curves ); - var values = this.getKeyframeTrackValues( times, curves, initialValue ); + const tracks = []; - return new VectorKeyframeTrack( modelName + '.' + type, times, values ); + let initialPosition = new Vector3(); + let initialRotation = new Quaternion(); + let initialScale = new Vector3(); - }, + if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition, initialRotation, initialScale ); - generateRotationTrack: function ( modelName, curves, initialValue, preRotation, postRotation, eulerOrder ) { + initialPosition = initialPosition.toArray(); + initialRotation = new Euler().setFromQuaternion( initialRotation, rawTracks.eulerOrder ).toArray(); + initialScale = initialScale.toArray(); - if ( curves.x !== undefined ) { + if ( rawTracks.T !== undefined && Object.keys( rawTracks.T.curves ).length > 0 ) { - this.interpolateRotations( curves.x ); - curves.x.values = curves.x.values.map( MathUtils.degToRad ); + const positionTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.T.curves, initialPosition, 'position' ); + if ( positionTrack !== undefined ) tracks.push( positionTrack ); - } + } - if ( curves.y !== undefined ) { + if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) { - this.interpolateRotations( curves.y ); - curves.y.values = curves.y.values.map( MathUtils.degToRad ); + const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, initialRotation, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder ); + if ( rotationTrack !== undefined ) tracks.push( rotationTrack ); - } + } - if ( curves.z !== undefined ) { + if ( rawTracks.S !== undefined && Object.keys( rawTracks.S.curves ).length > 0 ) { - this.interpolateRotations( curves.z ); - curves.z.values = curves.z.values.map( MathUtils.degToRad ); + const scaleTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.S.curves, initialScale, 'scale' ); + if ( scaleTrack !== undefined ) tracks.push( scaleTrack ); - } + } - var times = this.getTimesForAllAxes( curves ); - var values = this.getKeyframeTrackValues( times, curves, initialValue ); + if ( rawTracks.DeformPercent !== undefined ) { - if ( preRotation !== undefined ) { + const morphTrack = this.generateMorphTrack( rawTracks ); + if ( morphTrack !== undefined ) tracks.push( morphTrack ); - preRotation = preRotation.map( MathUtils.degToRad ); - preRotation.push( eulerOrder ); + } - preRotation = new Euler().fromArray( preRotation ); - preRotation = new Quaternion().setFromEuler( preRotation ); + return tracks; - } + } - if ( postRotation !== undefined ) { + generateVectorTrack( modelName, curves, initialValue, type ) { - postRotation = postRotation.map( MathUtils.degToRad ); - postRotation.push( eulerOrder ); + const times = this.getTimesForAllAxes( curves ); + const values = this.getKeyframeTrackValues( times, curves, initialValue ); - postRotation = new Euler().fromArray( postRotation ); - postRotation = new Quaternion().setFromEuler( postRotation ).invert(); + return new VectorKeyframeTrack( modelName + '.' + type, times, values ); - } + } - var quaternion = new Quaternion(); - var euler = new Euler(); + generateRotationTrack( modelName, curves, initialValue, preRotation, postRotation, eulerOrder ) { - var quaternionValues = []; + if ( curves.x !== undefined ) { - for ( var i = 0; i < values.length; i += 3 ) { + this.interpolateRotations( curves.x ); + curves.x.values = curves.x.values.map( MathUtils.degToRad ); - euler.set( values[ i ], values[ i + 1 ], values[ i + 2 ], eulerOrder ); + } - quaternion.setFromEuler( euler ); + if ( curves.y !== undefined ) { - if ( preRotation !== undefined ) quaternion.premultiply( preRotation ); - if ( postRotation !== undefined ) quaternion.multiply( postRotation ); + this.interpolateRotations( curves.y ); + curves.y.values = curves.y.values.map( MathUtils.degToRad ); - quaternion.toArray( quaternionValues, ( i / 3 ) * 4 ); + } - } + if ( curves.z !== undefined ) { - return new QuaternionKeyframeTrack( modelName + '.quaternion', times, quaternionValues ); + this.interpolateRotations( curves.z ); + curves.z.values = curves.z.values.map( MathUtils.degToRad ); - }, + } - generateMorphTrack: function ( rawTracks ) { + const times = this.getTimesForAllAxes( curves ); + const values = this.getKeyframeTrackValues( times, curves, initialValue ); - var curves = rawTracks.DeformPercent.curves.morph; - var values = curves.values.map( function ( val ) { + if ( preRotation !== undefined ) { - return val / 100; + preRotation = preRotation.map( MathUtils.degToRad ); + preRotation.push( eulerOrder ); - } ); + preRotation = new Euler().fromArray( preRotation ); + preRotation = new Quaternion().setFromEuler( preRotation ); - var morphNum = sceneGraph.getObjectByName( rawTracks.modelName ).morphTargetDictionary[ rawTracks.morphName ]; + } - return new NumberKeyframeTrack( rawTracks.modelName + '.morphTargetInfluences[' + morphNum + ']', curves.times, values ); + if ( postRotation !== undefined ) { - }, + postRotation = postRotation.map( MathUtils.degToRad ); + postRotation.push( eulerOrder ); - // For all animated objects, times are defined separately for each axis - // Here we'll combine the times into one sorted array without duplicates - getTimesForAllAxes: function ( curves ) { + postRotation = new Euler().fromArray( postRotation ); + postRotation = new Quaternion().setFromEuler( postRotation ).invert(); - var times = []; + } - // first join together the times for each axis, if defined - if ( curves.x !== undefined ) times = times.concat( curves.x.times ); - if ( curves.y !== undefined ) times = times.concat( curves.y.times ); - if ( curves.z !== undefined ) times = times.concat( curves.z.times ); + const quaternion = new Quaternion(); + const euler = new Euler(); - // then sort them - times = times.sort( function ( a, b ) { + const quaternionValues = []; - return a - b; + for ( let i = 0; i < values.length; i += 3 ) { - } ); + euler.set( values[ i ], values[ i + 1 ], values[ i + 2 ], eulerOrder ); - // and remove duplicates - if ( times.length > 1 ) { + quaternion.setFromEuler( euler ); - var targetIndex = 1; - var lastValue = times[ 0 ]; - for ( var i = 1; i < times.length; i ++ ) { + if ( preRotation !== undefined ) quaternion.premultiply( preRotation ); + if ( postRotation !== undefined ) quaternion.multiply( postRotation ); - var currentValue = times[ i ]; - if ( currentValue !== lastValue ) { + quaternion.toArray( quaternionValues, ( i / 3 ) * 4 ); - times[ targetIndex ] = currentValue; - lastValue = currentValue; - targetIndex ++; + } - } + return new QuaternionKeyframeTrack( modelName + '.quaternion', times, quaternionValues ); - } + } - times = times.slice( 0, targetIndex ); + generateMorphTrack( rawTracks ) { - } + const curves = rawTracks.DeformPercent.curves.morph; + const values = curves.values.map( function ( val ) { - return times; + return val / 100; - }, + } ); - getKeyframeTrackValues: function ( times, curves, initialValue ) { + const morphNum = sceneGraph.getObjectByName( rawTracks.modelName ).morphTargetDictionary[ rawTracks.morphName ]; - var prevValue = initialValue; + return new NumberKeyframeTrack( rawTracks.modelName + '.morphTargetInfluences[' + morphNum + ']', curves.times, values ); - var values = []; + } - var xIndex = - 1; - var yIndex = - 1; - var zIndex = - 1; + // For all animated objects, times are defined separately for each axis + // Here we'll combine the times into one sorted array without duplicates + getTimesForAllAxes( curves ) { - times.forEach( function ( time ) { + let times = []; - if ( curves.x ) xIndex = curves.x.times.indexOf( time ); - if ( curves.y ) yIndex = curves.y.times.indexOf( time ); - if ( curves.z ) zIndex = curves.z.times.indexOf( time ); + // first join together the times for each axis, if defined + if ( curves.x !== undefined ) times = times.concat( curves.x.times ); + if ( curves.y !== undefined ) times = times.concat( curves.y.times ); + if ( curves.z !== undefined ) times = times.concat( curves.z.times ); - // if there is an x value defined for this frame, use that - if ( xIndex !== - 1 ) { + // then sort them + times = times.sort( function ( a, b ) { - var xValue = curves.x.values[ xIndex ]; - values.push( xValue ); - prevValue[ 0 ] = xValue; + return a - b; - } else { + } ); - // otherwise use the x value from the previous frame - values.push( prevValue[ 0 ] ); + // and remove duplicates + if ( times.length > 1 ) { - } + let targetIndex = 1; + let lastValue = times[ 0 ]; + for ( let i = 1; i < times.length; i ++ ) { - if ( yIndex !== - 1 ) { + const currentValue = times[ i ]; + if ( currentValue !== lastValue ) { - var yValue = curves.y.values[ yIndex ]; - values.push( yValue ); - prevValue[ 1 ] = yValue; + times[ targetIndex ] = currentValue; + lastValue = currentValue; + targetIndex ++; - } else { + } - values.push( prevValue[ 1 ] ); + } - } + times = times.slice( 0, targetIndex ); - if ( zIndex !== - 1 ) { + } - var zValue = curves.z.values[ zIndex ]; - values.push( zValue ); - prevValue[ 2 ] = zValue; + return times; - } else { + } - values.push( prevValue[ 2 ] ); + getKeyframeTrackValues( times, curves, initialValue ) { - } + const prevValue = initialValue; - } ); + const values = []; - return values; + let xIndex = - 1; + let yIndex = - 1; + let zIndex = - 1; - }, + times.forEach( function ( time ) { - // Rotations are defined as Euler angles which can have values of any size - // These will be converted to quaternions which don't support values greater than - // PI, so we'll interpolate large rotations - interpolateRotations: function ( curve ) { + if ( curves.x ) xIndex = curves.x.times.indexOf( time ); + if ( curves.y ) yIndex = curves.y.times.indexOf( time ); + if ( curves.z ) zIndex = curves.z.times.indexOf( time ); - for ( var i = 1; i < curve.values.length; i ++ ) { + // if there is an x value defined for this frame, use that + if ( xIndex !== - 1 ) { - var initialValue = curve.values[ i - 1 ]; - var valuesSpan = curve.values[ i ] - initialValue; + const xValue = curves.x.values[ xIndex ]; + values.push( xValue ); + prevValue[ 0 ] = xValue; - var absoluteSpan = Math.abs( valuesSpan ); + } else { - if ( absoluteSpan >= 180 ) { + // otherwise use the x value from the previous frame + values.push( prevValue[ 0 ] ); - var numSubIntervals = absoluteSpan / 180; + } - var step = valuesSpan / numSubIntervals; - var nextValue = initialValue + step; + if ( yIndex !== - 1 ) { - var initialTime = curve.times[ i - 1 ]; - var timeSpan = curve.times[ i ] - initialTime; - var interval = timeSpan / numSubIntervals; - var nextTime = initialTime + interval; + const yValue = curves.y.values[ yIndex ]; + values.push( yValue ); + prevValue[ 1 ] = yValue; - var interpolatedTimes = []; - var interpolatedValues = []; + } else { - while ( nextTime < curve.times[ i ] ) { + values.push( prevValue[ 1 ] ); - interpolatedTimes.push( nextTime ); - nextTime += interval; + } - interpolatedValues.push( nextValue ); - nextValue += step; + if ( zIndex !== - 1 ) { - } + const zValue = curves.z.values[ zIndex ]; + values.push( zValue ); + prevValue[ 2 ] = zValue; - curve.times = inject( curve.times, i, interpolatedTimes ); - curve.values = inject( curve.values, i, interpolatedValues ); + } else { - } + values.push( prevValue[ 2 ] ); } - }, + } ); - }; + return values; - // parse an FBX file in ASCII format - function TextParser() {} + } - TextParser.prototype = { + // Rotations are defined as Euler angles which can have values of any size + // These will be converted to quaternions which don't support values greater than + // PI, so we'll interpolate large rotations + interpolateRotations( curve ) { - constructor: TextParser, + for ( let i = 1; i < curve.values.length; i ++ ) { - getPrevNode: function () { + const initialValue = curve.values[ i - 1 ]; + const valuesSpan = curve.values[ i ] - initialValue; - return this.nodeStack[ this.currentIndent - 2 ]; + const absoluteSpan = Math.abs( valuesSpan ); - }, + if ( absoluteSpan >= 180 ) { - getCurrentNode: function () { + const numSubIntervals = absoluteSpan / 180; - return this.nodeStack[ this.currentIndent - 1 ]; + const step = valuesSpan / numSubIntervals; + let nextValue = initialValue + step; - }, + const initialTime = curve.times[ i - 1 ]; + const timeSpan = curve.times[ i ] - initialTime; + const interval = timeSpan / numSubIntervals; + let nextTime = initialTime + interval; - getCurrentProp: function () { + const interpolatedTimes = []; + const interpolatedValues = []; - return this.currentProp; + while ( nextTime < curve.times[ i ] ) { - }, + interpolatedTimes.push( nextTime ); + nextTime += interval; - pushStack: function ( node ) { + interpolatedValues.push( nextValue ); + nextValue += step; - this.nodeStack.push( node ); - this.currentIndent += 1; + } - }, + curve.times = inject( curve.times, i, interpolatedTimes ); + curve.values = inject( curve.values, i, interpolatedValues ); - popStack: function () { + } - this.nodeStack.pop(); - this.currentIndent -= 1; + } - }, + } - setCurrentProp: function ( val, name ) { +} - this.currentProp = val; - this.currentPropName = name; +// parse an FBX file in ASCII format +class TextParser { - }, + getPrevNode() { - parse: function ( text ) { + return this.nodeStack[ this.currentIndent - 2 ]; - this.currentIndent = 0; + } - this.allNodes = new FBXTree(); - this.nodeStack = []; - this.currentProp = []; - this.currentPropName = ''; + getCurrentNode() { - var scope = this; + return this.nodeStack[ this.currentIndent - 1 ]; - var split = text.split( /[\r\n]+/ ); + } - split.forEach( function ( line, i ) { + getCurrentProp() { - var matchComment = line.match( /^[\s\t]*;/ ); - var matchEmpty = line.match( /^[\s\t]*$/ ); + return this.currentProp; - if ( matchComment || matchEmpty ) return; + } - var matchBeginning = line.match( '^\\t{' + scope.currentIndent + '}(\\w+):(.*){', '' ); - var matchProperty = line.match( '^\\t{' + ( scope.currentIndent ) + '}(\\w+):[\\s\\t\\r\\n](.*)' ); - var matchEnd = line.match( '^\\t{' + ( scope.currentIndent - 1 ) + '}}' ); + pushStack( node ) { - if ( matchBeginning ) { + this.nodeStack.push( node ); + this.currentIndent += 1; - scope.parseNodeBegin( line, matchBeginning ); + } - } else if ( matchProperty ) { + popStack() { - scope.parseNodeProperty( line, matchProperty, split[ ++ i ] ); + this.nodeStack.pop(); + this.currentIndent -= 1; - } else if ( matchEnd ) { + } - scope.popStack(); + setCurrentProp( val, name ) { - } else if ( line.match( /^[^\s\t}]/ ) ) { + this.currentProp = val; + this.currentPropName = name; - // large arrays are split over multiple lines terminated with a ',' character - // if this is encountered the line needs to be joined to the previous line - scope.parseNodePropertyContinued( line ); + } - } + parse( text ) { - } ); + this.currentIndent = 0; - return this.allNodes; + this.allNodes = new FBXTree(); + this.nodeStack = []; + this.currentProp = []; + this.currentPropName = ''; - }, + const scope = this; - parseNodeBegin: function ( line, property ) { + const split = text.split( /[\r\n]+/ ); - var nodeName = property[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' ); + split.forEach( function ( line, i ) { - var nodeAttrs = property[ 2 ].split( ',' ).map( function ( attr ) { + const matchComment = line.match( /^[\s\t]*;/ ); + const matchEmpty = line.match( /^[\s\t]*$/ ); - return attr.trim().replace( /^"/, '' ).replace( /"$/, '' ); + if ( matchComment || matchEmpty ) return; - } ); + const matchBeginning = line.match( '^\\t{' + scope.currentIndent + '}(\\w+):(.*){', '' ); + const matchProperty = line.match( '^\\t{' + ( scope.currentIndent ) + '}(\\w+):[\\s\\t\\r\\n](.*)' ); + const matchEnd = line.match( '^\\t{' + ( scope.currentIndent - 1 ) + '}}' ); - var node = { name: nodeName }; - var attrs = this.parseNodeAttr( nodeAttrs ); + if ( matchBeginning ) { - var currentNode = this.getCurrentNode(); + scope.parseNodeBegin( line, matchBeginning ); - // a top node - if ( this.currentIndent === 0 ) { + } else if ( matchProperty ) { - this.allNodes.add( nodeName, node ); + scope.parseNodeProperty( line, matchProperty, split[ ++ i ] ); - } else { // a subnode + } else if ( matchEnd ) { - // if the subnode already exists, append it - if ( nodeName in currentNode ) { + scope.popStack(); - // special case Pose needs PoseNodes as an array - if ( nodeName === 'PoseNode' ) { + } else if ( line.match( /^[^\s\t}]/ ) ) { - currentNode.PoseNode.push( node ); + // large arrays are split over multiple lines terminated with a ',' character + // if this is encountered the line needs to be joined to the previous line + scope.parseNodePropertyContinued( line ); - } else if ( currentNode[ nodeName ].id !== undefined ) { + } - currentNode[ nodeName ] = {}; - currentNode[ nodeName ][ currentNode[ nodeName ].id ] = currentNode[ nodeName ]; + } ); - } + return this.allNodes; - if ( attrs.id !== '' ) currentNode[ nodeName ][ attrs.id ] = node; + } - } else if ( typeof attrs.id === 'number' ) { + parseNodeBegin( line, property ) { - currentNode[ nodeName ] = {}; - currentNode[ nodeName ][ attrs.id ] = node; + const nodeName = property[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' ); - } else if ( nodeName !== 'Properties70' ) { + const nodeAttrs = property[ 2 ].split( ',' ).map( function ( attr ) { - if ( nodeName === 'PoseNode' ) currentNode[ nodeName ] = [ node ]; - else currentNode[ nodeName ] = node; + return attr.trim().replace( /^"/, '' ).replace( /"$/, '' ); - } + } ); - } + const node = { name: nodeName }; + const attrs = this.parseNodeAttr( nodeAttrs ); - if ( typeof attrs.id === 'number' ) node.id = attrs.id; - if ( attrs.name !== '' ) node.attrName = attrs.name; - if ( attrs.type !== '' ) node.attrType = attrs.type; + const currentNode = this.getCurrentNode(); - this.pushStack( node ); + // a top node + if ( this.currentIndent === 0 ) { - }, + this.allNodes.add( nodeName, node ); - parseNodeAttr: function ( attrs ) { + } else { // a subnode - var id = attrs[ 0 ]; + // if the subnode already exists, append it + if ( nodeName in currentNode ) { - if ( attrs[ 0 ] !== '' ) { + // special case Pose needs PoseNodes as an array + if ( nodeName === 'PoseNode' ) { - id = parseInt( attrs[ 0 ] ); + currentNode.PoseNode.push( node ); - if ( isNaN( id ) ) { + } else if ( currentNode[ nodeName ].id !== undefined ) { - id = attrs[ 0 ]; + currentNode[ nodeName ] = {}; + currentNode[ nodeName ][ currentNode[ nodeName ].id ] = currentNode[ nodeName ]; } - } + if ( attrs.id !== '' ) currentNode[ nodeName ][ attrs.id ] = node; - var name = '', type = ''; + } else if ( typeof attrs.id === 'number' ) { - if ( attrs.length > 1 ) { + currentNode[ nodeName ] = {}; + currentNode[ nodeName ][ attrs.id ] = node; - name = attrs[ 1 ].replace( /^(\w+)::/, '' ); - type = attrs[ 2 ]; + } else if ( nodeName !== 'Properties70' ) { + + if ( nodeName === 'PoseNode' ) currentNode[ nodeName ] = [ node ]; + else currentNode[ nodeName ] = node; } - return { id: id, name: name, type: type }; + } - }, + if ( typeof attrs.id === 'number' ) node.id = attrs.id; + if ( attrs.name !== '' ) node.attrName = attrs.name; + if ( attrs.type !== '' ) node.attrType = attrs.type; - parseNodeProperty: function ( line, property, contentLine ) { + this.pushStack( node ); - var propName = property[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim(); - var propValue = property[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim(); + } - // for special case: base64 image data follows "Content: ," line - // Content: , - // "/9j/4RDaRXhpZgAATU0A..." - if ( propName === 'Content' && propValue === ',' ) { + parseNodeAttr( attrs ) { - propValue = contentLine.replace( /"/g, '' ).replace( /,$/, '' ).trim(); + let id = attrs[ 0 ]; - } + if ( attrs[ 0 ] !== '' ) { - var currentNode = this.getCurrentNode(); - var parentName = currentNode.name; + id = parseInt( attrs[ 0 ] ); - if ( parentName === 'Properties70' ) { + if ( isNaN( id ) ) { - this.parseNodeSpecialProperty( line, propName, propValue ); - return; + id = attrs[ 0 ]; } - // Connections - if ( propName === 'C' ) { + } - var connProps = propValue.split( ',' ).slice( 1 ); - var from = parseInt( connProps[ 0 ] ); - var to = parseInt( connProps[ 1 ] ); + let name = '', type = ''; - var rest = propValue.split( ',' ).slice( 3 ); + if ( attrs.length > 1 ) { - rest = rest.map( function ( elem ) { + name = attrs[ 1 ].replace( /^(\w+)::/, '' ); + type = attrs[ 2 ]; - return elem.trim().replace( /^"/, '' ); + } - } ); + return { id: id, name: name, type: type }; - propName = 'connections'; - propValue = [ from, to ]; - append( propValue, rest ); + } - if ( currentNode[ propName ] === undefined ) { + parseNodeProperty( line, property, contentLine ) { - currentNode[ propName ] = []; + let propName = property[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim(); + let propValue = property[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim(); - } + // for special case: base64 image data follows "Content: ," line + // Content: , + // "/9j/4RDaRXhpZgAATU0A..." + if ( propName === 'Content' && propValue === ',' ) { - } + propValue = contentLine.replace( /"/g, '' ).replace( /,$/, '' ).trim(); - // Node - if ( propName === 'Node' ) currentNode.id = propValue; + } - // connections - if ( propName in currentNode && Array.isArray( currentNode[ propName ] ) ) { + const currentNode = this.getCurrentNode(); + const parentName = currentNode.name; - currentNode[ propName ].push( propValue ); + if ( parentName === 'Properties70' ) { - } else { + this.parseNodeSpecialProperty( line, propName, propValue ); + return; - if ( propName !== 'a' ) currentNode[ propName ] = propValue; - else currentNode.a = propValue; + } - } + // Connections + if ( propName === 'C' ) { - this.setCurrentProp( currentNode, propName ); + const connProps = propValue.split( ',' ).slice( 1 ); + const from = parseInt( connProps[ 0 ] ); + const to = parseInt( connProps[ 1 ] ); - // convert string to array, unless it ends in ',' in which case more will be added to it - if ( propName === 'a' && propValue.slice( - 1 ) !== ',' ) { + let rest = propValue.split( ',' ).slice( 3 ); - currentNode.a = parseNumberArray( propValue ); + rest = rest.map( function ( elem ) { - } + return elem.trim().replace( /^"/, '' ); - }, + } ); - parseNodePropertyContinued: function ( line ) { + propName = 'connections'; + propValue = [ from, to ]; + append( propValue, rest ); - var currentNode = this.getCurrentNode(); + if ( currentNode[ propName ] === undefined ) { - currentNode.a += line; + currentNode[ propName ] = []; - // if the line doesn't end in ',' we have reached the end of the property value - // so convert the string to an array - if ( line.slice( - 1 ) !== ',' ) { + } - currentNode.a = parseNumberArray( currentNode.a ); + } - } + // Node + if ( propName === 'Node' ) currentNode.id = propValue; - }, + // connections + if ( propName in currentNode && Array.isArray( currentNode[ propName ] ) ) { - // parse "Property70" - parseNodeSpecialProperty: function ( line, propName, propValue ) { + currentNode[ propName ].push( propValue ); - // split this - // P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1 - // into array like below - // ["Lcl Scaling", "Lcl Scaling", "", "A", "1,1,1" ] - var props = propValue.split( '",' ).map( function ( prop ) { + } else { - return prop.trim().replace( /^\"/, '' ).replace( /\s/, '_' ); + if ( propName !== 'a' ) currentNode[ propName ] = propValue; + else currentNode.a = propValue; - } ); + } - var innerPropName = props[ 0 ]; - var innerPropType1 = props[ 1 ]; - var innerPropType2 = props[ 2 ]; - var innerPropFlag = props[ 3 ]; - var innerPropValue = props[ 4 ]; - - // cast values where needed, otherwise leave as strings - switch ( innerPropType1 ) { - - case 'int': - case 'enum': - case 'bool': - case 'ULongLong': - case 'double': - case 'Number': - case 'FieldOfView': - innerPropValue = parseFloat( innerPropValue ); - break; + this.setCurrentProp( currentNode, propName ); - case 'Color': - case 'ColorRGB': - case 'Vector3D': - case 'Lcl_Translation': - case 'Lcl_Rotation': - case 'Lcl_Scaling': - innerPropValue = parseNumberArray( innerPropValue ); - break; + // convert string to array, unless it ends in ',' in which case more will be added to it + if ( propName === 'a' && propValue.slice( - 1 ) !== ',' ) { - } + currentNode.a = parseNumberArray( propValue ); - // CAUTION: these props must append to parent's parent - this.getPrevNode()[ innerPropName ] = { + } - 'type': innerPropType1, - 'type2': innerPropType2, - 'flag': innerPropFlag, - 'value': innerPropValue + } - }; + parseNodePropertyContinued( line ) { - this.setCurrentProp( this.getPrevNode(), innerPropName ); + const currentNode = this.getCurrentNode(); - }, + currentNode.a += line; - }; + // if the line doesn't end in ',' we have reached the end of the property value + // so convert the string to an array + if ( line.slice( - 1 ) !== ',' ) { - // Parse an FBX file in Binary format - function BinaryParser() {} + currentNode.a = parseNumberArray( currentNode.a ); - BinaryParser.prototype = { + } - constructor: BinaryParser, + } - parse: function ( buffer ) { + // parse "Property70" + parseNodeSpecialProperty( line, propName, propValue ) { - var reader = new BinaryReader( buffer ); - reader.skip( 23 ); // skip magic 23 bytes + // split this + // P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1 + // into array like below + // ["Lcl Scaling", "Lcl Scaling", "", "A", "1,1,1" ] + const props = propValue.split( '",' ).map( function ( prop ) { - var version = reader.getUint32(); + return prop.trim().replace( /^\"/, '' ).replace( /\s/, '_' ); - if ( version < 6400 ) { + } ); - throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + version ); + const innerPropName = props[ 0 ]; + const innerPropType1 = props[ 1 ]; + const innerPropType2 = props[ 2 ]; + const innerPropFlag = props[ 3 ]; + let innerPropValue = props[ 4 ]; + + // cast values where needed, otherwise leave as strings + switch ( innerPropType1 ) { + + case 'int': + case 'enum': + case 'bool': + case 'ULongLong': + case 'double': + case 'Number': + case 'FieldOfView': + innerPropValue = parseFloat( innerPropValue ); + break; - } + case 'Color': + case 'ColorRGB': + case 'Vector3D': + case 'Lcl_Translation': + case 'Lcl_Rotation': + case 'Lcl_Scaling': + innerPropValue = parseNumberArray( innerPropValue ); + break; - var allNodes = new FBXTree(); + } - while ( ! this.endOfContent( reader ) ) { + // CAUTION: these props must append to parent's parent + this.getPrevNode()[ innerPropName ] = { - var node = this.parseNode( reader, version ); - if ( node !== null ) allNodes.add( node.name, node ); + 'type': innerPropType1, + 'type2': innerPropType2, + 'flag': innerPropFlag, + 'value': innerPropValue - } + }; - return allNodes; + this.setCurrentProp( this.getPrevNode(), innerPropName ); - }, + } - // Check if reader has reached the end of content. - endOfContent: function ( reader ) { +} - // footer size: 160bytes + 16-byte alignment padding - // - 16bytes: magic - // - padding til 16-byte alignment (at least 1byte?) - // (seems like some exporters embed fixed 15 or 16bytes?) - // - 4bytes: magic - // - 4bytes: version - // - 120bytes: zero - // - 16bytes: magic - if ( reader.size() % 16 === 0 ) { +// Parse an FBX file in Binary format +class BinaryParser { - return ( ( reader.getOffset() + 160 + 16 ) & ~ 0xf ) >= reader.size(); + parse( buffer ) { - } else { + const reader = new BinaryReader( buffer ); + reader.skip( 23 ); // skip magic 23 bytes - return reader.getOffset() + 160 + 16 >= reader.size(); + const version = reader.getUint32(); - } + if ( version < 6400 ) { - }, + throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + version ); - // recursively parse nodes until the end of the file is reached - parseNode: function ( reader, version ) { + } - var node = {}; + const allNodes = new FBXTree(); - // The first three data sizes depends on version. - var endOffset = ( version >= 7500 ) ? reader.getUint64() : reader.getUint32(); - var numProperties = ( version >= 7500 ) ? reader.getUint64() : reader.getUint32(); + while ( ! this.endOfContent( reader ) ) { - ( version >= 7500 ) ? reader.getUint64() : reader.getUint32(); // the returned propertyListLen is not used + const node = this.parseNode( reader, version ); + if ( node !== null ) allNodes.add( node.name, node ); - var nameLen = reader.getUint8(); - var name = reader.getString( nameLen ); + } - // Regards this node as NULL-record if endOffset is zero - if ( endOffset === 0 ) return null; + return allNodes; - var propertyList = []; + } - for ( var i = 0; i < numProperties; i ++ ) { + // Check if reader has reached the end of content. + endOfContent( reader ) { - propertyList.push( this.parseProperty( reader ) ); + // footer size: 160bytes + 16-byte alignment padding + // - 16bytes: magic + // - padding til 16-byte alignment (at least 1byte?) + // (seems like some exporters embed fixed 15 or 16bytes?) + // - 4bytes: magic + // - 4bytes: version + // - 120bytes: zero + // - 16bytes: magic + if ( reader.size() % 16 === 0 ) { - } + return ( ( reader.getOffset() + 160 + 16 ) & ~ 0xf ) >= reader.size(); - // Regards the first three elements in propertyList as id, attrName, and attrType - var id = propertyList.length > 0 ? propertyList[ 0 ] : ''; - var attrName = propertyList.length > 1 ? propertyList[ 1 ] : ''; - var attrType = propertyList.length > 2 ? propertyList[ 2 ] : ''; + } else { - // check if this node represents just a single property - // like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]} - node.singleProperty = ( numProperties === 1 && reader.getOffset() === endOffset ) ? true : false; + return reader.getOffset() + 160 + 16 >= reader.size(); - while ( endOffset > reader.getOffset() ) { + } - var subNode = this.parseNode( reader, version ); + } - if ( subNode !== null ) this.parseSubNode( name, node, subNode ); + // recursively parse nodes until the end of the file is reached + parseNode( reader, version ) { - } + const node = {}; - node.propertyList = propertyList; // raw property list used by parent + // The first three data sizes depends on version. + const endOffset = ( version >= 7500 ) ? reader.getUint64() : reader.getUint32(); + const numProperties = ( version >= 7500 ) ? reader.getUint64() : reader.getUint32(); - if ( typeof id === 'number' ) node.id = id; - if ( attrName !== '' ) node.attrName = attrName; - if ( attrType !== '' ) node.attrType = attrType; - if ( name !== '' ) node.name = name; + ( version >= 7500 ) ? reader.getUint64() : reader.getUint32(); // the returned propertyListLen is not used - return node; + const nameLen = reader.getUint8(); + const name = reader.getString( nameLen ); - }, + // Regards this node as NULL-record if endOffset is zero + if ( endOffset === 0 ) return null; - parseSubNode: function ( name, node, subNode ) { + const propertyList = []; - // special case: child node is single property - if ( subNode.singleProperty === true ) { + for ( let i = 0; i < numProperties; i ++ ) { - var value = subNode.propertyList[ 0 ]; + propertyList.push( this.parseProperty( reader ) ); - if ( Array.isArray( value ) ) { + } - node[ subNode.name ] = subNode; + // Regards the first three elements in propertyList as id, attrName, and attrType + const id = propertyList.length > 0 ? propertyList[ 0 ] : ''; + const attrName = propertyList.length > 1 ? propertyList[ 1 ] : ''; + const attrType = propertyList.length > 2 ? propertyList[ 2 ] : ''; - subNode.a = value; + // check if this node represents just a single property + // like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]} + node.singleProperty = ( numProperties === 1 && reader.getOffset() === endOffset ) ? true : false; - } else { + while ( endOffset > reader.getOffset() ) { - node[ subNode.name ] = value; + const subNode = this.parseNode( reader, version ); - } + if ( subNode !== null ) this.parseSubNode( name, node, subNode ); - } else if ( name === 'Connections' && subNode.name === 'C' ) { + } - var array = []; + node.propertyList = propertyList; // raw property list used by parent - subNode.propertyList.forEach( function ( property, i ) { + if ( typeof id === 'number' ) node.id = id; + if ( attrName !== '' ) node.attrName = attrName; + if ( attrType !== '' ) node.attrType = attrType; + if ( name !== '' ) node.name = name; - // first Connection is FBX type (OO, OP, etc.). We'll discard these - if ( i !== 0 ) array.push( property ); + return node; - } ); + } - if ( node.connections === undefined ) { + parseSubNode( name, node, subNode ) { - node.connections = []; + // special case: child node is single property + if ( subNode.singleProperty === true ) { - } + const value = subNode.propertyList[ 0 ]; - node.connections.push( array ); + if ( Array.isArray( value ) ) { - } else if ( subNode.name === 'Properties70' ) { + node[ subNode.name ] = subNode; - var keys = Object.keys( subNode ); + subNode.a = value; - keys.forEach( function ( key ) { + } else { - node[ key ] = subNode[ key ]; + node[ subNode.name ] = value; - } ); + } - } else if ( name === 'Properties70' && subNode.name === 'P' ) { + } else if ( name === 'Connections' && subNode.name === 'C' ) { - var innerPropName = subNode.propertyList[ 0 ]; - var innerPropType1 = subNode.propertyList[ 1 ]; - var innerPropType2 = subNode.propertyList[ 2 ]; - var innerPropFlag = subNode.propertyList[ 3 ]; - var innerPropValue; + const array = []; - if ( innerPropName.indexOf( 'Lcl ' ) === 0 ) innerPropName = innerPropName.replace( 'Lcl ', 'Lcl_' ); - if ( innerPropType1.indexOf( 'Lcl ' ) === 0 ) innerPropType1 = innerPropType1.replace( 'Lcl ', 'Lcl_' ); + subNode.propertyList.forEach( function ( property, i ) { - if ( innerPropType1 === 'Color' || innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) { + // first Connection is FBX type (OO, OP, etc.). We'll discard these + if ( i !== 0 ) array.push( property ); - innerPropValue = [ - subNode.propertyList[ 4 ], - subNode.propertyList[ 5 ], - subNode.propertyList[ 6 ] - ]; + } ); - } else { + if ( node.connections === undefined ) { - innerPropValue = subNode.propertyList[ 4 ]; + node.connections = []; - } + } - // this will be copied to parent, see above - node[ innerPropName ] = { + node.connections.push( array ); - 'type': innerPropType1, - 'type2': innerPropType2, - 'flag': innerPropFlag, - 'value': innerPropValue + } else if ( subNode.name === 'Properties70' ) { - }; + const keys = Object.keys( subNode ); - } else if ( node[ subNode.name ] === undefined ) { + keys.forEach( function ( key ) { - if ( typeof subNode.id === 'number' ) { + node[ key ] = subNode[ key ]; - node[ subNode.name ] = {}; - node[ subNode.name ][ subNode.id ] = subNode; + } ); - } else { + } else if ( name === 'Properties70' && subNode.name === 'P' ) { - node[ subNode.name ] = subNode; + let innerPropName = subNode.propertyList[ 0 ]; + let innerPropType1 = subNode.propertyList[ 1 ]; + const innerPropType2 = subNode.propertyList[ 2 ]; + const innerPropFlag = subNode.propertyList[ 3 ]; + let innerPropValue; - } + if ( innerPropName.indexOf( 'Lcl ' ) === 0 ) innerPropName = innerPropName.replace( 'Lcl ', 'Lcl_' ); + if ( innerPropType1.indexOf( 'Lcl ' ) === 0 ) innerPropType1 = innerPropType1.replace( 'Lcl ', 'Lcl_' ); + + if ( innerPropType1 === 'Color' || innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) { + + innerPropValue = [ + subNode.propertyList[ 4 ], + subNode.propertyList[ 5 ], + subNode.propertyList[ 6 ] + ]; } else { - if ( subNode.name === 'PoseNode' ) { + innerPropValue = subNode.propertyList[ 4 ]; - if ( ! Array.isArray( node[ subNode.name ] ) ) { + } - node[ subNode.name ] = [ node[ subNode.name ] ]; + // this will be copied to parent, see above + node[ innerPropName ] = { - } + 'type': innerPropType1, + 'type2': innerPropType2, + 'flag': innerPropFlag, + 'value': innerPropValue - node[ subNode.name ].push( subNode ); + }; - } else if ( node[ subNode.name ][ subNode.id ] === undefined ) { + } else if ( node[ subNode.name ] === undefined ) { - node[ subNode.name ][ subNode.id ] = subNode; + if ( typeof subNode.id === 'number' ) { - } + node[ subNode.name ] = {}; + node[ subNode.name ][ subNode.id ] = subNode; - } + } else { - }, + node[ subNode.name ] = subNode; - parseProperty: function ( reader ) { + } - var type = reader.getString( 1 ); + } else { - switch ( type ) { + if ( subNode.name === 'PoseNode' ) { - case 'C': - return reader.getBoolean(); + if ( ! Array.isArray( node[ subNode.name ] ) ) { - case 'D': - return reader.getFloat64(); + node[ subNode.name ] = [ node[ subNode.name ] ]; - case 'F': - return reader.getFloat32(); + } - case 'I': - return reader.getInt32(); + node[ subNode.name ].push( subNode ); - case 'L': - return reader.getInt64(); + } else if ( node[ subNode.name ][ subNode.id ] === undefined ) { - case 'R': - var length = reader.getUint32(); - return reader.getArrayBuffer( length ); + node[ subNode.name ][ subNode.id ] = subNode; - case 'S': - var length = reader.getUint32(); - return reader.getString( length ); + } - case 'Y': - return reader.getInt16(); + } - case 'b': - case 'c': - case 'd': - case 'f': - case 'i': - case 'l': + } - var arrayLength = reader.getUint32(); - var encoding = reader.getUint32(); // 0: non-compressed, 1: compressed - var compressedLength = reader.getUint32(); + parseProperty( reader ) { - if ( encoding === 0 ) { + const type = reader.getString( 1 ); + let length; - switch ( type ) { + switch ( type ) { - case 'b': - case 'c': - return reader.getBooleanArray( arrayLength ); + case 'C': + return reader.getBoolean(); - case 'd': - return reader.getFloat64Array( arrayLength ); + case 'D': + return reader.getFloat64(); - case 'f': - return reader.getFloat32Array( arrayLength ); + case 'F': + return reader.getFloat32(); - case 'i': - return reader.getInt32Array( arrayLength ); + case 'I': + return reader.getInt32(); - case 'l': - return reader.getInt64Array( arrayLength ); + case 'L': + return reader.getInt64(); - } + case 'R': + length = reader.getUint32(); + return reader.getArrayBuffer( length ); - } + case 'S': + length = reader.getUint32(); + return reader.getString( length ); - if ( typeof fflate === 'undefined' ) { + case 'Y': + return reader.getInt16(); - console.error( 'THREE.FBXLoader: External library fflate.min.js required.' ); + case 'b': + case 'c': + case 'd': + case 'f': + case 'i': + case 'l': - } + const arrayLength = reader.getUint32(); + const encoding = reader.getUint32(); // 0: non-compressed, 1: compressed + const compressedLength = reader.getUint32(); - var data = fflate.unzlibSync( new Uint8Array( reader.getArrayBuffer( compressedLength ) ) ); // eslint-disable-line no-undef - var reader2 = new BinaryReader( data.buffer ); + if ( encoding === 0 ) { switch ( type ) { case 'b': case 'c': - return reader2.getBooleanArray( arrayLength ); + return reader.getBooleanArray( arrayLength ); case 'd': - return reader2.getFloat64Array( arrayLength ); + return reader.getFloat64Array( arrayLength ); case 'f': - return reader2.getFloat32Array( arrayLength ); + return reader.getFloat32Array( arrayLength ); case 'i': - return reader2.getInt32Array( arrayLength ); + return reader.getInt32Array( arrayLength ); case 'l': - return reader2.getInt64Array( arrayLength ); + return reader.getInt64Array( arrayLength ); } - default: - throw new Error( 'THREE.FBXLoader: Unknown property type ' + type ); + } - } + if ( typeof fflate === 'undefined' ) { - } + console.error( 'THREE.FBXLoader: External library fflate.min.js required.' ); - }; + } - function BinaryReader( buffer, littleEndian ) { + const data = fflate.unzlibSync( new Uint8Array( reader.getArrayBuffer( compressedLength ) ) ); // eslint-disable-line no-undef + const reader2 = new BinaryReader( data.buffer ); - this.dv = new DataView( buffer ); - this.offset = 0; - this.littleEndian = ( littleEndian !== undefined ) ? littleEndian : true; + switch ( type ) { + + case 'b': + case 'c': + return reader2.getBooleanArray( arrayLength ); + + case 'd': + return reader2.getFloat64Array( arrayLength ); + + case 'f': + return reader2.getFloat32Array( arrayLength ); + + case 'i': + return reader2.getInt32Array( arrayLength ); + + case 'l': + return reader2.getInt64Array( arrayLength ); + + } + + default: + throw new Error( 'THREE.FBXLoader: Unknown property type ' + type ); + + } } - BinaryReader.prototype = { +} - constructor: BinaryReader, +class BinaryReader { - getOffset: function () { + constructor( buffer, littleEndian ) { - return this.offset; + this.dv = new DataView( buffer ); + this.offset = 0; + this.littleEndian = ( littleEndian !== undefined ) ? littleEndian : true; - }, + } - size: function () { + getOffset() { - return this.dv.buffer.byteLength; + return this.offset; - }, + } - skip: function ( length ) { + size() { - this.offset += length; + return this.dv.buffer.byteLength; - }, + } - // seems like true/false representation depends on exporter. - // true: 1 or 'Y'(=0x59), false: 0 or 'T'(=0x54) - // then sees LSB. - getBoolean: function () { + skip( length ) { - return ( this.getUint8() & 1 ) === 1; + this.offset += length; - }, + } - getBooleanArray: function ( size ) { + // seems like true/false representation depends on exporter. + // true: 1 or 'Y'(=0x59), false: 0 or 'T'(=0x54) + // then sees LSB. + getBoolean() { - var a = []; + return ( this.getUint8() & 1 ) === 1; - for ( var i = 0; i < size; i ++ ) { + } - a.push( this.getBoolean() ); + getBooleanArray( size ) { - } + const a = []; - return a; + for ( let i = 0; i < size; i ++ ) { - }, + a.push( this.getBoolean() ); - getUint8: function () { + } - var value = this.dv.getUint8( this.offset ); - this.offset += 1; - return value; + return a; - }, + } - getInt16: function () { + getUint8() { - var value = this.dv.getInt16( this.offset, this.littleEndian ); - this.offset += 2; - return value; + const value = this.dv.getUint8( this.offset ); + this.offset += 1; + return value; - }, + } - getInt32: function () { + getInt16() { - var value = this.dv.getInt32( this.offset, this.littleEndian ); - this.offset += 4; - return value; + const value = this.dv.getInt16( this.offset, this.littleEndian ); + this.offset += 2; + return value; - }, + } - getInt32Array: function ( size ) { + getInt32() { - var a = []; + const value = this.dv.getInt32( this.offset, this.littleEndian ); + this.offset += 4; + return value; - for ( var i = 0; i < size; i ++ ) { + } - a.push( this.getInt32() ); + getInt32Array( size ) { - } + const a = []; - return a; + for ( let i = 0; i < size; i ++ ) { - }, + a.push( this.getInt32() ); - getUint32: function () { + } - var value = this.dv.getUint32( this.offset, this.littleEndian ); - this.offset += 4; - return value; + return a; - }, + } - // JavaScript doesn't support 64-bit integer so calculate this here - // 1 << 32 will return 1 so using multiply operation instead here. - // There's a possibility that this method returns wrong value if the value - // is out of the range between Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER. - // TODO: safely handle 64-bit integer - getInt64: function () { + getUint32() { - var low, high; + const value = this.dv.getUint32( this.offset, this.littleEndian ); + this.offset += 4; + return value; - if ( this.littleEndian ) { + } - low = this.getUint32(); - high = this.getUint32(); + // JavaScript doesn't support 64-bit integer so calculate this here + // 1 << 32 will return 1 so using multiply operation instead here. + // There's a possibility that this method returns wrong value if the value + // is out of the range between Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER. + // TODO: safely handle 64-bit integer + getInt64() { - } else { + let low, high; - high = this.getUint32(); - low = this.getUint32(); + if ( this.littleEndian ) { - } + low = this.getUint32(); + high = this.getUint32(); - // calculate negative value - if ( high & 0x80000000 ) { + } else { - high = ~ high & 0xFFFFFFFF; - low = ~ low & 0xFFFFFFFF; + high = this.getUint32(); + low = this.getUint32(); - if ( low === 0xFFFFFFFF ) high = ( high + 1 ) & 0xFFFFFFFF; + } - low = ( low + 1 ) & 0xFFFFFFFF; + // calculate negative value + if ( high & 0x80000000 ) { - return - ( high * 0x100000000 + low ); + high = ~ high & 0xFFFFFFFF; + low = ~ low & 0xFFFFFFFF; - } + if ( low === 0xFFFFFFFF ) high = ( high + 1 ) & 0xFFFFFFFF; - return high * 0x100000000 + low; + low = ( low + 1 ) & 0xFFFFFFFF; - }, + return - ( high * 0x100000000 + low ); - getInt64Array: function ( size ) { + } - var a = []; + return high * 0x100000000 + low; - for ( var i = 0; i < size; i ++ ) { + } - a.push( this.getInt64() ); + getInt64Array( size ) { - } + const a = []; - return a; + for ( let i = 0; i < size; i ++ ) { - }, + a.push( this.getInt64() ); - // Note: see getInt64() comment - getUint64: function () { + } - var low, high; + return a; - if ( this.littleEndian ) { + } - low = this.getUint32(); - high = this.getUint32(); + // Note: see getInt64() comment + getUint64() { - } else { + let low, high; - high = this.getUint32(); - low = this.getUint32(); + if ( this.littleEndian ) { - } + low = this.getUint32(); + high = this.getUint32(); - return high * 0x100000000 + low; + } else { - }, + high = this.getUint32(); + low = this.getUint32(); - getFloat32: function () { + } - var value = this.dv.getFloat32( this.offset, this.littleEndian ); - this.offset += 4; - return value; + return high * 0x100000000 + low; - }, + } - getFloat32Array: function ( size ) { + getFloat32() { - var a = []; + const value = this.dv.getFloat32( this.offset, this.littleEndian ); + this.offset += 4; + return value; - for ( var i = 0; i < size; i ++ ) { + } - a.push( this.getFloat32() ); + getFloat32Array( size ) { - } + const a = []; - return a; + for ( let i = 0; i < size; i ++ ) { - }, + a.push( this.getFloat32() ); - getFloat64: function () { + } - var value = this.dv.getFloat64( this.offset, this.littleEndian ); - this.offset += 8; - return value; + return a; - }, + } - getFloat64Array: function ( size ) { + getFloat64() { - var a = []; + const value = this.dv.getFloat64( this.offset, this.littleEndian ); + this.offset += 8; + return value; - for ( var i = 0; i < size; i ++ ) { + } - a.push( this.getFloat64() ); + getFloat64Array( size ) { - } + const a = []; - return a; + for ( let i = 0; i < size; i ++ ) { - }, + a.push( this.getFloat64() ); - getArrayBuffer: function ( size ) { + } - var value = this.dv.buffer.slice( this.offset, this.offset + size ); - this.offset += size; - return value; + return a; - }, + } - getString: function ( size ) { + getArrayBuffer( size ) { - // note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead - var a = []; + const value = this.dv.buffer.slice( this.offset, this.offset + size ); + this.offset += size; + return value; - for ( var i = 0; i < size; i ++ ) { + } - a[ i ] = this.getUint8(); + getString( size ) { - } + // note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead + let a = []; - var nullByte = a.indexOf( 0 ); - if ( nullByte >= 0 ) a = a.slice( 0, nullByte ); + for ( let i = 0; i < size; i ++ ) { - return LoaderUtils.decodeText( new Uint8Array( a ) ); + a[ i ] = this.getUint8(); } - }; + const nullByte = a.indexOf( 0 ); + if ( nullByte >= 0 ) a = a.slice( 0, nullByte ); - // FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format) - // and BinaryParser( FBX Binary format) - function FBXTree() {} + return LoaderUtils.decodeText( new Uint8Array( a ) ); - FBXTree.prototype = { + } - constructor: FBXTree, +} - add: function ( key, val ) { +// FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format) +// and BinaryParser( FBX Binary format) +class FBXTree { - this[ key ] = val; + add( key, val ) { - }, + this[ key ] = val; - }; + } - // ************** UTILITY FUNCTIONS ************** +} - function isFbxFormatBinary( buffer ) { +// ************** UTILITY FUNCTIONS ************** - var CORRECT = 'Kaydara FBX Binary \0'; +function isFbxFormatBinary( buffer ) { - return buffer.byteLength >= CORRECT.length && CORRECT === convertArrayBufferToString( buffer, 0, CORRECT.length ); + const CORRECT = 'Kaydara\u0020FBX\u0020Binary\u0020\u0020\0'; - } + return buffer.byteLength >= CORRECT.length && CORRECT === convertArrayBufferToString( buffer, 0, CORRECT.length ); - function isFbxFormatASCII( text ) { +} - var CORRECT = [ 'K', 'a', 'y', 'd', 'a', 'r', 'a', '\\', 'F', 'B', 'X', '\\', 'B', 'i', 'n', 'a', 'r', 'y', '\\', '\\' ]; +function isFbxFormatASCII( text ) { - var cursor = 0; + const CORRECT = [ 'K', 'a', 'y', 'd', 'a', 'r', 'a', '\\', 'F', 'B', 'X', '\\', 'B', 'i', 'n', 'a', 'r', 'y', '\\', '\\' ]; - function read( offset ) { + let cursor = 0; - var result = text[ offset - 1 ]; - text = text.slice( cursor + offset ); - cursor ++; - return result; + function read( offset ) { - } + const result = text[ offset - 1 ]; + text = text.slice( cursor + offset ); + cursor ++; + return result; - for ( var i = 0; i < CORRECT.length; ++ i ) { + } - var num = read( 1 ); - if ( num === CORRECT[ i ] ) { + for ( let i = 0; i < CORRECT.length; ++ i ) { - return false; + const num = read( 1 ); + if ( num === CORRECT[ i ] ) { - } + return false; } - return true; - } - function getFbxVersion( text ) { + return true; - var versionRegExp = /FBXVersion: (\d+)/; - var match = text.match( versionRegExp ); +} - if ( match ) { +function getFbxVersion( text ) { - var version = parseInt( match[ 1 ] ); - return version; + const versionRegExp = /FBXVersion: (\d+)/; + const match = text.match( versionRegExp ); - } + if ( match ) { - throw new Error( 'THREE.FBXLoader: Cannot find the version number for the file given.' ); + const version = parseInt( match[ 1 ] ); + return version; } - // Converts FBX ticks into real time seconds. - function convertFBXTimeToSeconds( time ) { + throw new Error( 'THREE.FBXLoader: Cannot find the version number for the file given.' ); - return time / 46186158000; +} - } +// Converts FBX ticks into real time seconds. +function convertFBXTimeToSeconds( time ) { - var dataArray = []; + return time / 46186158000; - // extracts the data from the correct position in the FBX array based on indexing type - function getData( polygonVertexIndex, polygonIndex, vertexIndex, infoObject ) { +} - var index; +const dataArray = []; - switch ( infoObject.mappingType ) { +// extracts the data from the correct position in the FBX array based on indexing type +function getData( polygonVertexIndex, polygonIndex, vertexIndex, infoObject ) { - case 'ByPolygonVertex' : - index = polygonVertexIndex; - break; - case 'ByPolygon' : - index = polygonIndex; - break; - case 'ByVertice' : - index = vertexIndex; - break; - case 'AllSame' : - index = infoObject.indices[ 0 ]; - break; - default : - console.warn( 'THREE.FBXLoader: unknown attribute mapping type ' + infoObject.mappingType ); + let index; - } + switch ( infoObject.mappingType ) { - if ( infoObject.referenceType === 'IndexToDirect' ) index = infoObject.indices[ index ]; + case 'ByPolygonVertex' : + index = polygonVertexIndex; + break; + case 'ByPolygon' : + index = polygonIndex; + break; + case 'ByVertice' : + index = vertexIndex; + break; + case 'AllSame' : + index = infoObject.indices[ 0 ]; + break; + default : + console.warn( 'THREE.FBXLoader: unknown attribute mapping type ' + infoObject.mappingType ); - var from = index * infoObject.dataSize; - var to = from + infoObject.dataSize; + } - return slice( dataArray, infoObject.buffer, from, to ); + if ( infoObject.referenceType === 'IndexToDirect' ) index = infoObject.indices[ index ]; - } + const from = index * infoObject.dataSize; + const to = from + infoObject.dataSize; - var tempEuler = new Euler(); - var tempVec = new Vector3(); + return slice( dataArray, infoObject.buffer, from, to ); - // generate transformation from FBX transform data - // ref: https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm - // ref: http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/index.html?url=cpp_ref/_transformations_2main_8cxx-example.html,topicNumber=cpp_ref__transformations_2main_8cxx_example_htmlfc10a1e1-b18d-4e72-9dc0-70d0f1959f5e - function generateTransform( transformData ) { +} - var lTranslationM = new Matrix4(); - var lPreRotationM = new Matrix4(); - var lRotationM = new Matrix4(); - var lPostRotationM = new Matrix4(); +const tempEuler = new Euler(); +const tempVec = new Vector3(); - var lScalingM = new Matrix4(); - var lScalingPivotM = new Matrix4(); - var lScalingOffsetM = new Matrix4(); - var lRotationOffsetM = new Matrix4(); - var lRotationPivotM = new Matrix4(); +// generate transformation from FBX transform data +// ref: https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm +// ref: http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/index.html?url=cpp_ref/_transformations_2main_8cxx-example.html,topicNumber=cpp_ref__transformations_2main_8cxx_example_htmlfc10a1e1-b18d-4e72-9dc0-70d0f1959f5e +function generateTransform( transformData ) { - var lParentGX = new Matrix4(); - var lParentLX = new Matrix4(); - var lGlobalT = new Matrix4(); + const lTranslationM = new Matrix4(); + const lPreRotationM = new Matrix4(); + const lRotationM = new Matrix4(); + const lPostRotationM = new Matrix4(); - var inheritType = ( transformData.inheritType ) ? transformData.inheritType : 0; + const lScalingM = new Matrix4(); + const lScalingPivotM = new Matrix4(); + const lScalingOffsetM = new Matrix4(); + const lRotationOffsetM = new Matrix4(); + const lRotationPivotM = new Matrix4(); - if ( transformData.translation ) lTranslationM.setPosition( tempVec.fromArray( transformData.translation ) ); + const lParentGX = new Matrix4(); + const lParentLX = new Matrix4(); + const lGlobalT = new Matrix4(); - if ( transformData.preRotation ) { + const inheritType = ( transformData.inheritType ) ? transformData.inheritType : 0; - var array = transformData.preRotation.map( MathUtils.degToRad ); - array.push( transformData.eulerOrder ); - lPreRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); + if ( transformData.translation ) lTranslationM.setPosition( tempVec.fromArray( transformData.translation ) ); - } + if ( transformData.preRotation ) { - if ( transformData.rotation ) { + const array = transformData.preRotation.map( MathUtils.degToRad ); + array.push( transformData.eulerOrder ); + lPreRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); - var array = transformData.rotation.map( MathUtils.degToRad ); - array.push( transformData.eulerOrder ); - lRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); + } - } + if ( transformData.rotation ) { - if ( transformData.postRotation ) { + const array = transformData.rotation.map( MathUtils.degToRad ); + array.push( transformData.eulerOrder ); + lRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); - var array = transformData.postRotation.map( MathUtils.degToRad ); - array.push( transformData.eulerOrder ); - lPostRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); - lPostRotationM.invert(); + } - } + if ( transformData.postRotation ) { - if ( transformData.scale ) lScalingM.scale( tempVec.fromArray( transformData.scale ) ); + const array = transformData.postRotation.map( MathUtils.degToRad ); + array.push( transformData.eulerOrder ); + lPostRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); + lPostRotationM.invert(); - // Pivots and offsets - if ( transformData.scalingOffset ) lScalingOffsetM.setPosition( tempVec.fromArray( transformData.scalingOffset ) ); - if ( transformData.scalingPivot ) lScalingPivotM.setPosition( tempVec.fromArray( transformData.scalingPivot ) ); - if ( transformData.rotationOffset ) lRotationOffsetM.setPosition( tempVec.fromArray( transformData.rotationOffset ) ); - if ( transformData.rotationPivot ) lRotationPivotM.setPosition( tempVec.fromArray( transformData.rotationPivot ) ); + } - // parent transform - if ( transformData.parentMatrixWorld ) { + if ( transformData.scale ) lScalingM.scale( tempVec.fromArray( transformData.scale ) ); - lParentLX.copy( transformData.parentMatrix ); - lParentGX.copy( transformData.parentMatrixWorld ); + // Pivots and offsets + if ( transformData.scalingOffset ) lScalingOffsetM.setPosition( tempVec.fromArray( transformData.scalingOffset ) ); + if ( transformData.scalingPivot ) lScalingPivotM.setPosition( tempVec.fromArray( transformData.scalingPivot ) ); + if ( transformData.rotationOffset ) lRotationOffsetM.setPosition( tempVec.fromArray( transformData.rotationOffset ) ); + if ( transformData.rotationPivot ) lRotationPivotM.setPosition( tempVec.fromArray( transformData.rotationPivot ) ); - } + // parent transform + if ( transformData.parentMatrixWorld ) { - var lLRM = new Matrix4().copy( lPreRotationM ).multiply( lRotationM ).multiply( lPostRotationM ); - // Global Rotation - var lParentGRM = new Matrix4(); - lParentGRM.extractRotation( lParentGX ); + lParentLX.copy( transformData.parentMatrix ); + lParentGX.copy( transformData.parentMatrixWorld ); - // Global Shear*Scaling - var lParentTM = new Matrix4(); - lParentTM.copyPosition( lParentGX ); + } - var lParentGSM = new Matrix4(); - var lParentGRSM = new Matrix4().copy( lParentTM ).invert().multiply( lParentGX ); - lParentGSM.copy( lParentGRM ).invert().multiply( lParentGRSM ); - var lLSM = lScalingM; + const lLRM = new Matrix4().copy( lPreRotationM ).multiply( lRotationM ).multiply( lPostRotationM ); + // Global Rotation + const lParentGRM = new Matrix4(); + lParentGRM.extractRotation( lParentGX ); - var lGlobalRS = new Matrix4(); + // Global Shear*Scaling + const lParentTM = new Matrix4(); + lParentTM.copyPosition( lParentGX ); - if ( inheritType === 0 ) { + const lParentGSM = new Matrix4(); + const lParentGRSM = new Matrix4().copy( lParentTM ).invert().multiply( lParentGX ); + lParentGSM.copy( lParentGRM ).invert().multiply( lParentGRSM ); + const lLSM = lScalingM; - lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM ).multiply( lLSM ); + const lGlobalRS = new Matrix4(); - } else if ( inheritType === 1 ) { + if ( inheritType === 0 ) { - lGlobalRS.copy( lParentGRM ).multiply( lParentGSM ).multiply( lLRM ).multiply( lLSM ); + lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM ).multiply( lLSM ); - } else { + } else if ( inheritType === 1 ) { - var lParentLSM = new Matrix4().scale( new Vector3().setFromMatrixScale( lParentLX ) ); - var lParentLSM_inv = new Matrix4().copy( lParentLSM ).invert(); - var lParentGSM_noLocal = new Matrix4().copy( lParentGSM ).multiply( lParentLSM_inv ); + lGlobalRS.copy( lParentGRM ).multiply( lParentGSM ).multiply( lLRM ).multiply( lLSM ); - lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM_noLocal ).multiply( lLSM ); + } else { - } + const lParentLSM = new Matrix4().scale( new Vector3().setFromMatrixScale( lParentLX ) ); + const lParentLSM_inv = new Matrix4().copy( lParentLSM ).invert(); + const lParentGSM_noLocal = new Matrix4().copy( lParentGSM ).multiply( lParentLSM_inv ); - var lRotationPivotM_inv = new Matrix4(); - lRotationPivotM_inv.copy( lRotationPivotM ).invert(); - var lScalingPivotM_inv = new Matrix4(); - lScalingPivotM_inv.copy( lScalingPivotM ).invert(); - // Calculate the local transform matrix - var lTransform = new Matrix4(); - lTransform.copy( lTranslationM ).multiply( lRotationOffsetM ).multiply( lRotationPivotM ).multiply( lPreRotationM ).multiply( lRotationM ).multiply( lPostRotationM ).multiply( lRotationPivotM_inv ).multiply( lScalingOffsetM ).multiply( lScalingPivotM ).multiply( lScalingM ).multiply( lScalingPivotM_inv ); + lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM_noLocal ).multiply( lLSM ); - var lLocalTWithAllPivotAndOffsetInfo = new Matrix4().copyPosition( lTransform ); + } - var lGlobalTranslation = new Matrix4().copy( lParentGX ).multiply( lLocalTWithAllPivotAndOffsetInfo ); - lGlobalT.copyPosition( lGlobalTranslation ); + const lRotationPivotM_inv = new Matrix4(); + lRotationPivotM_inv.copy( lRotationPivotM ).invert(); + const lScalingPivotM_inv = new Matrix4(); + lScalingPivotM_inv.copy( lScalingPivotM ).invert(); + // Calculate the local transform matrix + let lTransform = new Matrix4(); + lTransform.copy( lTranslationM ).multiply( lRotationOffsetM ).multiply( lRotationPivotM ).multiply( lPreRotationM ).multiply( lRotationM ).multiply( lPostRotationM ).multiply( lRotationPivotM_inv ).multiply( lScalingOffsetM ).multiply( lScalingPivotM ).multiply( lScalingM ).multiply( lScalingPivotM_inv ); - lTransform = new Matrix4().copy( lGlobalT ).multiply( lGlobalRS ); + const lLocalTWithAllPivotAndOffsetInfo = new Matrix4().copyPosition( lTransform ); - // from global to local - lTransform.premultiply( lParentGX.invert() ); + const lGlobalTranslation = new Matrix4().copy( lParentGX ).multiply( lLocalTWithAllPivotAndOffsetInfo ); + lGlobalT.copyPosition( lGlobalTranslation ); - return lTransform; + lTransform = new Matrix4().copy( lGlobalT ).multiply( lGlobalRS ); - } + // from global to local + lTransform.premultiply( lParentGX.invert() ); - // Returns the three.js intrinsic Euler order corresponding to FBX extrinsic Euler order - // ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html - function getEulerOrder( order ) { + return lTransform; - order = order || 0; +} - var enums = [ - 'ZYX', // -> XYZ extrinsic - 'YZX', // -> XZY extrinsic - 'XZY', // -> YZX extrinsic - 'ZXY', // -> YXZ extrinsic - 'YXZ', // -> ZXY extrinsic - 'XYZ', // -> ZYX extrinsic - //'SphericXYZ', // not possible to support - ]; +// Returns the three.js intrinsic Euler order corresponding to FBX extrinsic Euler order +// ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html +function getEulerOrder( order ) { - if ( order === 6 ) { + order = order || 0; - console.warn( 'THREE.FBXLoader: unsupported Euler Order: Spherical XYZ. Animations and rotations may be incorrect.' ); - return enums[ 0 ]; + const enums = [ + 'ZYX', // -> XYZ extrinsic + 'YZX', // -> XZY extrinsic + 'XZY', // -> YZX extrinsic + 'ZXY', // -> YXZ extrinsic + 'YXZ', // -> ZXY extrinsic + 'XYZ', // -> ZYX extrinsic + //'SphericXYZ', // not possible to support + ]; - } + if ( order === 6 ) { - return enums[ order ]; + console.warn( 'THREE.FBXLoader: unsupported Euler Order: Spherical XYZ. Animations and rotations may be incorrect.' ); + return enums[ 0 ]; } - // Parses comma separated list of numbers and returns them an array. - // Used internally by the TextParser - function parseNumberArray( value ) { + return enums[ order ]; - var array = value.split( ',' ).map( function ( val ) { +} - return parseFloat( val ); +// Parses comma separated list of numbers and returns them an array. +// Used internally by the TextParser +function parseNumberArray( value ) { - } ); + const array = value.split( ',' ).map( function ( val ) { - return array; + return parseFloat( val ); - } + } ); - function convertArrayBufferToString( buffer, from, to ) { + return array; - if ( from === undefined ) from = 0; - if ( to === undefined ) to = buffer.byteLength; +} - return LoaderUtils.decodeText( new Uint8Array( buffer, from, to ) ); +function convertArrayBufferToString( buffer, from, to ) { - } + if ( from === undefined ) from = 0; + if ( to === undefined ) to = buffer.byteLength; - function append( a, b ) { + return LoaderUtils.decodeText( new Uint8Array( buffer, from, to ) ); - for ( var i = 0, j = a.length, l = b.length; i < l; i ++, j ++ ) { +} - a[ j ] = b[ i ]; +function append( a, b ) { - } + for ( let i = 0, j = a.length, l = b.length; i < l; i ++, j ++ ) { - } + a[ j ] = b[ i ]; - function slice( a, b, from, to ) { + } - for ( var i = from, j = 0; i < to; i ++, j ++ ) { +} - a[ j ] = b[ i ]; +function slice( a, b, from, to ) { - } + for ( let i = from, j = 0; i < to; i ++, j ++ ) { - return a; + a[ j ] = b[ i ]; } - // inject array a2 into array a1 at index - function inject( a1, index, a2 ) { + return a; - return a1.slice( 0, index ).concat( a2 ).concat( a1.slice( index ) ); +} - } +// inject array a2 into array a1 at index +function inject( a1, index, a2 ) { - return FBXLoader; + return a1.slice( 0, index ).concat( a2 ).concat( a1.slice( index ) ); -} )(); +} export { FBXLoader }; diff --git a/examples/jsm/loaders/GCodeLoader.js b/examples/jsm/loaders/GCodeLoader.js index d1c4745abe08d4..649109ebef7f35 100644 --- a/examples/jsm/loaders/GCodeLoader.js +++ b/examples/jsm/loaders/GCodeLoader.js @@ -18,23 +18,21 @@ import { * @param {Manager} manager Loading manager. */ -var GCodeLoader = function ( manager ) { +class GCodeLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.splitLayer = false; + super( manager ); -}; + this.splitLayer = false; -GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: GCodeLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setRequestHeader( scope.requestHeader ); loader.setWithCredentials( scope.withCredentials ); @@ -62,19 +60,19 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { - var state = { x: 0, y: 0, z: 0, e: 0, f: 0, extruding: false, relative: false }; - var layers = []; + let state = { x: 0, y: 0, z: 0, e: 0, f: 0, extruding: false, relative: false }; + let layers = []; - var currentLayer = undefined; + let currentLayer = undefined; - var pathMaterial = new LineBasicMaterial( { color: 0xFF0000 } ); + const pathMaterial = new LineBasicMaterial( { color: 0xFF0000 } ); pathMaterial.name = 'path'; - var extrudingMaterial = new LineBasicMaterial( { color: 0x00FF00 } ); + const extrudingMaterial = new LineBasicMaterial( { color: 0x00FF00 } ); extrudingMaterial.name = 'extruded'; function newLayer( line ) { @@ -93,7 +91,7 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - if ( line.extruding ) { + if ( state.extruding ) { currentLayer.vertex.push( p1.x, p1.y, p1.z ); currentLayer.vertex.push( p2.x, p2.y, p2.z ); @@ -119,21 +117,21 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var lines = data.replace( /;.+/g, '' ).split( '\n' ); + let lines = data.replace( /;.+/g, '' ).split( '\n' ); - for ( var i = 0; i < lines.length; i ++ ) { + for ( let i = 0; i < lines.length; i ++ ) { - var tokens = lines[ i ].split( ' ' ); - var cmd = tokens[ 0 ].toUpperCase(); + let tokens = lines[ i ].split( ' ' ); + let cmd = tokens[ 0 ].toUpperCase(); //Argumments - var args = {}; + let args = {}; tokens.splice( 1 ).forEach( function ( token ) { if ( token[ 0 ] !== undefined ) { - var key = token[ 0 ].toLowerCase(); - var value = parseFloat( token.substring( 1 ) ); + let key = token[ 0 ].toLowerCase(); + let value = parseFloat( token.substring( 1 ) ); args[ key ] = value; } @@ -144,7 +142,7 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { //G0/G1 – Linear Movement if ( cmd === 'G0' || cmd === 'G1' ) { - var line = { + let line = { x: args.x !== undefined ? absolute( state.x, args.x ) : state.x, y: args.y !== undefined ? absolute( state.y, args.y ) : state.y, z: args.z !== undefined ? absolute( state.z, args.z ) : state.z, @@ -186,7 +184,7 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( cmd === 'G92' ) { //G92: Set Position - var line = state; + let line = state; line.x = args.x !== undefined ? args.x : line.x; line.y = args.y !== undefined ? args.y : line.y; line.z = args.z !== undefined ? args.z : line.z; @@ -201,47 +199,47 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - function addObject( vertex, extruding ) { + function addObject( vertex, extruding, i ) { - var geometry = new BufferGeometry(); + let geometry = new BufferGeometry(); geometry.setAttribute( 'position', new Float32BufferAttribute( vertex, 3 ) ); - - var segments = new LineSegments( geometry, extruding ? extrudingMaterial : pathMaterial ); + let segments = new LineSegments( geometry, extruding ? extrudingMaterial : pathMaterial ); segments.name = 'layer' + i; object.add( segments ); } - var object = new Group(); + const object = new Group(); object.name = 'gcode'; if ( this.splitLayer ) { - for ( var i = 0; i < layers.length; i ++ ) { + for ( let i = 0; i < layers.length; i ++ ) { - var layer = layers[ i ]; - addObject( layer.vertex, true ); - addObject( layer.pathVertex, false ); + let layer = layers[ i ]; + addObject( layer.vertex, true, i ); + addObject( layer.pathVertex, false, i ); } } else { - var vertex = [], pathVertex = []; + const vertex = [], + pathVertex = []; - for ( var i = 0; i < layers.length; i ++ ) { + for ( let i = 0; i < layers.length; i ++ ) { - var layer = layers[ i ]; - var layerVertex = layer.vertex; - var layerPathVertex = layer.pathVertex; + let layer = layers[ i ]; + let layerVertex = layer.vertex; + let layerPathVertex = layer.pathVertex; - for ( var j = 0; j < layerVertex.length; j ++ ) { + for ( let j = 0; j < layerVertex.length; j ++ ) { vertex.push( layerVertex[ j ] ); } - for ( var j = 0; j < layerPathVertex.length; j ++ ) { + for ( let j = 0; j < layerPathVertex.length; j ++ ) { pathVertex.push( layerPathVertex[ j ] ); @@ -249,8 +247,8 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - addObject( vertex, true ); - addObject( pathVertex, false ); + addObject( vertex, true, layers.length ); + addObject( pathVertex, false, layers.length ); } @@ -260,6 +258,6 @@ GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { GCodeLoader }; diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index 802134e647a879..6837c3fac0a2fe 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -63,11 +63,11 @@ import { sRGBEncoding } from '../../../build/three.module.js'; -var GLTFLoader = ( function () { +class GLTFLoader extends Loader { - function GLTFLoader( manager ) { + constructor( manager ) { - Loader.call( this, manager ); + super( manager ); this.dracoLoader = null; this.ktx2Loader = null; @@ -113,320 +113,318 @@ var GLTFLoader = ( function () { } - GLTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + load( url, onLoad, onProgress, onError ) { - constructor: GLTFLoader, + const scope = this; - load: function ( url, onLoad, onProgress, onError ) { + let resourcePath; - var scope = this; + if ( this.resourcePath !== '' ) { - var resourcePath; + resourcePath = this.resourcePath; - if ( this.resourcePath !== '' ) { + } else if ( this.path !== '' ) { - resourcePath = this.resourcePath; + resourcePath = this.path; - } else if ( this.path !== '' ) { - - resourcePath = this.path; - - } else { - - resourcePath = LoaderUtils.extractUrlBase( url ); + } else { - } + resourcePath = LoaderUtils.extractUrlBase( url ); - // Tells the LoadingManager to track an extra item, which resolves after - // the model is fully loaded. This means the count of items loaded will - // be incorrect, but ensures manager.onLoad() does not fire early. - this.manager.itemStart( url ); + } - var _onError = function ( e ) { + // Tells the LoadingManager to track an extra item, which resolves after + // the model is fully loaded. This means the count of items loaded will + // be incorrect, but ensures manager.onLoad() does not fire early. + this.manager.itemStart( url ); - if ( onError ) { + const _onError = function ( e ) { - onError( e ); + if ( onError ) { - } else { + onError( e ); - console.error( e ); + } else { - } + console.error( e ); - scope.manager.itemError( url ); - scope.manager.itemEnd( url ); + } - }; + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - var loader = new FileLoader( this.manager ); + }; - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); + const loader = new FileLoader( this.manager ); - loader.load( url, function ( data ) { + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); - try { + loader.load( url, function ( data ) { - scope.parse( data, resourcePath, function ( gltf ) { + try { - onLoad( gltf ); + scope.parse( data, resourcePath, function ( gltf ) { - scope.manager.itemEnd( url ); + onLoad( gltf ); - }, _onError ); + scope.manager.itemEnd( url ); - } catch ( e ) { + }, _onError ); - _onError( e ); + } catch ( e ) { - } + _onError( e ); - }, onProgress, _onError ); + } - }, + }, onProgress, _onError ); - setDRACOLoader: function ( dracoLoader ) { + } - this.dracoLoader = dracoLoader; - return this; + setDRACOLoader( dracoLoader ) { - }, + this.dracoLoader = dracoLoader; + return this; - setDDSLoader: function () { + } - throw new Error( + setDDSLoader() { - 'THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".' + throw new Error( - ); + 'THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".' - }, + ); - setKTX2Loader: function ( ktx2Loader ) { + } - this.ktx2Loader = ktx2Loader; - return this; + setKTX2Loader( ktx2Loader ) { - }, + this.ktx2Loader = ktx2Loader; + return this; - setMeshoptDecoder: function ( meshoptDecoder ) { + } - this.meshoptDecoder = meshoptDecoder; - return this; + setMeshoptDecoder( meshoptDecoder ) { - }, + this.meshoptDecoder = meshoptDecoder; + return this; - register: function ( callback ) { + } - if ( this.pluginCallbacks.indexOf( callback ) === - 1 ) { + register( callback ) { - this.pluginCallbacks.push( callback ); + if ( this.pluginCallbacks.indexOf( callback ) === - 1 ) { - } + this.pluginCallbacks.push( callback ); - return this; + } - }, + return this; - unregister: function ( callback ) { + } - if ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) { + unregister( callback ) { - this.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 ); + if ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) { - } + this.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 ); - return this; + } - }, + return this; - parse: function ( data, path, onLoad, onError ) { + } - var content; - var extensions = {}; - var plugins = {}; + parse( data, path, onLoad, onError ) { - if ( typeof data === 'string' ) { + let content; + const extensions = {}; + const plugins = {}; - content = data; + if ( typeof data === 'string' ) { - } else { + content = data; - var magic = LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) ); + } else { - if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) { + const magic = LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) ); - try { + if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) { - extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data ); + try { - } catch ( error ) { + extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data ); - if ( onError ) onError( error ); - return; + } catch ( error ) { - } + if ( onError ) onError( error ); + return; - content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content; + } - } else { + content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content; - content = LoaderUtils.decodeText( new Uint8Array( data ) ); + } else { - } + content = LoaderUtils.decodeText( new Uint8Array( data ) ); } - var json = JSON.parse( content ); + } - if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) { + const json = JSON.parse( content ); - if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) ); - return; + if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) { - } + if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) ); + return; - var parser = new GLTFParser( json, { + } - path: path || this.resourcePath || '', - crossOrigin: this.crossOrigin, - requestHeader: this.requestHeader, - manager: this.manager, - ktx2Loader: this.ktx2Loader, - meshoptDecoder: this.meshoptDecoder + const parser = new GLTFParser( json, { - } ); + path: path || this.resourcePath || '', + crossOrigin: this.crossOrigin, + requestHeader: this.requestHeader, + manager: this.manager, + ktx2Loader: this.ktx2Loader, + meshoptDecoder: this.meshoptDecoder - parser.fileLoader.setRequestHeader( this.requestHeader ); + } ); - for ( var i = 0; i < this.pluginCallbacks.length; i ++ ) { + parser.fileLoader.setRequestHeader( this.requestHeader ); - var plugin = this.pluginCallbacks[ i ]( parser ); - plugins[ plugin.name ] = plugin; + for ( let i = 0; i < this.pluginCallbacks.length; i ++ ) { - // Workaround to avoid determining as unknown extension - // in addUnknownExtensionsToUserData(). - // Remove this workaround if we move all the existing - // extension handlers to plugin system - extensions[ plugin.name ] = true; + const plugin = this.pluginCallbacks[ i ]( parser ); + plugins[ plugin.name ] = plugin; - } + // Workaround to avoid determining as unknown extension + // in addUnknownExtensionsToUserData(). + // Remove this workaround if we move all the existing + // extension handlers to plugin system + extensions[ plugin.name ] = true; - if ( json.extensionsUsed ) { + } - for ( var i = 0; i < json.extensionsUsed.length; ++ i ) { + if ( json.extensionsUsed ) { - var extensionName = json.extensionsUsed[ i ]; - var extensionsRequired = json.extensionsRequired || []; + for ( let i = 0; i < json.extensionsUsed.length; ++ i ) { - switch ( extensionName ) { + const extensionName = json.extensionsUsed[ i ]; + const extensionsRequired = json.extensionsRequired || []; - case EXTENSIONS.KHR_MATERIALS_UNLIT: - extensions[ extensionName ] = new GLTFMaterialsUnlitExtension(); - break; + switch ( extensionName ) { - case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: - extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension(); - break; + case EXTENSIONS.KHR_MATERIALS_UNLIT: + extensions[ extensionName ] = new GLTFMaterialsUnlitExtension(); + break; - case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION: - extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader ); - break; + case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: + extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension(); + break; - case EXTENSIONS.KHR_TEXTURE_TRANSFORM: - extensions[ extensionName ] = new GLTFTextureTransformExtension(); - break; + case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION: + extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader ); + break; - case EXTENSIONS.KHR_MESH_QUANTIZATION: - extensions[ extensionName ] = new GLTFMeshQuantizationExtension(); - break; + case EXTENSIONS.KHR_TEXTURE_TRANSFORM: + extensions[ extensionName ] = new GLTFTextureTransformExtension(); + break; - default: + case EXTENSIONS.KHR_MESH_QUANTIZATION: + extensions[ extensionName ] = new GLTFMeshQuantizationExtension(); + break; - if ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) { + default: - console.warn( 'THREE.GLTFLoader: Unknown extension "' + extensionName + '".' ); + if ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) { - } + console.warn( 'THREE.GLTFLoader: Unknown extension "' + extensionName + '".' ); - } + } } } - parser.setExtensions( extensions ); - parser.setPlugins( plugins ); - parser.parse( onLoad, onError ); - } - } ); + parser.setExtensions( extensions ); + parser.setPlugins( plugins ); + parser.parse( onLoad, onError ); - /* GLTFREGISTRY */ + } - function GLTFRegistry() { +} - var objects = {}; +/* GLTFREGISTRY */ - return { +function GLTFRegistry() { - get: function ( key ) { + let objects = {}; - return objects[ key ]; + return { - }, + get: function ( key ) { - add: function ( key, object ) { + return objects[ key ]; - objects[ key ] = object; + }, - }, + add: function ( key, object ) { - remove: function ( key ) { + objects[ key ] = object; - delete objects[ key ]; + }, - }, + remove: function ( key ) { - removeAll: function () { + delete objects[ key ]; - objects = {}; + }, - } + removeAll: function () { - }; + objects = {}; - } + } - /*********************************/ - /********** EXTENSIONS ***********/ - /*********************************/ - - var EXTENSIONS = { - KHR_BINARY_GLTF: 'KHR_binary_glTF', - KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression', - KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual', - KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat', - KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness', - KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission', - KHR_MATERIALS_UNLIT: 'KHR_materials_unlit', - KHR_TEXTURE_BASISU: 'KHR_texture_basisu', - KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', - KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', - EXT_TEXTURE_WEBP: 'EXT_texture_webp', - EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression' }; - /** +} + +/*********************************/ +/********** EXTENSIONS ***********/ +/*********************************/ + +const EXTENSIONS = { + KHR_BINARY_GLTF: 'KHR_binary_glTF', + KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression', + KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual', + KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat', + KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness', + KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission', + KHR_MATERIALS_UNLIT: 'KHR_materials_unlit', + KHR_TEXTURE_BASISU: 'KHR_texture_basisu', + KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', + KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', + EXT_TEXTURE_WEBP: 'EXT_texture_webp', + EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression' +}; + +/** * Punctual Lights Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual */ - function GLTFLightsExtension( parser ) { +class GLTFLightsExtension { + + constructor( parser ) { this.parser = parser; this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL; @@ -436,18 +434,18 @@ var GLTFLoader = ( function () { } - GLTFLightsExtension.prototype._markDefs = function () { + _markDefs() { - var parser = this.parser; - var nodeDefs = this.parser.json.nodes || []; + const parser = this.parser; + const nodeDefs = this.parser.json.nodes || []; - for ( var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) { + for ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) { - var nodeDef = nodeDefs[ nodeIndex ]; + const nodeDef = nodeDefs[ nodeIndex ]; if ( nodeDef.extensions - && nodeDef.extensions[ this.name ] - && nodeDef.extensions[ this.name ].light !== undefined ) { + && nodeDef.extensions[ this.name ] + && nodeDef.extensions[ this.name ].light !== undefined ) { parser._addNodeRef( this.cache, nodeDef.extensions[ this.name ].light ); @@ -455,27 +453,27 @@ var GLTFLoader = ( function () { } - }; + } - GLTFLightsExtension.prototype._loadLight = function ( lightIndex ) { + _loadLight( lightIndex ) { - var parser = this.parser; - var cacheKey = 'light:' + lightIndex; - var dependency = parser.cache.get( cacheKey ); + const parser = this.parser; + const cacheKey = 'light:' + lightIndex; + let dependency = parser.cache.get( cacheKey ); if ( dependency ) return dependency; - var json = parser.json; - var extensions = ( json.extensions && json.extensions[ this.name ] ) || {}; - var lightDefs = extensions.lights || []; - var lightDef = lightDefs[ lightIndex ]; - var lightNode; + const json = parser.json; + const extensions = ( json.extensions && json.extensions[ this.name ] ) || {}; + const lightDefs = extensions.lights || []; + const lightDef = lightDefs[ lightIndex ]; + let lightNode; - var color = new Color( 0xffffff ); + const color = new Color( 0xffffff ); if ( lightDef.color !== undefined ) color.fromArray( lightDef.color ); - var range = lightDef.range !== undefined ? lightDef.range : 0; + const range = lightDef.range !== undefined ? lightDef.range : 0; switch ( lightDef.type ) { @@ -524,16 +522,16 @@ var GLTFLoader = ( function () { return dependency; - }; + } - GLTFLightsExtension.prototype.createNodeAttachment = function ( nodeIndex ) { + createNodeAttachment( nodeIndex ) { - var self = this; - var parser = this.parser; - var json = parser.json; - var nodeDef = json.nodes[ nodeIndex ]; - var lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {}; - var lightIndex = lightDef.light; + const self = this; + const parser = this.parser; + const json = parser.json; + const nodeDef = json.nodes[ nodeIndex ]; + const lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {}; + const lightIndex = lightDef.light; if ( lightIndex === undefined ) return null; @@ -543,39 +541,43 @@ var GLTFLoader = ( function () { } ); - }; + } - /** +} + +/** * Unlit Materials Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit */ - function GLTFMaterialsUnlitExtension() { +class GLTFMaterialsUnlitExtension { + + constructor() { this.name = EXTENSIONS.KHR_MATERIALS_UNLIT; } - GLTFMaterialsUnlitExtension.prototype.getMaterialType = function () { + getMaterialType() { return MeshBasicMaterial; - }; + } - GLTFMaterialsUnlitExtension.prototype.extendParams = function ( materialParams, materialDef, parser ) { + extendParams( materialParams, materialDef, parser ) { - var pending = []; + const pending = []; materialParams.color = new Color( 1.0, 1.0, 1.0 ); materialParams.opacity = 1.0; - var metallicRoughness = materialDef.pbrMetallicRoughness; + const metallicRoughness = materialDef.pbrMetallicRoughness; if ( metallicRoughness ) { if ( Array.isArray( metallicRoughness.baseColorFactor ) ) { - var array = metallicRoughness.baseColorFactor; + const array = metallicRoughness.baseColorFactor; materialParams.color.fromArray( array ); materialParams.opacity = array[ 3 ]; @@ -592,35 +594,39 @@ var GLTFLoader = ( function () { return Promise.all( pending ); - }; + } - /** +} + +/** * Clearcoat Materials Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat */ - function GLTFMaterialsClearcoatExtension( parser ) { +class GLTFMaterialsClearcoatExtension { + + constructor( parser ) { this.parser = parser; this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT; } - GLTFMaterialsClearcoatExtension.prototype.getMaterialType = function ( materialIndex ) { + getMaterialType( materialIndex ) { - var parser = this.parser; - var materialDef = parser.json.materials[ materialIndex ]; + const parser = this.parser; + const materialDef = parser.json.materials[ materialIndex ]; if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; return MeshPhysicalMaterial; - }; + } - GLTFMaterialsClearcoatExtension.prototype.extendMaterialParams = function ( materialIndex, materialParams ) { + extendMaterialParams( materialIndex, materialParams ) { - var parser = this.parser; - var materialDef = parser.json.materials[ materialIndex ]; + const parser = this.parser; + const materialDef = parser.json.materials[ materialIndex ]; if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { @@ -628,9 +634,9 @@ var GLTFLoader = ( function () { } - var pending = []; + const pending = []; - var extension = materialDef.extensions[ this.name ]; + const extension = materialDef.extensions[ this.name ]; if ( extension.clearcoatFactor !== undefined ) { @@ -662,7 +668,7 @@ var GLTFLoader = ( function () { if ( extension.clearcoatNormalTexture.scale !== undefined ) { - var scale = extension.clearcoatNormalTexture.scale; + const scale = extension.clearcoatNormalTexture.scale; // https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995 materialParams.clearcoatNormalScale = new Vector2( scale, - scale ); @@ -673,36 +679,40 @@ var GLTFLoader = ( function () { return Promise.all( pending ); - }; + } - /** +} + +/** * Transmission Materials Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission * Draft: https://github.com/KhronosGroup/glTF/pull/1698 */ - function GLTFMaterialsTransmissionExtension( parser ) { +class GLTFMaterialsTransmissionExtension { + + constructor( parser ) { this.parser = parser; this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION; } - GLTFMaterialsTransmissionExtension.prototype.getMaterialType = function ( materialIndex ) { + getMaterialType( materialIndex ) { - var parser = this.parser; - var materialDef = parser.json.materials[ materialIndex ]; + const parser = this.parser; + const materialDef = parser.json.materials[ materialIndex ]; if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; return MeshPhysicalMaterial; - }; + } - GLTFMaterialsTransmissionExtension.prototype.extendMaterialParams = function ( materialIndex, materialParams ) { + extendMaterialParams( materialIndex, materialParams ) { - var parser = this.parser; - var materialDef = parser.json.materials[ materialIndex ]; + const parser = this.parser; + const materialDef = parser.json.materials[ materialIndex ]; if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { @@ -710,9 +720,9 @@ var GLTFLoader = ( function () { } - var pending = []; + const pending = []; - var extension = materialDef.extensions[ this.name ]; + const extension = materialDef.extensions[ this.name ]; if ( extension.transmissionFactor !== undefined ) { @@ -728,26 +738,30 @@ var GLTFLoader = ( function () { return Promise.all( pending ); - }; + } - /** +} + +/** * BasisU Texture Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu */ - function GLTFTextureBasisUExtension( parser ) { +class GLTFTextureBasisUExtension { + + constructor( parser ) { this.parser = parser; this.name = EXTENSIONS.KHR_TEXTURE_BASISU; } - GLTFTextureBasisUExtension.prototype.loadTexture = function ( textureIndex ) { + loadTexture( textureIndex ) { - var parser = this.parser; - var json = parser.json; + const parser = this.parser; + const json = parser.json; - var textureDef = json.textures[ textureIndex ]; + const textureDef = json.textures[ textureIndex ]; if ( ! textureDef.extensions || ! textureDef.extensions[ this.name ] ) { @@ -755,9 +769,9 @@ var GLTFLoader = ( function () { } - var extension = textureDef.extensions[ this.name ]; - var source = json.images[ extension.source ]; - var loader = parser.options.ktx2Loader; + const extension = textureDef.extensions[ this.name ]; + const source = json.images[ extension.source ]; + const loader = parser.options.ktx2Loader; if ( ! loader ) { @@ -776,14 +790,18 @@ var GLTFLoader = ( function () { return parser.loadTextureImage( textureIndex, source, loader ); - }; + } - /** +} + +/** * WebP Texture Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp */ - function GLTFTextureWebPExtension( parser ) { +class GLTFTextureWebPExtension { + + constructor( parser ) { this.parser = parser; this.name = EXTENSIONS.EXT_TEXTURE_WEBP; @@ -791,13 +809,13 @@ var GLTFLoader = ( function () { } - GLTFTextureWebPExtension.prototype.loadTexture = function ( textureIndex ) { + loadTexture( textureIndex ) { - var name = this.name; - var parser = this.parser; - var json = parser.json; + const name = this.name; + const parser = this.parser; + const json = parser.json; - var textureDef = json.textures[ textureIndex ]; + const textureDef = json.textures[ textureIndex ]; if ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) { @@ -805,13 +823,13 @@ var GLTFLoader = ( function () { } - var extension = textureDef.extensions[ name ]; - var source = json.images[ extension.source ]; + const extension = textureDef.extensions[ name ]; + const source = json.images[ extension.source ]; - var loader = parser.textureLoader; + let loader = parser.textureLoader; if ( source.uri ) { - var handler = parser.options.manager.getHandler( source.uri ); + const handler = parser.options.manager.getHandler( source.uri ); if ( handler !== null ) loader = handler; } @@ -831,15 +849,15 @@ var GLTFLoader = ( function () { } ); - }; + } - GLTFTextureWebPExtension.prototype.detectSupport = function () { + detectSupport() { if ( ! this.isSupported ) { this.isSupported = new Promise( function ( resolve ) { - var image = new Image(); + const image = new Image(); // Lossy test image. Support for lossy images doesn't guarantee support for all // WebP images, unfortunately. @@ -857,31 +875,35 @@ var GLTFLoader = ( function () { return this.isSupported; - }; + } - /** +} + +/** * meshopt BufferView Compression Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression */ - function GLTFMeshoptCompression( parser ) { +class GLTFMeshoptCompression { + + constructor( parser ) { this.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION; this.parser = parser; } - GLTFMeshoptCompression.prototype.loadBufferView = function ( index ) { + loadBufferView( index ) { - var json = this.parser.json; - var bufferView = json.bufferViews[ index ]; + const json = this.parser.json; + const bufferView = json.bufferViews[ index ]; if ( bufferView.extensions && bufferView.extensions[ this.name ] ) { - var extensionDef = bufferView.extensions[ this.name ]; + const extensionDef = bufferView.extensions[ this.name ]; - var buffer = this.parser.getDependency( 'buffer', extensionDef.buffer ); - var decoder = this.parser.options.meshoptDecoder; + const buffer = this.parser.getDependency( 'buffer', extensionDef.buffer ); + const decoder = this.parser.options.meshoptDecoder; if ( ! decoder || ! decoder.supported ) { @@ -900,14 +922,14 @@ var GLTFLoader = ( function () { return Promise.all( [ buffer, decoder.ready ] ).then( function ( res ) { - var byteOffset = extensionDef.byteOffset || 0; - var byteLength = extensionDef.byteLength || 0; + const byteOffset = extensionDef.byteOffset || 0; + const byteLength = extensionDef.byteLength || 0; - var count = extensionDef.count; - var stride = extensionDef.byteStride; + const count = extensionDef.count; + const stride = extensionDef.byteStride; - var result = new ArrayBuffer( count * stride ); - var source = new Uint8Array( res[ 0 ], byteOffset, byteLength ); + const result = new ArrayBuffer( count * stride ); + const source = new Uint8Array( res[ 0 ], byteOffset, byteLength ); decoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter ); return result; @@ -920,20 +942,24 @@ var GLTFLoader = ( function () { } - }; + } - /* BINARY EXTENSION */ - var BINARY_EXTENSION_HEADER_MAGIC = 'glTF'; - var BINARY_EXTENSION_HEADER_LENGTH = 12; - var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 }; +} - function GLTFBinaryExtension( data ) { +/* BINARY EXTENSION */ +const BINARY_EXTENSION_HEADER_MAGIC = 'glTF'; +const BINARY_EXTENSION_HEADER_LENGTH = 12; +const BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 }; + +class GLTFBinaryExtension { + + constructor( data ) { this.name = EXTENSIONS.KHR_BINARY_GLTF; this.content = null; this.body = null; - var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH ); + const headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH ); this.header = { magic: LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ), @@ -951,26 +977,26 @@ var GLTFLoader = ( function () { } - var chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH; - var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH ); - var chunkIndex = 0; + const chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH; + const chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH ); + let chunkIndex = 0; while ( chunkIndex < chunkContentsLength ) { - var chunkLength = chunkView.getUint32( chunkIndex, true ); + const chunkLength = chunkView.getUint32( chunkIndex, true ); chunkIndex += 4; - var chunkType = chunkView.getUint32( chunkIndex, true ); + const chunkType = chunkView.getUint32( chunkIndex, true ); chunkIndex += 4; if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) { - var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength ); + const contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength ); this.content = LoaderUtils.decodeText( contentArray ); } else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) { - var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex; + const byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex; this.body = data.slice( byteOffset, byteOffset + chunkLength ); } @@ -989,12 +1015,16 @@ var GLTFLoader = ( function () { } - /** +} + +/** * DRACO Mesh Compression Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression */ - function GLTFDracoMeshCompressionExtension( json, dracoLoader ) { +class GLTFDracoMeshCompressionExtension { + + constructor( json, dracoLoader ) { if ( ! dracoLoader ) { @@ -1009,32 +1039,32 @@ var GLTFLoader = ( function () { } - GLTFDracoMeshCompressionExtension.prototype.decodePrimitive = function ( primitive, parser ) { + decodePrimitive( primitive, parser ) { - var json = this.json; - var dracoLoader = this.dracoLoader; - var bufferViewIndex = primitive.extensions[ this.name ].bufferView; - var gltfAttributeMap = primitive.extensions[ this.name ].attributes; - var threeAttributeMap = {}; - var attributeNormalizedMap = {}; - var attributeTypeMap = {}; + const json = this.json; + const dracoLoader = this.dracoLoader; + const bufferViewIndex = primitive.extensions[ this.name ].bufferView; + const gltfAttributeMap = primitive.extensions[ this.name ].attributes; + const threeAttributeMap = {}; + const attributeNormalizedMap = {}; + const attributeTypeMap = {}; - for ( var attributeName in gltfAttributeMap ) { + for ( const attributeName in gltfAttributeMap ) { - var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase(); + const threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase(); threeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ]; } - for ( attributeName in primitive.attributes ) { + for ( const attributeName in primitive.attributes ) { - var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase(); + const threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase(); if ( gltfAttributeMap[ attributeName ] !== undefined ) { - var accessorDef = json.accessors[ primitive.attributes[ attributeName ] ]; - var componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ]; + const accessorDef = json.accessors[ primitive.attributes[ attributeName ] ]; + const componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ]; attributeTypeMap[ threeAttributeName ] = componentType; attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true; @@ -1049,10 +1079,10 @@ var GLTFLoader = ( function () { dracoLoader.decodeDracoFile( bufferView, function ( geometry ) { - for ( var attributeName in geometry.attributes ) { + for ( const attributeName in geometry.attributes ) { - var attribute = geometry.attributes[ attributeName ]; - var normalized = attributeNormalizedMap[ attributeName ]; + const attribute = geometry.attributes[ attributeName ]; + const normalized = attributeNormalizedMap[ attributeName ]; if ( normalized !== undefined ) attribute.normalized = normalized; @@ -1066,20 +1096,24 @@ var GLTFLoader = ( function () { } ); - }; + } - /** +} + +/** * Texture Transform Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform */ - function GLTFTextureTransformExtension() { +class GLTFTextureTransformExtension { + + constructor() { this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM; } - GLTFTextureTransformExtension.prototype.extendTexture = function ( texture, transform ) { + extendTexture( texture, transform ) { texture = texture.clone(); @@ -1111,40 +1145,44 @@ var GLTFLoader = ( function () { return texture; - }; + } - /** +} + +/** * Specular-Glossiness Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness */ - /** +/** * A sub class of StandardMaterial with some of the functionality * changed via the `onBeforeCompile` callback * @pailhead */ - function GLTFMeshStandardSGMaterial( params ) { +class GLTFMeshStandardSGMaterial extends MeshStandardMaterial { + + constructor( params ) { - MeshStandardMaterial.call( this ); + super(); this.isGLTFSpecularGlossinessMaterial = true; //various chunks that need replacing - var specularMapParsFragmentChunk = [ + const specularMapParsFragmentChunk = [ '#ifdef USE_SPECULARMAP', ' uniform sampler2D specularMap;', '#endif' ].join( '\n' ); - var glossinessMapParsFragmentChunk = [ + const glossinessMapParsFragmentChunk = [ '#ifdef USE_GLOSSINESSMAP', ' uniform sampler2D glossinessMap;', '#endif' ].join( '\n' ); - var specularMapFragmentChunk = [ + const specularMapFragmentChunk = [ 'vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', ' vec4 texelSpecular = texture2D( specularMap, vUv );', @@ -1154,7 +1192,7 @@ var GLTFLoader = ( function () { '#endif' ].join( '\n' ); - var glossinessMapFragmentChunk = [ + const glossinessMapFragmentChunk = [ 'float glossinessFactor = glossiness;', '#ifdef USE_GLOSSINESSMAP', ' vec4 texelGlossiness = texture2D( glossinessMap, vUv );', @@ -1163,7 +1201,7 @@ var GLTFLoader = ( function () { '#endif' ].join( '\n' ); - var lightPhysicalFragmentChunk = [ + 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 ) ) );', @@ -1174,7 +1212,7 @@ var GLTFLoader = ( function () { 'material.specularColor = specularFactor;', ].join( '\n' ); - var uniforms = { + const uniforms = { specular: { value: new Color().setHex( 0xffffff ) }, glossiness: { value: 1 }, specularMap: { value: null }, @@ -1185,7 +1223,7 @@ var GLTFLoader = ( function () { this.onBeforeCompile = function ( shader ) { - for ( var uniformName in uniforms ) { + for ( const uniformName in uniforms ) { shader.uniforms[ uniformName ] = uniforms[ uniformName ]; @@ -1289,12 +1327,10 @@ var GLTFLoader = ( function () { } - GLTFMeshStandardSGMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); - GLTFMeshStandardSGMaterial.prototype.constructor = GLTFMeshStandardSGMaterial; + copy( source ) { - GLTFMeshStandardSGMaterial.prototype.copy = function ( source ) { + super.copy( source ); - MeshStandardMaterial.prototype.copy.call( this, source ); this.specularMap = source.specularMap; this.specular.copy( source.specular ); this.glossinessMap = source.glossinessMap; @@ -1305,182 +1341,188 @@ var GLTFLoader = ( function () { delete this.roughnessMap; return this; - }; + } - function GLTFMaterialsPbrSpecularGlossinessExtension() { - - return { - - name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS, - - specularGlossinessParams: [ - 'color', - 'map', - 'lightMap', - 'lightMapIntensity', - 'aoMap', - 'aoMapIntensity', - 'emissive', - 'emissiveIntensity', - 'emissiveMap', - 'bumpMap', - 'bumpScale', - 'normalMap', - 'normalMapType', - 'displacementMap', - 'displacementScale', - 'displacementBias', - 'specularMap', - 'specular', - 'glossinessMap', - 'glossiness', - 'alphaMap', - 'envMap', - 'envMapIntensity', - 'refractionRatio', - ], - - getMaterialType: function () { - - return GLTFMeshStandardSGMaterial; +} + + +class GLTFMaterialsPbrSpecularGlossinessExtension { + + constructor() { + + this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS; + + this.specularGlossinessParams = [ + 'color', + 'map', + 'lightMap', + 'lightMapIntensity', + 'aoMap', + 'aoMapIntensity', + 'emissive', + 'emissiveIntensity', + 'emissiveMap', + 'bumpMap', + 'bumpScale', + 'normalMap', + 'normalMapType', + 'displacementMap', + 'displacementScale', + 'displacementBias', + 'specularMap', + 'specular', + 'glossinessMap', + 'glossiness', + 'alphaMap', + 'envMap', + 'envMapIntensity', + 'refractionRatio', + ]; - }, + } - extendParams: function ( materialParams, materialDef, parser ) { + getMaterialType() { - var pbrSpecularGlossiness = materialDef.extensions[ this.name ]; + return GLTFMeshStandardSGMaterial; - materialParams.color = new Color( 1.0, 1.0, 1.0 ); - materialParams.opacity = 1.0; + } - var pending = []; + extendParams( materialParams, materialDef, parser ) { - if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) { + const pbrSpecularGlossiness = materialDef.extensions[ this.name ]; - var array = pbrSpecularGlossiness.diffuseFactor; + materialParams.color = new Color( 1.0, 1.0, 1.0 ); + materialParams.opacity = 1.0; - materialParams.color.fromArray( array ); - materialParams.opacity = array[ 3 ]; + const pending = []; - } + if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) { - if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) { + const array = pbrSpecularGlossiness.diffuseFactor; - pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture ) ); + materialParams.color.fromArray( array ); + materialParams.opacity = array[ 3 ]; - } + } - materialParams.emissive = new Color( 0.0, 0.0, 0.0 ); - materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0; - materialParams.specular = new Color( 1.0, 1.0, 1.0 ); + if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) { - if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) { + pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture ) ); - materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor ); + } - } + materialParams.emissive = new Color( 0.0, 0.0, 0.0 ); + materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0; + materialParams.specular = new Color( 1.0, 1.0, 1.0 ); - if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) { + if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) { - var specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture; - pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) ); - pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef ) ); + materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor ); - } + } - return Promise.all( pending ); + if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) { - }, + const specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture; + pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) ); + pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef ) ); - createMaterial: function ( materialParams ) { + } - var material = new GLTFMeshStandardSGMaterial( materialParams ); - material.fog = true; + return Promise.all( pending ); - material.color = materialParams.color; + } - material.map = materialParams.map === undefined ? null : materialParams.map; + createMaterial( materialParams ) { - material.lightMap = null; - material.lightMapIntensity = 1.0; + const material = new GLTFMeshStandardSGMaterial( materialParams ); + material.fog = true; - material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap; - material.aoMapIntensity = 1.0; + material.color = materialParams.color; - material.emissive = materialParams.emissive; - material.emissiveIntensity = 1.0; - material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap; + material.map = materialParams.map === undefined ? null : materialParams.map; - material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap; - material.bumpScale = 1; + material.lightMap = null; + material.lightMapIntensity = 1.0; - material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap; - material.normalMapType = TangentSpaceNormalMap; + material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap; + material.aoMapIntensity = 1.0; - if ( materialParams.normalScale ) material.normalScale = materialParams.normalScale; + material.emissive = materialParams.emissive; + material.emissiveIntensity = 1.0; + material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap; - material.displacementMap = null; - material.displacementScale = 1; - material.displacementBias = 0; + material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap; + material.bumpScale = 1; - material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap; - material.specular = materialParams.specular; + material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap; + material.normalMapType = TangentSpaceNormalMap; - material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap; - material.glossiness = materialParams.glossiness; + if ( materialParams.normalScale ) material.normalScale = materialParams.normalScale; - material.alphaMap = null; + material.displacementMap = null; + material.displacementScale = 1; + material.displacementBias = 0; - material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap; - material.envMapIntensity = 1.0; + material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap; + material.specular = materialParams.specular; - material.refractionRatio = 0.98; + material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap; + material.glossiness = materialParams.glossiness; - return material; + material.alphaMap = null; - }, + material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap; + material.envMapIntensity = 1.0; - }; + material.refractionRatio = 0.98; + + return material; } - /** +} + +/** * Mesh Quantization Extension * * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization */ - function GLTFMeshQuantizationExtension() { +class GLTFMeshQuantizationExtension { + + constructor() { this.name = EXTENSIONS.KHR_MESH_QUANTIZATION; } - /*********************************/ - /********** INTERPOLATION ********/ - /*********************************/ +} - // Spline Interpolation - // Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation - function GLTFCubicSplineInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +/*********************************/ +/********** INTERPOLATION ********/ +/*********************************/ - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); +// Spline Interpolation +// Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation +class GLTFCubicSplineInterpolant extends Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - GLTFCubicSplineInterpolant.prototype = Object.create( Interpolant.prototype ); - GLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant; + } - GLTFCubicSplineInterpolant.prototype.copySampleValue_ = function ( index ) { + copySampleValue_( index ) { // Copies a sample value to the result buffer. See description of glTF // CUBICSPLINE values layout in interpolate_() function below. - var result = this.resultBuffer, + const result = this.resultBuffer, values = this.sampleValues, valueSize = this.valueSize, offset = index * valueSize * 3 + valueSize; - for ( var i = 0; i !== valueSize; i ++ ) { + for ( let i = 0; i !== valueSize; i ++ ) { result[ i ] = values[ offset + i ]; @@ -1488,236 +1530,238 @@ var GLTFLoader = ( function () { return result; - }; - - GLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_; - - GLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_; - - GLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) { - - var result = this.resultBuffer; - var values = this.sampleValues; - var stride = this.valueSize; - - var stride2 = stride * 2; - var stride3 = stride * 3; - - var td = t1 - t0; - - var p = ( t - t0 ) / td; - var pp = p * p; - var ppp = pp * p; - - var offset1 = i1 * stride3; - var offset0 = offset1 - stride3; + } - var s2 = - 2 * ppp + 3 * pp; - var s3 = ppp - pp; - var s0 = 1 - s2; - var s1 = s3 - pp + p; +} - // Layout of keyframe output values for CUBICSPLINE animations: - // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ] - for ( var i = 0; i !== stride; i ++ ) { +GLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_; - var p0 = values[ offset0 + i + stride ]; // splineVertex_k - var m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k) - var p1 = values[ offset1 + i + stride ]; // splineVertex_k+1 - var m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k) +GLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_; - result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1; +GLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) { - } + const result = this.resultBuffer; + const values = this.sampleValues; + const stride = this.valueSize; - return result; + const stride2 = stride * 2; + const stride3 = stride * 3; - }; + const td = t1 - t0; - /*********************************/ - /********** INTERNALS ************/ - /*********************************/ - - /* CONSTANTS */ - - var WEBGL_CONSTANTS = { - FLOAT: 5126, - //FLOAT_MAT2: 35674, - FLOAT_MAT3: 35675, - FLOAT_MAT4: 35676, - FLOAT_VEC2: 35664, - FLOAT_VEC3: 35665, - FLOAT_VEC4: 35666, - LINEAR: 9729, - REPEAT: 10497, - SAMPLER_2D: 35678, - POINTS: 0, - LINES: 1, - LINE_LOOP: 2, - LINE_STRIP: 3, - TRIANGLES: 4, - TRIANGLE_STRIP: 5, - TRIANGLE_FAN: 6, - UNSIGNED_BYTE: 5121, - UNSIGNED_SHORT: 5123 - }; + const p = ( t - t0 ) / td; + const pp = p * p; + const ppp = pp * p; - var WEBGL_COMPONENT_TYPES = { - 5120: Int8Array, - 5121: Uint8Array, - 5122: Int16Array, - 5123: Uint16Array, - 5125: Uint32Array, - 5126: Float32Array - }; + const offset1 = i1 * stride3; + const offset0 = offset1 - stride3; - var WEBGL_FILTERS = { - 9728: NearestFilter, - 9729: LinearFilter, - 9984: NearestMipmapNearestFilter, - 9985: LinearMipmapNearestFilter, - 9986: NearestMipmapLinearFilter, - 9987: LinearMipmapLinearFilter - }; + const s2 = - 2 * ppp + 3 * pp; + const s3 = ppp - pp; + const s0 = 1 - s2; + const s1 = s3 - pp + p; - var WEBGL_WRAPPINGS = { - 33071: ClampToEdgeWrapping, - 33648: MirroredRepeatWrapping, - 10497: RepeatWrapping - }; + // Layout of keyframe output values for CUBICSPLINE animations: + // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ] + for ( let i = 0; i !== stride; i ++ ) { - var WEBGL_TYPE_SIZES = { - 'SCALAR': 1, - 'VEC2': 2, - 'VEC3': 3, - 'VEC4': 4, - 'MAT2': 4, - 'MAT3': 9, - 'MAT4': 16 - }; + const p0 = values[ offset0 + i + stride ]; // splineVertex_k + const m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k) + const p1 = values[ offset1 + i + stride ]; // splineVertex_k+1 + const m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k) - var ATTRIBUTES = { - POSITION: 'position', - NORMAL: 'normal', - TANGENT: 'tangent', - TEXCOORD_0: 'uv', - TEXCOORD_1: 'uv2', - COLOR_0: 'color', - WEIGHTS_0: 'skinWeight', - JOINTS_0: 'skinIndex', - }; + result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1; - var PATH_PROPERTIES = { - scale: 'scale', - translation: 'position', - rotation: 'quaternion', - weights: 'morphTargetInfluences' - }; + } - var INTERPOLATION = { - CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each + return result; + +}; + +/*********************************/ +/********** INTERNALS ************/ +/*********************************/ + +/* CONSTANTS */ + +const WEBGL_CONSTANTS = { + FLOAT: 5126, + //FLOAT_MAT2: 35674, + FLOAT_MAT3: 35675, + FLOAT_MAT4: 35676, + FLOAT_VEC2: 35664, + FLOAT_VEC3: 35665, + FLOAT_VEC4: 35666, + LINEAR: 9729, + REPEAT: 10497, + SAMPLER_2D: 35678, + POINTS: 0, + LINES: 1, + LINE_LOOP: 2, + LINE_STRIP: 3, + TRIANGLES: 4, + TRIANGLE_STRIP: 5, + TRIANGLE_FAN: 6, + UNSIGNED_BYTE: 5121, + UNSIGNED_SHORT: 5123 +}; + +const WEBGL_COMPONENT_TYPES = { + 5120: Int8Array, + 5121: Uint8Array, + 5122: Int16Array, + 5123: Uint16Array, + 5125: Uint32Array, + 5126: Float32Array +}; + +const WEBGL_FILTERS = { + 9728: NearestFilter, + 9729: LinearFilter, + 9984: NearestMipmapNearestFilter, + 9985: LinearMipmapNearestFilter, + 9986: NearestMipmapLinearFilter, + 9987: LinearMipmapLinearFilter +}; + +const WEBGL_WRAPPINGS = { + 33071: ClampToEdgeWrapping, + 33648: MirroredRepeatWrapping, + 10497: RepeatWrapping +}; + +const WEBGL_TYPE_SIZES = { + 'SCALAR': 1, + 'VEC2': 2, + 'VEC3': 3, + 'VEC4': 4, + 'MAT2': 4, + 'MAT3': 9, + 'MAT4': 16 +}; + +const ATTRIBUTES = { + POSITION: 'position', + NORMAL: 'normal', + TANGENT: 'tangent', + TEXCOORD_0: 'uv', + TEXCOORD_1: 'uv2', + COLOR_0: 'color', + WEIGHTS_0: 'skinWeight', + JOINTS_0: 'skinIndex', +}; + +const PATH_PROPERTIES = { + scale: 'scale', + translation: 'position', + rotation: 'quaternion', + weights: 'morphTargetInfluences' +}; + +const INTERPOLATION = { + CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each // keyframe track will be initialized with a default interpolation type, then modified. - LINEAR: InterpolateLinear, - STEP: InterpolateDiscrete - }; + LINEAR: InterpolateLinear, + STEP: InterpolateDiscrete +}; - var ALPHA_MODES = { - OPAQUE: 'OPAQUE', - MASK: 'MASK', - BLEND: 'BLEND' - }; +const ALPHA_MODES = { + OPAQUE: 'OPAQUE', + MASK: 'MASK', + BLEND: 'BLEND' +}; - /* UTILITY FUNCTIONS */ +/* UTILITY FUNCTIONS */ - function resolveURL( url, path ) { +function resolveURL( url, path ) { - // Invalid URL - if ( typeof url !== 'string' || url === '' ) return ''; + // Invalid URL + if ( typeof url !== 'string' || url === '' ) return ''; - // Host Relative URL - if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { + // Host Relative URL + if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { - path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); + path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); - } + } - // Absolute URL http://,https://,// - if ( /^(https?:)?\/\//i.test( url ) ) return url; + // Absolute URL http://,https://,// + if ( /^(https?:)?\/\//i.test( url ) ) return url; - // Data URI - if ( /^data:.*,.*$/i.test( url ) ) return url; + // Data URI + if ( /^data:.*,.*$/i.test( url ) ) return url; - // Blob URL - if ( /^blob:.*$/i.test( url ) ) return url; + // Blob URL + if ( /^blob:.*$/i.test( url ) ) return url; - // Relative URL - return path + url; + // Relative URL + return path + url; - } +} - /** +/** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material */ - function createDefaultMaterial( cache ) { - - if ( cache[ 'DefaultMaterial' ] === undefined ) { - - cache[ 'DefaultMaterial' ] = new MeshStandardMaterial( { - color: 0xFFFFFF, - emissive: 0x000000, - metalness: 1, - roughness: 1, - transparent: false, - depthTest: true, - side: FrontSide - } ); - - } - - return cache[ 'DefaultMaterial' ]; +function createDefaultMaterial( cache ) { + + if ( cache[ 'DefaultMaterial' ] === undefined ) { + + cache[ 'DefaultMaterial' ] = new MeshStandardMaterial( { + color: 0xFFFFFF, + emissive: 0x000000, + metalness: 1, + roughness: 1, + transparent: false, + depthTest: true, + side: FrontSide + } ); } - function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) { + return cache[ 'DefaultMaterial' ]; - // Add unknown glTF extensions to an object's userData. +} - for ( var name in objectDef.extensions ) { +function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) { - if ( knownExtensions[ name ] === undefined ) { + // Add unknown glTF extensions to an object's userData. - object.userData.gltfExtensions = object.userData.gltfExtensions || {}; - object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ]; + for ( const name in objectDef.extensions ) { - } + if ( knownExtensions[ name ] === undefined ) { + + object.userData.gltfExtensions = object.userData.gltfExtensions || {}; + object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ]; } } - /** +} + +/** * @param {Object3D|Material|BufferGeometry} object * @param {GLTF.definition} gltfDef */ - function assignExtrasToUserData( object, gltfDef ) { - - if ( gltfDef.extras !== undefined ) { +function assignExtrasToUserData( object, gltfDef ) { - if ( typeof gltfDef.extras === 'object' ) { + if ( gltfDef.extras !== undefined ) { - Object.assign( object.userData, gltfDef.extras ); + if ( typeof gltfDef.extras === 'object' ) { - } else { + Object.assign( object.userData, gltfDef.extras ); - console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras ); + } else { - } + console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras ); } } - /** +} + +/** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets * * @param {BufferGeometry} geometry @@ -1725,159 +1769,187 @@ var GLTFLoader = ( function () { * @param {GLTFParser} parser * @return {Promise} */ - function addMorphTargets( geometry, targets, parser ) { - - var hasMorphPosition = false; - var hasMorphNormal = false; +function addMorphTargets( geometry, targets, parser ) { - for ( var i = 0, il = targets.length; i < il; i ++ ) { + let hasMorphPosition = false; + let hasMorphNormal = false; - var target = targets[ i ]; + for ( let i = 0, il = targets.length; i < il; i ++ ) { - if ( target.POSITION !== undefined ) hasMorphPosition = true; - if ( target.NORMAL !== undefined ) hasMorphNormal = true; + const target = targets[ i ]; - if ( hasMorphPosition && hasMorphNormal ) break; + if ( target.POSITION !== undefined ) hasMorphPosition = true; + if ( target.NORMAL !== undefined ) hasMorphNormal = true; - } + if ( hasMorphPosition && hasMorphNormal ) break; - if ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry ); + } - var pendingPositionAccessors = []; - var pendingNormalAccessors = []; + if ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry ); - for ( var i = 0, il = targets.length; i < il; i ++ ) { + const pendingPositionAccessors = []; + const pendingNormalAccessors = []; - var target = targets[ i ]; + for ( let i = 0, il = targets.length; i < il; i ++ ) { - if ( hasMorphPosition ) { + const target = targets[ i ]; - var pendingAccessor = target.POSITION !== undefined - ? parser.getDependency( 'accessor', target.POSITION ) - : geometry.attributes.position; + if ( hasMorphPosition ) { - pendingPositionAccessors.push( pendingAccessor ); + const pendingAccessor = target.POSITION !== undefined + ? parser.getDependency( 'accessor', target.POSITION ) + : geometry.attributes.position; - } + pendingPositionAccessors.push( pendingAccessor ); - if ( hasMorphNormal ) { + } - var pendingAccessor = target.NORMAL !== undefined - ? parser.getDependency( 'accessor', target.NORMAL ) - : geometry.attributes.normal; + if ( hasMorphNormal ) { - pendingNormalAccessors.push( pendingAccessor ); + const pendingAccessor = target.NORMAL !== undefined + ? parser.getDependency( 'accessor', target.NORMAL ) + : geometry.attributes.normal; - } + pendingNormalAccessors.push( pendingAccessor ); } - return Promise.all( [ - Promise.all( pendingPositionAccessors ), - Promise.all( pendingNormalAccessors ) - ] ).then( function ( accessors ) { + } - var morphPositions = accessors[ 0 ]; - var morphNormals = accessors[ 1 ]; + return Promise.all( [ + Promise.all( pendingPositionAccessors ), + Promise.all( pendingNormalAccessors ) + ] ).then( function ( accessors ) { - if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions; - if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals; - geometry.morphTargetsRelative = true; + const morphPositions = accessors[ 0 ]; + const morphNormals = accessors[ 1 ]; - return geometry; + if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions; + if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals; + geometry.morphTargetsRelative = true; - } ); + return geometry; - } + } ); - /** +} + +/** * @param {Mesh} mesh * @param {GLTF.Mesh} meshDef */ - function updateMorphTargets( mesh, meshDef ) { - - mesh.updateMorphTargets(); +function updateMorphTargets( mesh, meshDef ) { - if ( meshDef.weights !== undefined ) { + mesh.updateMorphTargets(); - for ( var i = 0, il = meshDef.weights.length; i < il; i ++ ) { + if ( meshDef.weights !== undefined ) { - mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ]; + for ( let i = 0, il = meshDef.weights.length; i < il; i ++ ) { - } + mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ]; } - // .extras has user-defined data, so check that .extras.targetNames is an array. - if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) { + } - var targetNames = meshDef.extras.targetNames; + // .extras has user-defined data, so check that .extras.targetNames is an array. + if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) { - if ( mesh.morphTargetInfluences.length === targetNames.length ) { + const targetNames = meshDef.extras.targetNames; - mesh.morphTargetDictionary = {}; + if ( mesh.morphTargetInfluences.length === targetNames.length ) { - for ( var i = 0, il = targetNames.length; i < il; i ++ ) { + mesh.morphTargetDictionary = {}; - mesh.morphTargetDictionary[ targetNames[ i ] ] = i; + for ( let i = 0, il = targetNames.length; i < il; i ++ ) { - } + mesh.morphTargetDictionary[ targetNames[ i ] ] = i; - } else { + } - console.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' ); + } else { - } + console.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' ); } } - function createPrimitiveKey( primitiveDef ) { +} + +function createPrimitiveKey( primitiveDef ) { - var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]; - var geometryKey; + const dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]; + let geometryKey; - if ( dracoExtension ) { + if ( dracoExtension ) { - geometryKey = 'draco:' + dracoExtension.bufferView + geometryKey = 'draco:' + dracoExtension.bufferView + ':' + dracoExtension.indices + ':' + createAttributesKey( dracoExtension.attributes ); - } else { + } else { - geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode; + geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode; - } + } + + return geometryKey; + +} + +function createAttributesKey( attributes ) { + + let attributesKey = ''; + + const keys = Object.keys( attributes ).sort(); - return geometryKey; + for ( let i = 0, il = keys.length; i < il; i ++ ) { + + attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';'; } - function createAttributesKey( attributes ) { + return attributesKey; - var attributesKey = ''; +} - var keys = Object.keys( attributes ).sort(); +function getNormalizedComponentScale( constructor ) { - for ( var i = 0, il = keys.length; i < il; i ++ ) { + // Reference: + // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data - attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';'; + switch ( constructor ) { - } + case Int8Array: + return 1 / 127; + + case Uint8Array: + return 1 / 255; + + case Int16Array: + return 1 / 32767; - return attributesKey; + case Uint16Array: + return 1 / 65535; + + default: + throw new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' ); } - /* GLTF PARSER */ +} + +/* GLTF PARSER */ - function GLTFParser( json, options ) { +class GLTFParser { - this.json = json || {}; + constructor( json = {}, options = {} ) { + + this.json = json; this.extensions = {}; this.plugins = {}; - this.options = options || {}; + this.options = options; // loader object cache this.cache = new GLTFRegistry(); @@ -1922,23 +1994,23 @@ var GLTFLoader = ( function () { } - GLTFParser.prototype.setExtensions = function ( extensions ) { + setExtensions( extensions ) { this.extensions = extensions; - }; + } - GLTFParser.prototype.setPlugins = function ( plugins ) { + setPlugins( plugins ) { this.plugins = plugins; - }; + } - GLTFParser.prototype.parse = function ( onLoad, onError ) { + parse( onLoad, onError ) { - var parser = this; - var json = this.json; - var extensions = this.extensions; + const parser = this; + const json = this.json; + const extensions = this.extensions; // Clear the loader cache this.cache.removeAll(); @@ -1966,7 +2038,7 @@ var GLTFLoader = ( function () { } ).then( function ( dependencies ) { - var result = { + const result = { scene: dependencies[ 0 ][ json.scene || 0 ], scenes: dependencies[ 0 ], animations: dependencies[ 1 ], @@ -1992,24 +2064,24 @@ var GLTFLoader = ( function () { } ).catch( onError ); - }; + } /** * Marks the special nodes/meshes in json for efficient parse. */ - GLTFParser.prototype._markDefs = function () { + _markDefs() { - var nodeDefs = this.json.nodes || []; - var skinDefs = this.json.skins || []; - var meshDefs = this.json.meshes || []; + const nodeDefs = this.json.nodes || []; + const skinDefs = this.json.skins || []; + const meshDefs = this.json.meshes || []; // Nothing in the node definition indicates whether it is a Bone or an // Object3D. Use the skins' joint references to mark bones. - for ( var skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) { + for ( let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) { - var joints = skinDefs[ skinIndex ].joints; + const joints = skinDefs[ skinIndex ].joints; - for ( var i = 0, il = joints.length; i < il; i ++ ) { + for ( let i = 0, il = joints.length; i < il; i ++ ) { nodeDefs[ joints[ i ] ].isBone = true; @@ -2019,9 +2091,9 @@ var GLTFLoader = ( function () { // Iterate over all nodes, marking references to shared resources, // as well as skeleton joints. - for ( var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) { + for ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) { - var nodeDef = nodeDefs[ nodeIndex ]; + const nodeDef = nodeDefs[ nodeIndex ]; if ( nodeDef.mesh !== undefined ) { @@ -2046,7 +2118,7 @@ var GLTFLoader = ( function () { } - }; + } /** * Counts references to shared node / Object3D resources. These resources @@ -2057,7 +2129,7 @@ var GLTFLoader = ( function () { * * Example: CesiumMilkTruck sample model reuses "Wheel" meshes. */ - GLTFParser.prototype._addNodeRef = function ( cache, index ) { + _addNodeRef( cache, index ) { if ( index === undefined ) return; @@ -2069,46 +2141,48 @@ var GLTFLoader = ( function () { cache.refs[ index ] ++; - }; + } /** Returns a reference to a shared resource, cloning it if necessary. */ - GLTFParser.prototype._getNodeRef = function ( cache, index, object ) { + _getNodeRef( cache, index, object ) { if ( cache.refs[ index ] <= 1 ) return object; - var ref = object.clone(); + const ref = object.clone(); ref.name += '_instance_' + ( cache.uses[ index ] ++ ); return ref; - }; + } - GLTFParser.prototype._invokeOne = function ( func ) { + _invokeOne( func ) { - var extensions = Object.values( this.plugins ); + const extensions = Object.values( this.plugins ); extensions.push( this ); - for ( var i = 0; i < extensions.length; i ++ ) { + for ( let i = 0; i < extensions.length; i ++ ) { - var result = func( extensions[ i ] ); + const result = func( extensions[ i ] ); if ( result ) return result; } - }; + return null; + + } - GLTFParser.prototype._invokeAll = function ( func ) { + _invokeAll( func ) { - var extensions = Object.values( this.plugins ); + const extensions = Object.values( this.plugins ); extensions.unshift( this ); - var pending = []; + const pending = []; - for ( var i = 0; i < extensions.length; i ++ ) { + for ( let i = 0; i < extensions.length; i ++ ) { - var result = func( extensions[ i ] ); + const result = func( extensions[ i ] ); if ( result ) pending.push( result ); @@ -2116,7 +2190,7 @@ var GLTFLoader = ( function () { return pending; - }; + } /** * Requests the specified dependency asynchronously, with caching. @@ -2124,10 +2198,10 @@ var GLTFLoader = ( function () { * @param {number} index * @return {Promise} */ - GLTFParser.prototype.getDependency = function ( type, index ) { + getDependency( type, index ) { - var cacheKey = type + ':' + index; - var dependency = this.cache.get( cacheKey ); + const cacheKey = type + ':' + index; + let dependency = this.cache.get( cacheKey ); if ( ! dependency ) { @@ -2204,21 +2278,21 @@ var GLTFLoader = ( function () { return dependency; - }; + } /** * Requests all dependencies of the specified type asynchronously, with caching. * @param {string} type * @return {Promise>} */ - GLTFParser.prototype.getDependencies = function ( type ) { + getDependencies( type ) { - var dependencies = this.cache.get( type ); + let dependencies = this.cache.get( type ); if ( ! dependencies ) { - var parser = this; - var defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || []; + const parser = this; + const defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || []; dependencies = Promise.all( defs.map( function ( def, index ) { @@ -2232,17 +2306,17 @@ var GLTFLoader = ( function () { return dependencies; - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views * @param {number} bufferIndex * @return {Promise} */ - GLTFParser.prototype.loadBuffer = function ( bufferIndex ) { + loadBuffer( bufferIndex ) { - var bufferDef = this.json.buffers[ bufferIndex ]; - var loader = this.fileLoader; + const bufferDef = this.json.buffers[ bufferIndex ]; + const loader = this.fileLoader; if ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) { @@ -2257,7 +2331,7 @@ var GLTFLoader = ( function () { } - var options = this.options; + const options = this.options; return new Promise( function ( resolve, reject ) { @@ -2269,38 +2343,38 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views * @param {number} bufferViewIndex * @return {Promise} */ - GLTFParser.prototype.loadBufferView = function ( bufferViewIndex ) { + loadBufferView( bufferViewIndex ) { - var bufferViewDef = this.json.bufferViews[ bufferViewIndex ]; + const bufferViewDef = this.json.bufferViews[ bufferViewIndex ]; return this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) { - var byteLength = bufferViewDef.byteLength || 0; - var byteOffset = bufferViewDef.byteOffset || 0; + const byteLength = bufferViewDef.byteLength || 0; + const byteOffset = bufferViewDef.byteOffset || 0; return buffer.slice( byteOffset, byteOffset + byteLength ); } ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors * @param {number} accessorIndex * @return {Promise} */ - GLTFParser.prototype.loadAccessor = function ( accessorIndex ) { + loadAccessor( accessorIndex ) { - var parser = this; - var json = this.json; + const parser = this; + const json = this.json; - var accessorDef = this.json.accessors[ accessorIndex ]; + const accessorDef = this.json.accessors[ accessorIndex ]; if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) { @@ -2311,7 +2385,7 @@ var GLTFLoader = ( function () { } - var pendingBufferViews = []; + const pendingBufferViews = []; if ( accessorDef.bufferView !== undefined ) { @@ -2332,27 +2406,27 @@ var GLTFLoader = ( function () { return Promise.all( pendingBufferViews ).then( function ( bufferViews ) { - var bufferView = bufferViews[ 0 ]; + const bufferView = bufferViews[ 0 ]; - var itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ]; - var TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ]; + const itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ]; + const TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ]; // For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12. - var elementBytes = TypedArray.BYTES_PER_ELEMENT; - var itemBytes = elementBytes * itemSize; - var byteOffset = accessorDef.byteOffset || 0; - var byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined; - var normalized = accessorDef.normalized === true; - var array, bufferAttribute; + const elementBytes = TypedArray.BYTES_PER_ELEMENT; + const itemBytes = elementBytes * itemSize; + const byteOffset = accessorDef.byteOffset || 0; + const byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined; + const normalized = accessorDef.normalized === true; + let array, bufferAttribute; // The buffer is not interleaved if the stride is the item size in bytes. if ( byteStride && byteStride !== itemBytes ) { // Each "slice" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer // This makes sure that IBA.count reflects accessor.count properly - var ibSlice = Math.floor( byteOffset / byteStride ); - var ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count; - var ib = parser.cache.get( ibCacheKey ); + const ibSlice = Math.floor( byteOffset / byteStride ); + const ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count; + let ib = parser.cache.get( ibCacheKey ); if ( ! ib ) { @@ -2386,14 +2460,14 @@ var GLTFLoader = ( function () { // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors if ( accessorDef.sparse !== undefined ) { - var itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR; - var TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ]; + const itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR; + const TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ]; - var byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0; - var byteOffsetValues = accessorDef.sparse.values.byteOffset || 0; + const byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0; + const byteOffsetValues = accessorDef.sparse.values.byteOffset || 0; - var sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices ); - var sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize ); + const sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices ); + const sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize ); if ( bufferView !== null ) { @@ -2402,9 +2476,9 @@ var GLTFLoader = ( function () { } - for ( var i = 0, il = sparseIndices.length; i < il; i ++ ) { + for ( let i = 0, il = sparseIndices.length; i < il; i ++ ) { - var index = sparseIndices[ i ]; + const index = sparseIndices[ i ]; bufferAttribute.setX( index, sparseValues[ i * itemSize ] ); if ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] ); @@ -2420,46 +2494,46 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures * @param {number} textureIndex * @return {Promise} */ - GLTFParser.prototype.loadTexture = function ( textureIndex ) { + loadTexture( textureIndex ) { - var json = this.json; - var options = this.options; - var textureDef = json.textures[ textureIndex ]; - var source = json.images[ textureDef.source ]; + const json = this.json; + const options = this.options; + const textureDef = json.textures[ textureIndex ]; + const source = json.images[ textureDef.source ]; - var loader = this.textureLoader; + let loader = this.textureLoader; if ( source.uri ) { - var handler = options.manager.getHandler( source.uri ); + const handler = options.manager.getHandler( source.uri ); if ( handler !== null ) loader = handler; } return this.loadTextureImage( textureIndex, source, loader ); - }; + } - GLTFParser.prototype.loadTextureImage = function ( textureIndex, source, loader ) { + loadTextureImage( textureIndex, source, loader ) { - var parser = this; - var json = this.json; - var options = this.options; + const parser = this; + const json = this.json; + const options = this.options; - var textureDef = json.textures[ textureIndex ]; + const textureDef = json.textures[ textureIndex ]; - var URL = self.URL || self.webkitURL; + const URL = self.URL || self.webkitURL; - var sourceURI = source.uri; - var isObjectURL = false; - var hasAlpha = true; + let sourceURI = source.uri; + let isObjectURL = false; + let hasAlpha = true; if ( source.mimeType === 'image/jpeg' ) hasAlpha = false; @@ -2477,13 +2551,13 @@ var GLTFLoader = ( function () { // sometimes contains alpha. // // https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header - var colorType = new DataView( bufferView, 25, 1 ).getUint8( 0, false ); + const colorType = new DataView( bufferView, 25, 1 ).getUint8( 0, false ); hasAlpha = colorType === 6 || colorType === 4 || colorType === 3; } isObjectURL = true; - var blob = new Blob( [ bufferView ], { type: source.mimeType } ); + const blob = new Blob( [ bufferView ], { type: source.mimeType } ); sourceURI = URL.createObjectURL( blob ); return sourceURI; @@ -2499,7 +2573,7 @@ var GLTFLoader = ( function () { return new Promise( function ( resolve, reject ) { - var onLoad = resolve; + let onLoad = resolve; if ( loader.isImageBitmapLoader === true ) { @@ -2532,8 +2606,8 @@ var GLTFLoader = ( function () { // When there is definitely no alpha channel in the texture, set RGBFormat to save space. if ( ! hasAlpha ) texture.format = RGBFormat; - var samplers = json.samplers || {}; - var sampler = samplers[ textureDef.sampler ] || {}; + const samplers = json.samplers || {}; + const sampler = samplers[ textureDef.sampler ] || {}; texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter; texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter; @@ -2549,7 +2623,7 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Asynchronously assigns a texture to the given material parameters. @@ -2558,9 +2632,9 @@ var GLTFLoader = ( function () { * @param {Object} mapDef * @return {Promise} */ - GLTFParser.prototype.assignTexture = function ( materialParams, mapName, mapDef ) { + assignTexture( materialParams, mapName, mapDef ) { - var parser = this; + const parser = this; return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) { @@ -2574,11 +2648,11 @@ var GLTFLoader = ( function () { if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) { - var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined; + const transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined; if ( transform ) { - var gltfReference = parser.associations.get( texture ); + const gltfReference = parser.associations.get( texture ); texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform ); parser.associations.set( texture, gltfReference ); @@ -2590,7 +2664,7 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Assigns final material to a Mesh, Line, or Points instance. The instance @@ -2600,23 +2674,23 @@ var GLTFLoader = ( function () { * be created if necessary, and reused from a cache. * @param {Object3D} mesh Mesh, Line, or Points instance. */ - GLTFParser.prototype.assignFinalMaterial = function ( mesh ) { + assignFinalMaterial( mesh ) { - var geometry = mesh.geometry; - var material = mesh.material; + const geometry = mesh.geometry; + let material = mesh.material; - var useVertexTangents = geometry.attributes.tangent !== undefined; - var useVertexColors = geometry.attributes.color !== undefined; - var useFlatShading = geometry.attributes.normal === undefined; - var useSkinning = mesh.isSkinnedMesh === true; - var useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0; - var useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined; + const useVertexTangents = geometry.attributes.tangent !== undefined; + const useVertexColors = geometry.attributes.color !== undefined; + const useFlatShading = geometry.attributes.normal === undefined; + const useSkinning = mesh.isSkinnedMesh === true; + const useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0; + const useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined; if ( mesh.isPoints ) { - var cacheKey = 'PointsMaterial:' + material.uuid; + const cacheKey = 'PointsMaterial:' + material.uuid; - var pointsMaterial = this.cache.get( cacheKey ); + let pointsMaterial = this.cache.get( cacheKey ); if ( ! pointsMaterial ) { @@ -2634,9 +2708,9 @@ var GLTFLoader = ( function () { } else if ( mesh.isLine ) { - var cacheKey = 'LineBasicMaterial:' + material.uuid; + const cacheKey = 'LineBasicMaterial:' + material.uuid; - var lineMaterial = this.cache.get( cacheKey ); + let lineMaterial = this.cache.get( cacheKey ); if ( ! lineMaterial ) { @@ -2655,7 +2729,7 @@ var GLTFLoader = ( function () { // Clone the material if it will be modified if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) { - var cacheKey = 'ClonedMaterial:' + material.uuid + ':'; + let cacheKey = 'ClonedMaterial:' + material.uuid + ':'; if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:'; if ( useSkinning ) cacheKey += 'skinning:'; @@ -2665,7 +2739,7 @@ var GLTFLoader = ( function () { if ( useMorphTargets ) cacheKey += 'morph-targets:'; if ( useMorphNormals ) cacheKey += 'morph-normals:'; - var cachedMaterial = this.cache.get( cacheKey ); + let cachedMaterial = this.cache.get( cacheKey ); if ( ! cachedMaterial ) { @@ -2707,41 +2781,41 @@ var GLTFLoader = ( function () { mesh.material = material; - }; + } - GLTFParser.prototype.getMaterialType = function ( /* materialIndex */ ) { + getMaterialType( /* materialIndex */ ) { return MeshStandardMaterial; - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials * @param {number} materialIndex * @return {Promise} */ - GLTFParser.prototype.loadMaterial = function ( materialIndex ) { + loadMaterial( materialIndex ) { - var parser = this; - var json = this.json; - var extensions = this.extensions; - var materialDef = json.materials[ materialIndex ]; + const parser = this; + const json = this.json; + const extensions = this.extensions; + const materialDef = json.materials[ materialIndex ]; - var materialType; - var materialParams = {}; - var materialExtensions = materialDef.extensions || {}; + let materialType; + const materialParams = {}; + const materialExtensions = materialDef.extensions || {}; - var pending = []; + const pending = []; if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) { - var sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ]; + const sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ]; materialType = sgExtension.getMaterialType(); pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) ); } else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) { - var kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ]; + const kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ]; materialType = kmuExtension.getMaterialType(); pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) ); @@ -2750,14 +2824,14 @@ var GLTFLoader = ( function () { // Specification: // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material - var metallicRoughness = materialDef.pbrMetallicRoughness || {}; + const metallicRoughness = materialDef.pbrMetallicRoughness || {}; materialParams.color = new Color( 1.0, 1.0, 1.0 ); materialParams.opacity = 1.0; if ( Array.isArray( metallicRoughness.baseColorFactor ) ) { - var array = metallicRoughness.baseColorFactor; + const array = metallicRoughness.baseColorFactor; materialParams.color.fromArray( array ); materialParams.opacity = array[ 3 ]; @@ -2800,7 +2874,7 @@ var GLTFLoader = ( function () { } - var alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE; + const alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE; if ( alphaMode === ALPHA_MODES.BLEND ) { @@ -2862,7 +2936,7 @@ var GLTFLoader = ( function () { return Promise.all( pending ).then( function () { - var material; + let material; if ( materialType === GLTFMeshStandardSGMaterial ) { @@ -2890,16 +2964,16 @@ var GLTFLoader = ( function () { } ); - }; + } /** When Object3D instances are targeted by animation, they need unique names. */ - GLTFParser.prototype.createUniqueName = function ( originalName ) { + createUniqueName( originalName ) { - var sanitizedName = PropertyBinding.sanitizeNodeName( originalName || '' ); + const sanitizedName = PropertyBinding.sanitizeNodeName( originalName || '' ); - var name = sanitizedName; + let name = sanitizedName; - for ( var i = 1; this.nodeNamesUsed[ name ]; ++ i ) { + for ( let i = 1; this.nodeNamesUsed[ name ]; ++ i ) { name = sanitizedName + '_' + i; @@ -2909,258 +2983,6 @@ var GLTFLoader = ( function () { return name; - }; - - /** - * @param {BufferGeometry} geometry - * @param {GLTF.Primitive} primitiveDef - * @param {GLTFParser} parser - */ - function computeBounds( geometry, primitiveDef, parser ) { - - var attributes = primitiveDef.attributes; - - var box = new Box3(); - - if ( attributes.POSITION !== undefined ) { - - var accessor = parser.json.accessors[ attributes.POSITION ]; - - var min = accessor.min; - var max = accessor.max; - - // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement. - - if ( min !== undefined && max !== undefined ) { - - box.set( - new Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ), - new Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) ); - - } else { - - console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' ); - - return; - - } - - } else { - - return; - - } - - var targets = primitiveDef.targets; - - if ( targets !== undefined ) { - - var maxDisplacement = new Vector3(); - var vector = new Vector3(); - - for ( var i = 0, il = targets.length; i < il; i ++ ) { - - var target = targets[ i ]; - - if ( target.POSITION !== undefined ) { - - var accessor = parser.json.accessors[ target.POSITION ]; - var min = accessor.min; - var max = accessor.max; - - // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement. - - if ( min !== undefined && max !== undefined ) { - - // we need to get max of absolute components because target weight is [-1,1] - vector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) ); - vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) ); - vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) ); - - // Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative - // to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets - // are used to implement key-frame animations and as such only two are active at a time - this results in very large - // boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size. - maxDisplacement.max( vector ); - - } else { - - console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' ); - - } - - } - - } - - // As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets. - box.expandByVector( maxDisplacement ); - - } - - geometry.boundingBox = box; - - var sphere = new Sphere(); - - box.getCenter( sphere.center ); - sphere.radius = box.min.distanceTo( box.max ) / 2; - - geometry.boundingSphere = sphere; - - } - - /** - * @param {BufferGeometry} geometry - * @param {GLTF.Primitive} primitiveDef - * @param {GLTFParser} parser - * @return {Promise} - */ - function addPrimitiveAttributes( geometry, primitiveDef, parser ) { - - var attributes = primitiveDef.attributes; - - var pending = []; - - function assignAttributeAccessor( accessorIndex, attributeName ) { - - return parser.getDependency( 'accessor', accessorIndex ) - .then( function ( accessor ) { - - geometry.setAttribute( attributeName, accessor ); - - } ); - - } - - for ( var gltfAttributeName in attributes ) { - - var threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase(); - - // Skip attributes already provided by e.g. Draco extension. - if ( threeAttributeName in geometry.attributes ) continue; - - pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) ); - - } - - if ( primitiveDef.indices !== undefined && ! geometry.index ) { - - var accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) { - - geometry.setIndex( accessor ); - - } ); - - pending.push( accessor ); - - } - - assignExtrasToUserData( geometry, primitiveDef ); - - computeBounds( geometry, primitiveDef, parser ); - - return Promise.all( pending ).then( function () { - - return primitiveDef.targets !== undefined - ? addMorphTargets( geometry, primitiveDef.targets, parser ) - : geometry; - - } ); - - } - - /** - * @param {BufferGeometry} geometry - * @param {Number} drawMode - * @return {BufferGeometry} - */ - function toTrianglesDrawMode( geometry, drawMode ) { - - var index = geometry.getIndex(); - - // generate index if not present - - if ( index === null ) { - - var indices = []; - - var position = geometry.getAttribute( 'position' ); - - if ( position !== undefined ) { - - for ( var i = 0; i < position.count; i ++ ) { - - indices.push( i ); - - } - - geometry.setIndex( indices ); - index = geometry.getIndex(); - - } else { - - console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' ); - return geometry; - - } - - } - - // - - var numberOfTriangles = index.count - 2; - var newIndices = []; - - if ( drawMode === TriangleFanDrawMode ) { - - // gl.TRIANGLE_FAN - - for ( var i = 1; i <= numberOfTriangles; i ++ ) { - - newIndices.push( index.getX( 0 ) ); - newIndices.push( index.getX( i ) ); - newIndices.push( index.getX( i + 1 ) ); - - } - - } else { - - // gl.TRIANGLE_STRIP - - for ( var i = 0; i < numberOfTriangles; i ++ ) { - - if ( i % 2 === 0 ) { - - newIndices.push( index.getX( i ) ); - newIndices.push( index.getX( i + 1 ) ); - newIndices.push( index.getX( i + 2 ) ); - - - } else { - - newIndices.push( index.getX( i + 2 ) ); - newIndices.push( index.getX( i + 1 ) ); - newIndices.push( index.getX( i ) ); - - } - - } - - } - - if ( ( newIndices.length / 3 ) !== numberOfTriangles ) { - - console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' ); - - } - - // build final geometry - - var newGeometry = geometry.clone(); - newGeometry.setIndex( newIndices ); - - return newGeometry; - } /** @@ -3171,11 +2993,11 @@ var GLTFLoader = ( function () { * @param {Array} primitives * @return {Promise>} */ - GLTFParser.prototype.loadGeometries = function ( primitives ) { + loadGeometries( primitives ) { - var parser = this; - var extensions = this.extensions; - var cache = this.primitiveCache; + const parser = this; + const extensions = this.extensions; + const cache = this.primitiveCache; function createDracoPrimitive( primitive ) { @@ -3189,15 +3011,15 @@ var GLTFLoader = ( function () { } - var pending = []; + const pending = []; - for ( var i = 0, il = primitives.length; i < il; i ++ ) { + for ( let i = 0, il = primitives.length; i < il; i ++ ) { - var primitive = primitives[ i ]; - var cacheKey = createPrimitiveKey( primitive ); + const primitive = primitives[ i ]; + const cacheKey = createPrimitiveKey( primitive ); // See if we've already created this geometry - var cached = cache[ cacheKey ]; + const cached = cache[ cacheKey ]; if ( cached ) { @@ -3206,7 +3028,7 @@ var GLTFLoader = ( function () { } else { - var geometryPromise; + let geometryPromise; if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) { @@ -3231,27 +3053,27 @@ var GLTFLoader = ( function () { return Promise.all( pending ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes * @param {number} meshIndex * @return {Promise} */ - GLTFParser.prototype.loadMesh = function ( meshIndex ) { + loadMesh( meshIndex ) { - var parser = this; - var json = this.json; - var extensions = this.extensions; + const parser = this; + const json = this.json; + const extensions = this.extensions; - var meshDef = json.meshes[ meshIndex ]; - var primitives = meshDef.primitives; + const meshDef = json.meshes[ meshIndex ]; + const primitives = meshDef.primitives; - var pending = []; + const pending = []; - for ( var i = 0, il = primitives.length; i < il; i ++ ) { + for ( let i = 0, il = primitives.length; i < il; i ++ ) { - var material = primitives[ i ].material === undefined + const material = primitives[ i ].material === undefined ? createDefaultMaterial( this.cache ) : this.getDependency( 'material', primitives[ i ].material ); @@ -3263,26 +3085,26 @@ var GLTFLoader = ( function () { return Promise.all( pending ).then( function ( results ) { - var materials = results.slice( 0, results.length - 1 ); - var geometries = results[ results.length - 1 ]; + const materials = results.slice( 0, results.length - 1 ); + const geometries = results[ results.length - 1 ]; - var meshes = []; + const meshes = []; - for ( var i = 0, il = geometries.length; i < il; i ++ ) { + for ( let i = 0, il = geometries.length; i < il; i ++ ) { - var geometry = geometries[ i ]; - var primitive = primitives[ i ]; + const geometry = geometries[ i ]; + const primitive = primitives[ i ]; // 1. create Mesh - var mesh; + let mesh; - var material = materials[ i ]; + const material = materials[ i ]; if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || - primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP || - primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN || - primitive.mode === undefined ) { + primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP || + primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN || + primitive.mode === undefined ) { // .isSkinnedMesh isn't in glTF spec. See ._markDefs() mesh = meshDef.isSkinnedMesh === true @@ -3353,9 +3175,9 @@ var GLTFLoader = ( function () { } - var group = new Group(); + const group = new Group(); - for ( var i = 0, il = meshes.length; i < il; i ++ ) { + for ( let i = 0, il = meshes.length; i < il; i ++ ) { group.add( meshes[ i ] ); @@ -3365,18 +3187,18 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras * @param {number} cameraIndex * @return {Promise} */ - GLTFParser.prototype.loadCamera = function ( cameraIndex ) { + loadCamera( cameraIndex ) { - var camera; - var cameraDef = this.json.cameras[ cameraIndex ]; - var params = cameraDef[ cameraDef.type ]; + let camera; + const cameraDef = this.json.cameras[ cameraIndex ]; + const params = cameraDef[ cameraDef.type ]; if ( ! params ) { @@ -3401,18 +3223,18 @@ var GLTFLoader = ( function () { return Promise.resolve( camera ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins * @param {number} skinIndex * @return {Promise} */ - GLTFParser.prototype.loadSkin = function ( skinIndex ) { + loadSkin( skinIndex ) { - var skinDef = this.json.skins[ skinIndex ]; + const skinDef = this.json.skins[ skinIndex ]; - var skinEntry = { joints: skinDef.joints }; + const skinEntry = { joints: skinDef.joints }; if ( skinDef.inverseBindMatrices === undefined ) { @@ -3428,33 +3250,33 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations * @param {number} animationIndex * @return {Promise} */ - GLTFParser.prototype.loadAnimation = function ( animationIndex ) { + loadAnimation( animationIndex ) { - var json = this.json; + const json = this.json; - var animationDef = json.animations[ animationIndex ]; + const animationDef = json.animations[ animationIndex ]; - var pendingNodes = []; - var pendingInputAccessors = []; - var pendingOutputAccessors = []; - var pendingSamplers = []; - var pendingTargets = []; + const pendingNodes = []; + const pendingInputAccessors = []; + const pendingOutputAccessors = []; + const pendingSamplers = []; + const pendingTargets = []; - for ( var i = 0, il = animationDef.channels.length; i < il; i ++ ) { + for ( let i = 0, il = animationDef.channels.length; i < il; i ++ ) { - var channel = animationDef.channels[ i ]; - var sampler = animationDef.samplers[ channel.sampler ]; - var target = channel.target; - var name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated. - var input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input; - var output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output; + const channel = animationDef.channels[ i ]; + const sampler = animationDef.samplers[ channel.sampler ]; + const target = channel.target; + const name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated. + const input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input; + const output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output; pendingNodes.push( this.getDependency( 'node', name ) ); pendingInputAccessors.push( this.getDependency( 'accessor', input ) ); @@ -3474,28 +3296,28 @@ var GLTFLoader = ( function () { ] ).then( function ( dependencies ) { - var nodes = dependencies[ 0 ]; - var inputAccessors = dependencies[ 1 ]; - var outputAccessors = dependencies[ 2 ]; - var samplers = dependencies[ 3 ]; - var targets = dependencies[ 4 ]; + const nodes = dependencies[ 0 ]; + const inputAccessors = dependencies[ 1 ]; + const outputAccessors = dependencies[ 2 ]; + const samplers = dependencies[ 3 ]; + const targets = dependencies[ 4 ]; - var tracks = []; + const tracks = []; - for ( var i = 0, il = nodes.length; i < il; i ++ ) { + for ( let i = 0, il = nodes.length; i < il; i ++ ) { - var node = nodes[ i ]; - var inputAccessor = inputAccessors[ i ]; - var outputAccessor = outputAccessors[ i ]; - var sampler = samplers[ i ]; - var target = targets[ i ]; + const node = nodes[ i ]; + const inputAccessor = inputAccessors[ i ]; + const outputAccessor = outputAccessors[ i ]; + const sampler = samplers[ i ]; + const target = targets[ i ]; if ( node === undefined ) continue; node.updateMatrix(); node.matrixAutoUpdate = true; - var TypedKeyframeTrack; + let TypedKeyframeTrack; switch ( PATH_PROPERTIES[ target.path ] ) { @@ -3518,11 +3340,11 @@ var GLTFLoader = ( function () { } - var targetName = node.name ? node.name : node.uuid; + const targetName = node.name ? node.name : node.uuid; - var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear; + const interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear; - var targetNames = []; + const targetNames = []; if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) { @@ -3543,37 +3365,14 @@ var GLTFLoader = ( function () { } - var outputArray = outputAccessor.array; + let outputArray = outputAccessor.array; if ( outputAccessor.normalized ) { - var scale; - - if ( outputArray.constructor === Int8Array ) { - - scale = 1 / 127; - - } else if ( outputArray.constructor === Uint8Array ) { + const scale = getNormalizedComponentScale( outputArray.constructor ); + const scaled = new Float32Array( outputArray.length ); - scale = 1 / 255; - - } else if ( outputArray.constructor == Int16Array ) { - - scale = 1 / 32767; - - } else if ( outputArray.constructor === Uint16Array ) { - - scale = 1 / 65535; - - } else { - - throw new Error( 'THREE.GLTFLoader: Unsupported output accessor component type.' ); - - } - - var scaled = new Float32Array( outputArray.length ); - - for ( var j = 0, jl = outputArray.length; j < jl; j ++ ) { + for ( let j = 0, jl = outputArray.length; j < jl; j ++ ) { scaled[ j ] = outputArray[ j ] * scale; @@ -3583,9 +3382,9 @@ var GLTFLoader = ( function () { } - for ( var j = 0, jl = targetNames.length; j < jl; j ++ ) { + for ( let j = 0, jl = targetNames.length; j < jl; j ++ ) { - var track = new TypedKeyframeTrack( + const track = new TypedKeyframeTrack( targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ], inputAccessor.array, outputArray, @@ -3616,60 +3415,78 @@ var GLTFLoader = ( function () { } - var name = animationDef.name ? animationDef.name : 'animation_' + animationIndex; + const name = animationDef.name ? animationDef.name : 'animation_' + animationIndex; return new AnimationClip( name, undefined, tracks ); } ); - }; + } - /** - * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy - * @param {number} nodeIndex - * @return {Promise} - */ - GLTFParser.prototype.loadNode = function ( nodeIndex ) { + createNodeMesh( nodeIndex ) { - var json = this.json; - var extensions = this.extensions; - var parser = this; + const json = this.json; + const parser = this; + const nodeDef = json.nodes[ nodeIndex ]; - var nodeDef = json.nodes[ nodeIndex ]; + if ( nodeDef.mesh === undefined ) return null; - // reserve node's name before its dependencies, so the root has the intended name. - var nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : ''; + return parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) { - return ( function () { + const node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh ); - var pending = []; + // if weights are provided on the node, override weights on the mesh. + if ( nodeDef.weights !== undefined ) { - if ( nodeDef.mesh !== undefined ) { + node.traverse( function ( o ) { - pending.push( parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) { + if ( ! o.isMesh ) return; - var node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh ); + for ( let i = 0, il = nodeDef.weights.length; i < il; i ++ ) { - // if weights are provided on the node, override weights on the mesh. - if ( nodeDef.weights !== undefined ) { + o.morphTargetInfluences[ i ] = nodeDef.weights[ i ]; - node.traverse( function ( o ) { + } - if ( ! o.isMesh ) return; + } ); - for ( var i = 0, il = nodeDef.weights.length; i < il; i ++ ) { + } - o.morphTargetInfluences[ i ] = nodeDef.weights[ i ]; + return node; - } + } ); - } ); + } - } + /** + * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy + * @param {number} nodeIndex + * @return {Promise} + */ + loadNode( nodeIndex ) { - return node; + const json = this.json; + const extensions = this.extensions; + const parser = this; - } ) ); + const nodeDef = json.nodes[ nodeIndex ]; + + // reserve node's name before its dependencies, so the root has the intended name. + const nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : ''; + + return ( function () { + + const pending = []; + + const meshPromise = parser._invokeOne( function ( ext ) { + + return ext.createNodeMesh && ext.createNodeMesh( nodeIndex ); + + } ); + + if ( meshPromise ) { + + pending.push( meshPromise ); } @@ -3697,7 +3514,7 @@ var GLTFLoader = ( function () { }() ).then( function ( objects ) { - var node; + let node; // .isBone isn't in glTF spec. See ._markDefs if ( nodeDef.isBone === true ) { @@ -3720,7 +3537,7 @@ var GLTFLoader = ( function () { if ( node !== objects[ 0 ] ) { - for ( var i = 0, il = objects.length; i < il; i ++ ) { + for ( let i = 0, il = objects.length; i < il; i ++ ) { node.add( objects[ i ] ); @@ -3741,7 +3558,7 @@ var GLTFLoader = ( function () { if ( nodeDef.matrix !== undefined ) { - var matrix = new Matrix4(); + const matrix = new Matrix4(); matrix.fromArray( nodeDef.matrix ); node.applyMatrix4( matrix ); @@ -3773,151 +3590,412 @@ var GLTFLoader = ( function () { } ); - }; + } /** * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes * @param {number} sceneIndex * @return {Promise} */ - GLTFParser.prototype.loadScene = function () { + loadScene( sceneIndex ) { + + const json = this.json; + const extensions = this.extensions; + const sceneDef = this.json.scenes[ sceneIndex ]; + const parser = this; + + // Loader returns Group, not Scene. + // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172 + const scene = new Group(); + if ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name ); - // scene node hierachy builder + assignExtrasToUserData( scene, sceneDef ); - function buildNodeHierachy( nodeId, parentObject, json, parser ) { + if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef ); - var nodeDef = json.nodes[ nodeId ]; + const nodeIds = sceneDef.nodes || []; - return parser.getDependency( 'node', nodeId ).then( function ( node ) { + const pending = []; - if ( nodeDef.skin === undefined ) return node; + for ( let i = 0, il = nodeIds.length; i < il; i ++ ) { - // build skeleton here as well + pending.push( buildNodeHierachy( nodeIds[ i ], scene, json, parser ) ); - var skinEntry; + } + + return Promise.all( pending ).then( function () { - return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) { + return scene; - skinEntry = skin; + } ); - var pendingJoints = []; + } - for ( var i = 0, il = skinEntry.joints.length; i < il; i ++ ) { +} - pendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) ); +function buildNodeHierachy( nodeId, parentObject, json, parser ) { - } + const nodeDef = json.nodes[ nodeId ]; - return Promise.all( pendingJoints ); + return parser.getDependency( 'node', nodeId ).then( function ( node ) { - } ).then( function ( jointNodes ) { + if ( nodeDef.skin === undefined ) return node; - node.traverse( function ( mesh ) { + // build skeleton here as well - if ( ! mesh.isMesh ) return; + let skinEntry; - var bones = []; - var boneInverses = []; + return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) { - for ( var j = 0, jl = jointNodes.length; j < jl; j ++ ) { + skinEntry = skin; - var jointNode = jointNodes[ j ]; + const pendingJoints = []; - if ( jointNode ) { + for ( let i = 0, il = skinEntry.joints.length; i < il; i ++ ) { - bones.push( jointNode ); + pendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) ); - var mat = new Matrix4(); + } + + return Promise.all( pendingJoints ); + + } ).then( function ( jointNodes ) { + + node.traverse( function ( mesh ) { - if ( skinEntry.inverseBindMatrices !== undefined ) { + if ( ! mesh.isMesh ) return; - mat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 ); + const bones = []; + const boneInverses = []; - } + for ( let j = 0, jl = jointNodes.length; j < jl; j ++ ) { - boneInverses.push( mat ); + const jointNode = jointNodes[ j ]; - } else { + if ( jointNode ) { - console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[ j ] ); + bones.push( jointNode ); - } + const mat = new Matrix4(); + + if ( skinEntry.inverseBindMatrices !== undefined ) { + + mat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 ); } - mesh.bind( new Skeleton( bones, boneInverses ), mesh.matrixWorld ); + boneInverses.push( mat ); - } ); + } else { - return node; + console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[ j ] ); - } ); + } + + } + + mesh.bind( new Skeleton( bones, boneInverses ), mesh.matrixWorld ); + + } ); + + return node; + + } ); + + } ).then( function ( node ) { + + // build node hierachy + + parentObject.add( node ); + + const pending = []; + + if ( nodeDef.children ) { + + const children = nodeDef.children; + + for ( let i = 0, il = children.length; i < il; i ++ ) { + + const child = children[ i ]; + pending.push( buildNodeHierachy( child, node, json, parser ) ); + + } + + } + + return Promise.all( pending ); + + } ); + +} + +/** + * @param {BufferGeometry} geometry + * @param {GLTF.Primitive} primitiveDef + * @param {GLTFParser} parser + */ +function computeBounds( geometry, primitiveDef, parser ) { + + const attributes = primitiveDef.attributes; + + const box = new Box3(); + + if ( attributes.POSITION !== undefined ) { + + const accessor = parser.json.accessors[ attributes.POSITION ]; + + const min = accessor.min; + const max = accessor.max; + + // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement. + + if ( min !== undefined && max !== undefined ) { + + box.set( + new Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ), + new Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) + ); + + if ( accessor.normalized ) { + + const boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] ); + box.min.multiplyScalar( boxScale ); + box.max.multiplyScalar( boxScale ); + + } + + } else { + + console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' ); + + return; + + } + + } else { + + return; + + } + + const targets = primitiveDef.targets; - } ).then( function ( node ) { + if ( targets !== undefined ) { - // build node hierachy + const maxDisplacement = new Vector3(); + const vector = new Vector3(); - parentObject.add( node ); + for ( let i = 0, il = targets.length; i < il; i ++ ) { - var pending = []; + const target = targets[ i ]; - if ( nodeDef.children ) { + if ( target.POSITION !== undefined ) { - var children = nodeDef.children; + const accessor = parser.json.accessors[ target.POSITION ]; + const min = accessor.min; + const max = accessor.max; - for ( var i = 0, il = children.length; i < il; i ++ ) { + // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement. - var child = children[ i ]; - pending.push( buildNodeHierachy( child, node, json, parser ) ); + if ( min !== undefined && max !== undefined ) { + + // we need to get max of absolute components because target weight is [-1,1] + vector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) ); + vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) ); + vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) ); + + + if ( accessor.normalized ) { + + const boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] ); + vector.multiplyScalar( boxScale ); } + // Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative + // to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets + // are used to implement key-frame animations and as such only two are active at a time - this results in very large + // boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size. + maxDisplacement.max( vector ); + + } else { + + console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' ); + } - return Promise.all( pending ); + } + + } + + // As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets. + box.expandByVector( maxDisplacement ); + + } + + geometry.boundingBox = box; + + const sphere = new Sphere(); + + box.getCenter( sphere.center ); + sphere.radius = box.min.distanceTo( box.max ) / 2; + + geometry.boundingSphere = sphere; + +} + +/** + * @param {BufferGeometry} geometry + * @param {GLTF.Primitive} primitiveDef + * @param {GLTFParser} parser + * @return {Promise} + */ +function addPrimitiveAttributes( geometry, primitiveDef, parser ) { + + const attributes = primitiveDef.attributes; + + const pending = []; + + function assignAttributeAccessor( accessorIndex, attributeName ) { + + return parser.getDependency( 'accessor', accessorIndex ) + .then( function ( accessor ) { + + geometry.setAttribute( attributeName, accessor ); } ); + } + + for ( const gltfAttributeName in attributes ) { + + const threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase(); + + // Skip attributes already provided by e.g. Draco extension. + if ( threeAttributeName in geometry.attributes ) continue; + + pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) ); + + } + + if ( primitiveDef.indices !== undefined && ! geometry.index ) { + + const accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) { + + geometry.setIndex( accessor ); + + } ); + + pending.push( accessor ); + + } + + assignExtrasToUserData( geometry, primitiveDef ); + + computeBounds( geometry, primitiveDef, parser ); + + return Promise.all( pending ).then( function () { + + return primitiveDef.targets !== undefined + ? addMorphTargets( geometry, primitiveDef.targets, parser ) + : geometry; + + } ); + +} + +/** + * @param {BufferGeometry} geometry + * @param {Number} drawMode + * @return {BufferGeometry} + */ +function toTrianglesDrawMode( geometry, drawMode ) { + + let index = geometry.getIndex(); + + // generate index if not present + + if ( index === null ) { + + const indices = []; + + const position = geometry.getAttribute( 'position' ); + + if ( position !== undefined ) { + + for ( let i = 0; i < position.count; i ++ ) { + + indices.push( i ); + + } + + geometry.setIndex( indices ); + index = geometry.getIndex(); + + } else { + + console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' ); + return geometry; + } - return function loadScene( sceneIndex ) { + } + + // + + const numberOfTriangles = index.count - 2; + const newIndices = []; + + if ( drawMode === TriangleFanDrawMode ) { + + // gl.TRIANGLE_FAN + + for ( let i = 1; i <= numberOfTriangles; i ++ ) { + + newIndices.push( index.getX( 0 ) ); + newIndices.push( index.getX( i ) ); + newIndices.push( index.getX( i + 1 ) ); + + } - var json = this.json; - var extensions = this.extensions; - var sceneDef = this.json.scenes[ sceneIndex ]; - var parser = this; + } else { - // Loader returns Group, not Scene. - // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172 - var scene = new Group(); - if ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name ); + // gl.TRIANGLE_STRIP - assignExtrasToUserData( scene, sceneDef ); + for ( let i = 0; i < numberOfTriangles; i ++ ) { - if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef ); + if ( i % 2 === 0 ) { - var nodeIds = sceneDef.nodes || []; + newIndices.push( index.getX( i ) ); + newIndices.push( index.getX( i + 1 ) ); + newIndices.push( index.getX( i + 2 ) ); - var pending = []; - for ( var i = 0, il = nodeIds.length; i < il; i ++ ) { + } else { - pending.push( buildNodeHierachy( nodeIds[ i ], scene, json, parser ) ); + newIndices.push( index.getX( i + 2 ) ); + newIndices.push( index.getX( i + 1 ) ); + newIndices.push( index.getX( i ) ); } - return Promise.all( pending ).then( function () { + } + + } - return scene; + if ( ( newIndices.length / 3 ) !== numberOfTriangles ) { - } ); + console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' ); - }; + } + + // build final geometry - }(); + const newGeometry = geometry.clone(); + newGeometry.setIndex( newIndices ); - return GLTFLoader; + return newGeometry; -} )(); +} export { GLTFLoader }; diff --git a/examples/jsm/loaders/HDRCubeTextureLoader.js b/examples/jsm/loaders/HDRCubeTextureLoader.js index d8e02d35d47dee..47a882c354d63f 100644 --- a/examples/jsm/loaders/HDRCubeTextureLoader.js +++ b/examples/jsm/loaders/HDRCubeTextureLoader.js @@ -15,20 +15,18 @@ import { } from '../../../build/three.module.js'; import { RGBELoader } from '../loaders/RGBELoader.js'; -var HDRCubeTextureLoader = function ( manager ) { +class HDRCubeTextureLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.hdrLoader = new RGBELoader(); - this.type = UnsignedByteType; + super( manager ); -}; + this.hdrLoader = new RGBELoader(); + this.type = UnsignedByteType; -HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: HDRCubeTextureLoader, + } - load: function ( urls, onLoad, onProgress, onError ) { + load( urls, onLoad, onProgress, onError ) { if ( ! Array.isArray( urls ) ) { @@ -43,7 +41,7 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype } - var texture = new CubeTexture(); + const texture = new CubeTexture(); texture.type = this.type; @@ -78,9 +76,9 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype } - var scope = this; + const scope = this; - var loaded = 0; + let loaded = 0; function loadHDRData( i, onLoad, onProgress, onError ) { @@ -92,13 +90,13 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype loaded ++; - var texData = scope.hdrLoader.parse( buffer ); + const texData = scope.hdrLoader.parse( buffer ); if ( ! texData ) return; if ( texData.data !== undefined ) { - var dataTexture = new DataTexture( texData.data, texData.width, texData.height ); + const dataTexture = new DataTexture( texData.data, texData.width, texData.height ); dataTexture.type = texture.type; dataTexture.encoding = texture.encoding; @@ -122,7 +120,7 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype } - for ( var i = 0; i < urls.length; i ++ ) { + for ( let i = 0; i < urls.length; i ++ ) { loadHDRData( i, onLoad, onProgress, onError ); @@ -130,9 +128,9 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype return texture; - }, + } - setDataType: function ( value ) { + setDataType( value ) { this.type = value; this.hdrLoader.setDataType( value ); @@ -141,6 +139,6 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype } -} ); +} export { HDRCubeTextureLoader }; diff --git a/examples/jsm/loaders/IFCLoader.js b/examples/jsm/loaders/IFCLoader.js index 46d353221fe5ad..6b2fe4d00eeb3a 100644 --- a/examples/jsm/loaders/IFCLoader.js +++ b/examples/jsm/loaders/IFCLoader.js @@ -14,25 +14,23 @@ import { InterleavedBuffer, InterleavedBufferAttribute, BufferAttribute, -} from '../../../../build/three.module.js'; +} from '../../../build/three.module.js'; -var ifcAPI = new IfcAPI(); +const ifcAPI = new IfcAPI(); -function IFCLoader( manager ) { +class IFCLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -} + super( manager ); -IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: IFCLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -66,9 +64,9 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { onError ); - }, + } - parse: async function ( buffer ) { + async parse( buffer ) { if ( ifcAPI.wasmModule === undefined ) { @@ -76,18 +74,18 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var data = new Uint8Array( buffer ); - var modelID = ifcAPI.OpenModel( 'example.ifc', data ); + const data = new Uint8Array( buffer ); + const modelID = ifcAPI.OpenModel( 'example.ifc', data ); return loadAllGeometry( modelID ); function loadAllGeometry( modelID ) { - var flatMeshes = getFlatMeshes( modelID ); - var mainObject = new Object3D(); - for ( var i = 0; i < flatMeshes.size(); i ++ ) { + const flatMeshes = getFlatMeshes( modelID ); + const mainObject = new Object3D(); + for ( let i = 0; i < flatMeshes.size(); i ++ ) { - var placedGeometries = flatMeshes.get( i ).geometries; - for ( var j = 0; j < placedGeometries.size(); j ++ ) + const placedGeometries = flatMeshes.get( i ).geometries; + for ( let j = 0; j < placedGeometries.size(); j ++ ) mainObject.add( getPlacedGeometry( modelID, placedGeometries.get( j ) ) ); } @@ -98,16 +96,16 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getFlatMeshes( modelID ) { - var flatMeshes = ifcAPI.LoadAllGeometry( modelID ); + const flatMeshes = ifcAPI.LoadAllGeometry( modelID ); return flatMeshes; } function getPlacedGeometry( modelID, placedGeometry ) { - var geometry = getBufferGeometry( modelID, placedGeometry ); - var material = getMeshMaterial( placedGeometry.color ); - var mesh = new Mesh( geometry, material ); + const geometry = getBufferGeometry( modelID, placedGeometry ); + const material = getMeshMaterial( placedGeometry.color ); + const mesh = new Mesh( geometry, material ); mesh.matrix = getMeshMatrix( placedGeometry.flatTransformation ); mesh.matrixAutoUpdate = false; return mesh; @@ -116,27 +114,27 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getBufferGeometry( modelID, placedGeometry ) { - var geometry = ifcAPI.GetGeometry( + const geometry = ifcAPI.GetGeometry( modelID, placedGeometry.geometryExpressID ); - var verts = ifcAPI.GetVertexArray( + const verts = ifcAPI.GetVertexArray( geometry.GetVertexData(), geometry.GetVertexDataSize() ); - var indices = ifcAPI.GetIndexArray( + const indices = ifcAPI.GetIndexArray( geometry.GetIndexData(), geometry.GetIndexDataSize() ); - var bufferGeometry = ifcGeometryToBuffer( verts, indices ); + const bufferGeometry = ifcGeometryToBuffer( verts, indices ); return bufferGeometry; } function getMeshMaterial( color ) { - var col = new Color( color.x, color.y, color.z ); - var material = new MeshPhongMaterial( { color: col, side: DoubleSide } ); + const col = new Color( color.x, color.y, color.z ); + const material = new MeshPhongMaterial( { color: col, side: DoubleSide } ); material.transparent = color.w !== 1; if ( material.transparent ) material.opacity = color.w; return material; @@ -145,7 +143,7 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getMeshMatrix( matrix ) { - var mat = new Matrix4(); + const mat = new Matrix4(); mat.fromArray( matrix ); // mat.elements[15 - 3] *= 0.001; // mat.elements[15 - 2] *= 0.001; @@ -156,8 +154,8 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function ifcGeometryToBuffer( vertexData, indexData ) { - var geometry = new BufferGeometry(); - var buffer32 = new InterleavedBuffer( vertexData, 6 ); + const geometry = new BufferGeometry(); + const buffer32 = new InterleavedBuffer( vertexData, 6 ); geometry.setAttribute( 'position', new InterleavedBufferAttribute( buffer32, 3, 0 ) @@ -172,6 +170,10 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } } -} ); + + setWasmPath(path){ + ifcAPI.SetWasmPath(path); + } +}; export { IFCLoader }; diff --git a/examples/jsm/loaders/KMZLoader.js b/examples/jsm/loaders/KMZLoader.js index 0237c06c7dbf05..0f451422c5a8e2 100644 --- a/examples/jsm/loaders/KMZLoader.js +++ b/examples/jsm/loaders/KMZLoader.js @@ -5,23 +5,21 @@ import { LoadingManager } from '../../../build/three.module.js'; import { ColladaLoader } from '../loaders/ColladaLoader.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; -var KMZLoader = function ( manager ) { +class KMZLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: KMZLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -50,13 +48,13 @@ KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { function findFile( url ) { - for ( var path in zip ) { + for ( const path in zip ) { if ( path.substr( - url.length ) === url ) { @@ -68,16 +66,16 @@ KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var manager = new LoadingManager(); + const manager = new LoadingManager(); manager.setURLModifier( function ( url ) { - var image = findFile( url ); + const image = findFile( url ); if ( image ) { console.log( 'Loading', url ); - var blob = new Blob( [ image.buffer ], { type: 'application/octet-stream' } ); + const blob = new Blob( [ image.buffer ], { type: 'application/octet-stream' } ); return URL.createObjectURL( blob ); } @@ -88,17 +86,17 @@ KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var zip = fflate.unzipSync( new Uint8Array( data ) ); // eslint-disable-line no-undef + const zip = fflate.unzipSync( new Uint8Array( data ) ); // eslint-disable-line no-undef if ( zip[ 'doc.kml' ] ) { - var xml = new DOMParser().parseFromString( fflate.strFromU8( zip[ 'doc.kml' ] ), 'application/xml' ); // eslint-disable-line no-undef + const xml = new DOMParser().parseFromString( fflate.strFromU8( zip[ 'doc.kml' ] ), 'application/xml' ); // eslint-disable-line no-undef - var model = xml.querySelector( 'Placemark Model Link href' ); + const model = xml.querySelector( 'Placemark Model Link href' ); if ( model ) { - var loader = new ColladaLoader( manager ); + const loader = new ColladaLoader( manager ); return loader.parse( fflate.strFromU8( zip[ model.textContent ] ) ); // eslint-disable-line no-undef } @@ -107,13 +105,13 @@ KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { console.warn( 'KMZLoader: Missing doc.kml file.' ); - for ( var path in zip ) { + for ( const path in zip ) { - var extension = path.split( '.' ).pop().toLowerCase(); + const extension = path.split( '.' ).pop().toLowerCase(); if ( extension === 'dae' ) { - var loader = new ColladaLoader( manager ); + const loader = new ColladaLoader( manager ); return loader.parse( fflate.strFromU8( zip[ path ] ) ); // eslint-disable-line no-undef } @@ -127,6 +125,6 @@ KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { KMZLoader }; diff --git a/examples/jsm/loaders/KTX2Loader.js b/examples/jsm/loaders/KTX2Loader.js index b8d71b26f68948..fd7dbddd30e012 100644 --- a/examples/jsm/loaders/KTX2Loader.js +++ b/examples/jsm/loaders/KTX2Loader.js @@ -21,42 +21,17 @@ import { LinearEncoding, sRGBEncoding, } from '../../../build/three.module.js'; - +import { + read as readKTX, + KTX2ChannelETC1S, + KTX2ChannelUASTC, + KTX2Flags, + KTX2Model, + KTX2SupercompressionScheme, + KTX2Transfer +} from '../libs/ktx-parse.module.js'; import { BasisTextureLoader } from './BasisTextureLoader.js'; import { ZSTDDecoder } from '../libs/zstddec.module.js'; -import { read as readKTX } from '../libs/ktx-parse.module.js'; - -// KTX 2.0 constants. - -var DFDModel = { - ETC1S: 163, - UASTC: 166, -}; - -var DFDChannel = { - ETC1S: { - RGB: 0, - RRR: 3, - GGG: 4, - AAA: 15, - }, - UASTC: { - RGB: 0, - RGBA: 3, - RRR: 4, - RRRG: 5 - }, -}; - -var SupercompressionScheme = { - ZSTD: 2 -}; - -var Transfer = { - SRGB: 2 -}; - -// class KTX2Loader extends CompressedTextureLoader { @@ -176,7 +151,7 @@ class KTX2Loader extends CompressedTextureLoader { KTX2Utils.createLevels( ktx, this.zstd ).then( function ( levels ) { - var basisFormat = dfd.colorModel === DFDModel.UASTC + var basisFormat = dfd.colorModel === KTX2Model.UASTC ? BasisTextureLoader.BasisFormat.UASTC_4x4 : BasisTextureLoader.BasisFormat.ETC1S; @@ -200,7 +175,7 @@ class KTX2Loader extends CompressedTextureLoader { } ).then( function ( texture ) { - texture.encoding = dfd.transferFunction === Transfer.SRGB + texture.encoding = dfd.transferFunction === KTX2Transfer.SRGB ? sRGBEncoding : LinearEncoding; texture.premultiplyAlpha = KTX2Utils.getPremultiplyAlpha( ktx ); @@ -219,7 +194,7 @@ var KTX2Utils = { createLevels: async function ( ktx, zstd ) { - if ( ktx.supercompressionScheme === SupercompressionScheme.ZSTD ) { + if ( ktx.supercompressionScheme === KTX2SupercompressionScheme.ZSTD ) { await zstd.init(); @@ -235,7 +210,7 @@ var KTX2Utils = { var levelHeight = Math.max( 1, Math.floor( height / Math.pow( 2, levelIndex ) ) ); var levelData = ktx.levels[ levelIndex ].levelData; - if ( ktx.supercompressionScheme === SupercompressionScheme.ZSTD ) { + if ( ktx.supercompressionScheme === KTX2SupercompressionScheme.ZSTD ) { levelData = zstd.decode( levelData, ktx.levels[ levelIndex ].uncompressedByteLength ); @@ -269,9 +244,9 @@ var KTX2Utils = { // UASTC - if ( dfd.colorModel === DFDModel.UASTC ) { + if ( dfd.colorModel === KTX2Model.UASTC ) { - if ( ( dfd.samples[ 0 ].channelID & 0xF ) === DFDChannel.UASTC.RGBA ) { + if ( ( dfd.samples[ 0 ].channelID & 0xF ) === KTX2ChannelUASTC.RGBA ) { return true; @@ -284,7 +259,7 @@ var KTX2Utils = { // ETC1S if ( dfd.samples.length === 2 - && ( dfd.samples[ 1 ].channelID & 0xF ) === DFDChannel.ETC1S.AAA ) { + && ( dfd.samples[ 1 ].channelID & 0xF ) === KTX2ChannelETC1S.AAA ) { return true; @@ -298,7 +273,7 @@ var KTX2Utils = { var dfd = this.getBasicDFD( ktx ); - return !! ( dfd.flags & 1 /* KHR_DF_FLAG_ALPHA_PREMULTIPLIED */ ); + return !! ( dfd.flags & KTX2Flags.ALPHA_PREMULTIPLIED ); }, diff --git a/examples/jsm/loaders/KTXLoader.js b/examples/jsm/loaders/KTXLoader.js index ea929a34c5b15e..f0bcd2773073ba 100644 --- a/examples/jsm/loaders/KTXLoader.js +++ b/examples/jsm/loaders/KTXLoader.js @@ -10,19 +10,17 @@ import { */ -var KTXLoader = function ( manager ) { +class KTXLoader extends CompressedTextureLoader { - CompressedTextureLoader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -KTXLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), { - - constructor: KTXLoader, + } - parse: function ( buffer, loadMipmaps ) { + parse( buffer, loadMipmaps ) { - var ktx = new KhronosTextureContainer( buffer, 1 ); + const ktx = new KhronosTextureContainer( buffer, 1 ); return { mipmaps: ktx.mipmaps( loadMipmaps ), @@ -35,9 +33,17 @@ KTXLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot } -} ); +} + + +const HEADER_LEN = 12 + ( 13 * 4 ); // identifier + header elements (not including key value meta-data pairs) +// load types +const COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D() +//const COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D() +//const TEX_2D = 2; // uses a gl.texImage2D() +//const TEX_3D = 3; // uses a gl.texImage3D() -var KhronosTextureContainer = ( function () { +class KhronosTextureContainer { /** * @param {ArrayBuffer} arrayBuffer- contents of the KTX container file @@ -45,14 +51,14 @@ var KhronosTextureContainer = ( function () { * @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented * @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented */ - function KhronosTextureContainer( arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */ ) { + constructor( arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */ ) { this.arrayBuffer = arrayBuffer; // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is: // '´', 'K', 'T', 'X', ' ', '1', '1', 'ª', '\r', '\n', '\x1A', '\n' // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A - var identifier = new Uint8Array( this.arrayBuffer, 0, 12 ); + const identifier = new Uint8Array( this.arrayBuffer, 0, 12 ); if ( identifier[ 0 ] !== 0xAB || identifier[ 1 ] !== 0x4B || identifier[ 2 ] !== 0x54 || @@ -72,10 +78,10 @@ var KhronosTextureContainer = ( function () { } // load the reset of the header in native 32 bit uint - var dataSize = Uint32Array.BYTES_PER_ELEMENT; - var headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize ); - var endianness = headerDataView.getUint32( 0, true ); - var littleEndian = endianness === 0x04030201; + const dataSize = Uint32Array.BYTES_PER_ELEMENT; + const headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize ); + const endianness = headerDataView.getUint32( 0, true ); + const littleEndian = endianness === 0x04030201; this.glType = headerDataView.getUint32( 1 * dataSize, littleEndian ); // must be 0 for compressed textures this.glTypeSize = headerDataView.getUint32( 2 * dataSize, littleEndian ); // must be 1 for compressed textures @@ -126,29 +132,28 @@ var KhronosTextureContainer = ( function () { // we now have a completely validated file, so could use existence of loadType as success // would need to make this more elaborate & adjust checks above to support more than one load type - this.loadType = KhronosTextureContainer.COMPRESSED_2D; + this.loadType = COMPRESSED_2D; } - // return mipmaps for js - KhronosTextureContainer.prototype.mipmaps = function ( loadMipmaps ) { + mipmaps( loadMipmaps ) { - var mipmaps = []; + const mipmaps = []; // initialize width & height for level 1 - var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData; - var width = this.pixelWidth; - var height = this.pixelHeight; - var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1; + let dataOffset = HEADER_LEN + this.bytesOfKeyValueData; + let width = this.pixelWidth; + let height = this.pixelHeight; + const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1; - for ( var level = 0; level < mipmapCount; level ++ ) { + for ( let level = 0; level < mipmapCount; level ++ ) { - var imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps + const imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps dataOffset += 4; // size of the image + 4 for the imageSize field - for ( var face = 0; face < this.numberOfFaces; face ++ ) { + for ( let face = 0; face < this.numberOfFaces; face ++ ) { - var byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize ); + const byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize ); mipmaps.push( { 'data': byteArray, 'width': width, 'height': height } ); @@ -164,17 +169,8 @@ var KhronosTextureContainer = ( function () { return mipmaps; - }; - - KhronosTextureContainer.HEADER_LEN = 12 + ( 13 * 4 ); // identifier + header elements (not including key value meta-data pairs) - // load types - KhronosTextureContainer.COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D() - KhronosTextureContainer.COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D() - KhronosTextureContainer.TEX_2D = 2; // uses a gl.texImage2D() - KhronosTextureContainer.TEX_3D = 3; // uses a gl.texImage3D() - - return KhronosTextureContainer; + } -}() ); +} export { KTXLoader }; diff --git a/examples/jsm/loaders/LDrawLoader.js b/examples/jsm/loaders/LDrawLoader.js index 8add49ebdffcb9..32391d5c9b0e60 100644 --- a/examples/jsm/loaders/LDrawLoader.js +++ b/examples/jsm/loaders/LDrawLoader.js @@ -18,9 +18,26 @@ import { Vector3 } from '../../../build/three.module.js'; -var LDrawLoader = ( function () { - - var conditionalLineVertShader = /* glsl */` +// Special surface finish tag types. +// Note: "MATERIAL" tag (e.g. GLITTER, SPECKLE) is not implemented +const FINISH_TYPE_DEFAULT = 0; +const FINISH_TYPE_CHROME = 1; +const FINISH_TYPE_PEARLESCENT = 2; +const FINISH_TYPE_RUBBER = 3; +const FINISH_TYPE_MATTE_METALLIC = 4; +const FINISH_TYPE_METAL = 5; + +// State machine to search a subobject path. +// The LDraw standard establishes these various possible subfolders. +const FILE_LOCATION_AS_IS = 0; +const FILE_LOCATION_TRY_PARTS = 1; +const FILE_LOCATION_TRY_P = 2; +const FILE_LOCATION_TRY_MODELS = 3; +const FILE_LOCATION_TRY_RELATIVE = 4; +const FILE_LOCATION_TRY_ABSOLUTE = 5; +const FILE_LOCATION_NOT_FOUND = 6; + +const conditionalLineVertShader = /* glsl */` attribute vec3 control0; attribute vec3 control1; attribute vec3 direction; @@ -68,7 +85,7 @@ var LDrawLoader = ( function () { } `; - var conditionalLineFragShader = /* glsl */` +const conditionalLineFragShader = /* glsl */` uniform vec3 diffuse; uniform float opacity; varying float discardFlag; @@ -96,178 +113,175 @@ var LDrawLoader = ( function () { } `; +const _tempVec0 = new Vector3(); +const _tempVec1 = new Vector3(); +function smoothNormals( triangles, lineSegments ) { - var tempVec0 = new Vector3(); - var tempVec1 = new Vector3(); - function smoothNormals( triangles, lineSegments ) { - - function hashVertex( v ) { - - // NOTE: 1e2 is pretty coarse but was chosen because it allows edges - // to be smoothed as expected (see minifig arms). The errors between edges - // could be due to matrix multiplication. - var x = ~ ~ ( v.x * 1e2 ); - var y = ~ ~ ( v.y * 1e2 ); - var z = ~ ~ ( v.z * 1e2 ); - return `${ x },${ y },${ z }`; + function hashVertex( v ) { - } + // NOTE: 1e2 is pretty coarse but was chosen because it allows edges + // to be smoothed as expected (see minifig arms). The errors between edges + // could be due to matrix multiplication. + const x = ~ ~ ( v.x * 1e2 ); + const y = ~ ~ ( v.y * 1e2 ); + const z = ~ ~ ( v.z * 1e2 ); + return `${ x },${ y },${ z }`; - function hashEdge( v0, v1 ) { + } - return `${ hashVertex( v0 ) }_${ hashVertex( v1 ) }`; + function hashEdge( v0, v1 ) { - } + return `${ hashVertex( v0 ) }_${ hashVertex( v1 ) }`; - var hardEdges = new Set(); - var halfEdgeList = {}; - var fullHalfEdgeList = {}; - var normals = []; + } - // Save the list of hard edges by hash - for ( var i = 0, l = lineSegments.length; i < l; i ++ ) { + const hardEdges = new Set(); + const halfEdgeList = {}; + const fullHalfEdgeList = {}; + const normals = []; - var ls = lineSegments[ i ]; - var v0 = ls.v0; - var v1 = ls.v1; - hardEdges.add( hashEdge( v0, v1 ) ); - hardEdges.add( hashEdge( v1, v0 ) ); + // Save the list of hard edges by hash + for ( let i = 0, l = lineSegments.length; i < l; i ++ ) { - } + const ls = lineSegments[ i ]; + const v0 = ls.v0; + const v1 = ls.v1; + hardEdges.add( hashEdge( v0, v1 ) ); + hardEdges.add( hashEdge( v1, v0 ) ); - // track the half edges associated with each triangle - for ( var i = 0, l = triangles.length; i < l; i ++ ) { + } - var tri = triangles[ i ]; - for ( var i2 = 0, l2 = 3; i2 < l2; i2 ++ ) { + // track the half edges associated with each triangle + for ( let i = 0, l = triangles.length; i < l; i ++ ) { - var index = i2; - var next = ( i2 + 1 ) % 3; - var v0 = tri[ `v${ index }` ]; - var v1 = tri[ `v${ next }` ]; - var hash = hashEdge( v0, v1 ); + const tri = triangles[ i ]; + for ( let i2 = 0, l2 = 3; i2 < l2; i2 ++ ) { - // don't add the triangle if the edge is supposed to be hard - if ( hardEdges.has( hash ) ) continue; - halfEdgeList[ hash ] = tri; - fullHalfEdgeList[ hash ] = tri; + const index = i2; + const next = ( i2 + 1 ) % 3; + const v0 = tri[ `v${ index }` ]; + const v1 = tri[ `v${ next }` ]; + const hash = hashEdge( v0, v1 ); - } + // don't add the triangle if the edge is supposed to be hard + if ( hardEdges.has( hash ) ) continue; + halfEdgeList[ hash ] = tri; + fullHalfEdgeList[ hash ] = tri; } - // NOTE: Some of the normals wind up being skewed in an unexpected way because - // quads provide more "influence" to some vertex normals than a triangle due to - // the fact that a quad is made up of two triangles and all triangles are weighted - // equally. To fix this quads could be tracked separately so their vertex normals - // are weighted appropriately or we could try only adding a normal direction - // once per normal. - - // Iterate until we've tried to connect all triangles to share normals - while ( true ) { + } - // Stop if there are no more triangles left - var halfEdges = Object.keys( halfEdgeList ); - if ( halfEdges.length === 0 ) break; + // NOTE: Some of the normals wind up being skewed in an unexpected way because + // quads provide more "influence" to some vertex normals than a triangle due to + // the fact that a quad is made up of two triangles and all triangles are weighted + // equally. To fix this quads could be tracked separately so their vertex normals + // are weighted appropriately or we could try only adding a normal direction + // once per normal. - // Exhaustively find all connected triangles - var i = 0; - var queue = [ fullHalfEdgeList[ halfEdges[ 0 ] ] ]; - while ( i < queue.length ) { + // Iterate until we've tried to connect all triangles to share normals + while ( true ) { - // initialize all vertex normals in this triangle - var tri = queue[ i ]; - i ++; + // Stop if there are no more triangles left + const halfEdges = Object.keys( halfEdgeList ); + if ( halfEdges.length === 0 ) break; - var faceNormal = tri.faceNormal; - if ( tri.n0 === null ) { + // Exhaustively find all connected triangles + let i = 0; + const queue = [ fullHalfEdgeList[ halfEdges[ 0 ] ] ]; + while ( i < queue.length ) { - tri.n0 = faceNormal.clone(); - normals.push( tri.n0 ); + // initialize all vertex normals in this triangle + const tri = queue[ i ]; + i ++; - } + const faceNormal = tri.faceNormal; + if ( tri.n0 === null ) { - if ( tri.n1 === null ) { + tri.n0 = faceNormal.clone(); + normals.push( tri.n0 ); - tri.n1 = faceNormal.clone(); - normals.push( tri.n1 ); + } - } + if ( tri.n1 === null ) { - if ( tri.n2 === null ) { + tri.n1 = faceNormal.clone(); + normals.push( tri.n1 ); - tri.n2 = faceNormal.clone(); - normals.push( tri.n2 ); + } - } + if ( tri.n2 === null ) { - // Check if any edge is connected to another triangle edge - for ( var i2 = 0, l2 = 3; i2 < l2; i2 ++ ) { + tri.n2 = faceNormal.clone(); + normals.push( tri.n2 ); - var index = i2; - var next = ( i2 + 1 ) % 3; - var v0 = tri[ `v${ index }` ]; - var v1 = tri[ `v${ next }` ]; + } - // delete this triangle from the list so it won't be found again - var hash = hashEdge( v0, v1 ); - delete halfEdgeList[ hash ]; + // Check if any edge is connected to another triangle edge + for ( let i2 = 0, l2 = 3; i2 < l2; i2 ++ ) { - var reverseHash = hashEdge( v1, v0 ); - var otherTri = fullHalfEdgeList[ reverseHash ]; - if ( otherTri ) { + const index = i2; + const next = ( i2 + 1 ) % 3; + const v0 = tri[ `v${ index }` ]; + const v1 = tri[ `v${ next }` ]; - // NOTE: If the angle between triangles is > 67.5 degrees then assume it's - // hard edge. There are some cases where the line segments do not line up exactly - // with or span multiple triangle edges (see Lunar Vehicle wheels). - if ( Math.abs( otherTri.faceNormal.dot( tri.faceNormal ) ) < 0.25 ) { + // delete this triangle from the list so it won't be found again + const hash = hashEdge( v0, v1 ); + delete halfEdgeList[ hash ]; - continue; + const reverseHash = hashEdge( v1, v0 ); + const otherTri = fullHalfEdgeList[ reverseHash ]; + if ( otherTri ) { - } + // NOTE: If the angle between triangles is > 67.5 degrees then assume it's + // hard edge. There are some cases where the line segments do not line up exactly + // with or span multiple triangle edges (see Lunar Vehicle wheels). + if ( Math.abs( otherTri.faceNormal.dot( tri.faceNormal ) ) < 0.25 ) { - // if this triangle has already been traversed then it won't be in - // the halfEdgeList. If it has not then add it to the queue and delete - // it so it won't be found again. - if ( reverseHash in halfEdgeList ) { + continue; - queue.push( otherTri ); - delete halfEdgeList[ reverseHash ]; + } - } + // if this triangle has already been traversed then it won't be in + // the halfEdgeList. If it has not then add it to the queue and delete + // it so it won't be found again. + if ( reverseHash in halfEdgeList ) { - // Find the matching edge in this triangle and copy the normal vector over - for ( var i3 = 0, l3 = 3; i3 < l3; i3 ++ ) { + queue.push( otherTri ); + delete halfEdgeList[ reverseHash ]; - var otherIndex = i3; - var otherNext = ( i3 + 1 ) % 3; - var otherV0 = otherTri[ `v${ otherIndex }` ]; - var otherV1 = otherTri[ `v${ otherNext }` ]; + } - var otherHash = hashEdge( otherV0, otherV1 ); - if ( otherHash === reverseHash ) { + // Find the matching edge in this triangle and copy the normal vector over + for ( let i3 = 0, l3 = 3; i3 < l3; i3 ++ ) { - if ( otherTri[ `n${ otherIndex }` ] === null ) { + const otherIndex = i3; + const otherNext = ( i3 + 1 ) % 3; + const otherV0 = otherTri[ `v${ otherIndex }` ]; + const otherV1 = otherTri[ `v${ otherNext }` ]; - var norm = tri[ `n${ next }` ]; - otherTri[ `n${ otherIndex }` ] = norm; - norm.add( otherTri.faceNormal ); + const otherHash = hashEdge( otherV0, otherV1 ); + if ( otherHash === reverseHash ) { - } + if ( otherTri[ `n${ otherIndex }` ] === null ) { - if ( otherTri[ `n${ otherNext }` ] === null ) { + const norm = tri[ `n${ next }` ]; + otherTri[ `n${ otherIndex }` ] = norm; + norm.add( otherTri.faceNormal ); - var norm = tri[ `n${ index }` ]; - otherTri[ `n${ otherNext }` ] = norm; - norm.add( otherTri.faceNormal ); + } - } + if ( otherTri[ `n${ otherNext }` ] === null ) { - break; + const norm = tri[ `n${ index }` ]; + otherTri[ `n${ otherNext }` ] = norm; + norm.add( otherTri.faceNormal ); } + break; + } } @@ -278,22 +292,26 @@ var LDrawLoader = ( function () { } - // The normals of each face have been added up so now we average them by normalizing the vector. - for ( var i = 0, l = normals.length; i < l; i ++ ) { + } - normals[ i ].normalize(); + // The normals of each face have been added up so now we average them by normalizing the vector. + for ( let i = 0, l = normals.length; i < l; i ++ ) { - } + normals[ i ].normalize(); } - function isPrimitiveType( type ) { +} - return /primitive/i.test( type ) || type === 'Subpart'; +function isPrimitiveType( type ) { - } + return /primitive/i.test( type ) || type === 'Subpart'; + +} - function LineParser( line, lineNumber ) { +class LineParser { + + constructor( line, lineNumber ) { this.line = line; this.lineLength = line.length; @@ -303,238 +321,235 @@ var LDrawLoader = ( function () { } - LineParser.prototype = { - - constructor: LineParser, - - seekNonSpace: function () { - - while ( this.currentCharIndex < this.lineLength ) { - - this.currentChar = this.line.charAt( this.currentCharIndex ); + seekNonSpace() { - if ( this.currentChar !== ' ' && this.currentChar !== '\t' ) { + while ( this.currentCharIndex < this.lineLength ) { - return; + this.currentChar = this.line.charAt( this.currentCharIndex ); - } + if ( this.currentChar !== ' ' && this.currentChar !== '\t' ) { - this.currentCharIndex ++; + return; } - }, + this.currentCharIndex ++; - getToken: function () { + } - var pos0 = this.currentCharIndex ++; + } - // Seek space - while ( this.currentCharIndex < this.lineLength ) { + getToken() { - this.currentChar = this.line.charAt( this.currentCharIndex ); + const pos0 = this.currentCharIndex ++; - if ( this.currentChar === ' ' || this.currentChar === '\t' ) { + // Seek space + while ( this.currentCharIndex < this.lineLength ) { - break; + this.currentChar = this.line.charAt( this.currentCharIndex ); - } + if ( this.currentChar === ' ' || this.currentChar === '\t' ) { - this.currentCharIndex ++; + break; } - var pos1 = this.currentCharIndex; + this.currentCharIndex ++; - this.seekNonSpace(); + } - return this.line.substring( pos0, pos1 ); + const pos1 = this.currentCharIndex; - }, + this.seekNonSpace(); - getRemainingString: function () { + return this.line.substring( pos0, pos1 ); - return this.line.substring( this.currentCharIndex, this.lineLength ); + } - }, + getRemainingString() { - isAtTheEnd: function () { + return this.line.substring( this.currentCharIndex, this.lineLength ); - return this.currentCharIndex >= this.lineLength; + } - }, + isAtTheEnd() { - setToEnd: function () { + return this.currentCharIndex >= this.lineLength; - this.currentCharIndex = this.lineLength; + } - }, + setToEnd() { - getLineNumberString: function () { + this.currentCharIndex = this.lineLength; - return this.lineNumber >= 0 ? ' at line ' + this.lineNumber : ''; + } - } + getLineNumberString() { + return this.lineNumber >= 0 ? ' at line ' + this.lineNumber : ''; - }; + } - function sortByMaterial( a, b ) { +} - if ( a.colourCode === b.colourCode ) { +function sortByMaterial( a, b ) { - return 0; + if ( a.colourCode === b.colourCode ) { - } + return 0; - if ( a.colourCode < b.colourCode ) { + } - return - 1; + if ( a.colourCode < b.colourCode ) { - } - - return 1; + return - 1; } - function createObject( elements, elementSize, isConditionalSegments ) { + return 1; - // Creates a LineSegments (elementSize = 2) or a Mesh (elementSize = 3 ) - // With per face / segment material, implemented with mesh groups and materials array +} - // Sort the triangles or line segments by colour code to make later the mesh groups - elements.sort( sortByMaterial ); +function createObject( elements, elementSize, isConditionalSegments ) { - var positions = []; - var normals = []; - var materials = []; + // Creates a LineSegments (elementSize = 2) or a Mesh (elementSize = 3 ) + // With per face / segment material, implemented with mesh groups and materials array - var bufferGeometry = new BufferGeometry(); - var prevMaterial = null; - var index0 = 0; - var numGroupVerts = 0; + // Sort the triangles or line segments by colour code to make later the mesh groups + elements.sort( sortByMaterial ); - for ( var iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) { + const positions = []; + const normals = []; + const materials = []; - var elem = elements[ iElem ]; - var v0 = elem.v0; - var v1 = elem.v1; - // Note that LDraw coordinate system is rotated 180 deg. in the X axis w.r.t. Three.js's one - positions.push( v0.x, v0.y, v0.z, v1.x, v1.y, v1.z ); - if ( elementSize === 3 ) { + const bufferGeometry = new BufferGeometry(); + let prevMaterial = null; + let index0 = 0; + let numGroupVerts = 0; - positions.push( elem.v2.x, elem.v2.y, elem.v2.z ); + for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) { - var n0 = elem.n0 || elem.faceNormal; - var n1 = elem.n1 || elem.faceNormal; - var n2 = elem.n2 || elem.faceNormal; - normals.push( n0.x, n0.y, n0.z ); - normals.push( n1.x, n1.y, n1.z ); - normals.push( n2.x, n2.y, n2.z ); + const elem = elements[ iElem ]; + const v0 = elem.v0; + const v1 = elem.v1; + // Note that LDraw coordinate system is rotated 180 deg. in the X axis w.r.t. Three.js's one + positions.push( v0.x, v0.y, v0.z, v1.x, v1.y, v1.z ); + if ( elementSize === 3 ) { - } + positions.push( elem.v2.x, elem.v2.y, elem.v2.z ); - if ( prevMaterial !== elem.material ) { + const n0 = elem.n0 || elem.faceNormal; + const n1 = elem.n1 || elem.faceNormal; + const n2 = elem.n2 || elem.faceNormal; + normals.push( n0.x, n0.y, n0.z ); + normals.push( n1.x, n1.y, n1.z ); + normals.push( n2.x, n2.y, n2.z ); - if ( prevMaterial !== null ) { + } - bufferGeometry.addGroup( index0, numGroupVerts, materials.length - 1 ); + if ( prevMaterial !== elem.material ) { - } + if ( prevMaterial !== null ) { - materials.push( elem.material ); + bufferGeometry.addGroup( index0, numGroupVerts, materials.length - 1 ); - prevMaterial = elem.material; - index0 = iElem * elementSize; - numGroupVerts = elementSize; + } - } else { + materials.push( elem.material ); - numGroupVerts += elementSize; + prevMaterial = elem.material; + index0 = iElem * elementSize; + numGroupVerts = elementSize; - } + } else { - } + numGroupVerts += elementSize; - if ( numGroupVerts > 0 ) { + } - bufferGeometry.addGroup( index0, Infinity, materials.length - 1 ); + } - } + if ( numGroupVerts > 0 ) { - bufferGeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + bufferGeometry.addGroup( index0, Infinity, materials.length - 1 ); - if ( elementSize === 3 ) { + } - bufferGeometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + bufferGeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - } + if ( elementSize === 3 ) { - var object3d = null; + bufferGeometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - if ( elementSize === 2 ) { + } - object3d = new LineSegments( bufferGeometry, materials ); + let object3d = null; - } else if ( elementSize === 3 ) { + if ( elementSize === 2 ) { - object3d = new Mesh( bufferGeometry, materials ); + object3d = new LineSegments( bufferGeometry, materials ); - } + } else if ( elementSize === 3 ) { - if ( isConditionalSegments ) { - - object3d.isConditionalLine = true; - - var controlArray0 = new Float32Array( elements.length * 3 * 2 ); - var controlArray1 = new Float32Array( elements.length * 3 * 2 ); - var directionArray = new Float32Array( elements.length * 3 * 2 ); - for ( var i = 0, l = elements.length; i < l; i ++ ) { - - var os = elements[ i ]; - var c0 = os.c0; - var c1 = os.c1; - var v0 = os.v0; - var v1 = os.v1; - var index = i * 3 * 2; - controlArray0[ index + 0 ] = c0.x; - controlArray0[ index + 1 ] = c0.y; - controlArray0[ index + 2 ] = c0.z; - controlArray0[ index + 3 ] = c0.x; - controlArray0[ index + 4 ] = c0.y; - controlArray0[ index + 5 ] = c0.z; - - controlArray1[ index + 0 ] = c1.x; - controlArray1[ index + 1 ] = c1.y; - controlArray1[ index + 2 ] = c1.z; - controlArray1[ index + 3 ] = c1.x; - controlArray1[ index + 4 ] = c1.y; - controlArray1[ index + 5 ] = c1.z; - - directionArray[ index + 0 ] = v1.x - v0.x; - directionArray[ index + 1 ] = v1.y - v0.y; - directionArray[ index + 2 ] = v1.z - v0.z; - directionArray[ index + 3 ] = v1.x - v0.x; - directionArray[ index + 4 ] = v1.y - v0.y; - directionArray[ index + 5 ] = v1.z - v0.z; + object3d = new Mesh( bufferGeometry, materials ); - } + } - bufferGeometry.setAttribute( 'control0', new BufferAttribute( controlArray0, 3, false ) ); - bufferGeometry.setAttribute( 'control1', new BufferAttribute( controlArray1, 3, false ) ); - bufferGeometry.setAttribute( 'direction', new BufferAttribute( directionArray, 3, false ) ); + if ( isConditionalSegments ) { + + object3d.isConditionalLine = true; + + const controlArray0 = new Float32Array( elements.length * 3 * 2 ); + const controlArray1 = new Float32Array( elements.length * 3 * 2 ); + const directionArray = new Float32Array( elements.length * 3 * 2 ); + for ( let i = 0, l = elements.length; i < l; i ++ ) { + + const os = elements[ i ]; + const c0 = os.c0; + const c1 = os.c1; + const v0 = os.v0; + const v1 = os.v1; + const index = i * 3 * 2; + controlArray0[ index + 0 ] = c0.x; + controlArray0[ index + 1 ] = c0.y; + controlArray0[ index + 2 ] = c0.z; + controlArray0[ index + 3 ] = c0.x; + controlArray0[ index + 4 ] = c0.y; + controlArray0[ index + 5 ] = c0.z; + + controlArray1[ index + 0 ] = c1.x; + controlArray1[ index + 1 ] = c1.y; + controlArray1[ index + 2 ] = c1.z; + controlArray1[ index + 3 ] = c1.x; + controlArray1[ index + 4 ] = c1.y; + controlArray1[ index + 5 ] = c1.z; + + directionArray[ index + 0 ] = v1.x - v0.x; + directionArray[ index + 1 ] = v1.y - v0.y; + directionArray[ index + 2 ] = v1.z - v0.z; + directionArray[ index + 3 ] = v1.x - v0.x; + directionArray[ index + 4 ] = v1.y - v0.y; + directionArray[ index + 5 ] = v1.z - v0.z; } - return object3d; + bufferGeometry.setAttribute( 'control0', new BufferAttribute( controlArray0, 3, false ) ); + bufferGeometry.setAttribute( 'control1', new BufferAttribute( controlArray1, 3, false ) ); + bufferGeometry.setAttribute( 'direction', new BufferAttribute( directionArray, 3, false ) ); } - // + return object3d; - function LDrawLoader( manager ) { +} - Loader.call( this, manager ); +// + +class LDrawLoader extends Loader { + + constructor( manager ) { + + super( manager ); // This is a stack of 'parse scopes' with one level per subobject loaded file. // Each level contains a material lib and also other runtime variables passed between parent and child subobjects @@ -567,984 +582,990 @@ var LDrawLoader = ( function () { } - // Special surface finish tag types. - // Note: "MATERIAL" tag (e.g. GLITTER, SPECKLE) is not implemented - LDrawLoader.FINISH_TYPE_DEFAULT = 0; - LDrawLoader.FINISH_TYPE_CHROME = 1; - LDrawLoader.FINISH_TYPE_PEARLESCENT = 2; - LDrawLoader.FINISH_TYPE_RUBBER = 3; - LDrawLoader.FINISH_TYPE_MATTE_METALLIC = 4; - LDrawLoader.FINISH_TYPE_METAL = 5; - - // State machine to search a subobject path. - // The LDraw standard establishes these various possible subfolders. - LDrawLoader.FILE_LOCATION_AS_IS = 0; - LDrawLoader.FILE_LOCATION_TRY_PARTS = 1; - LDrawLoader.FILE_LOCATION_TRY_P = 2; - LDrawLoader.FILE_LOCATION_TRY_MODELS = 3; - LDrawLoader.FILE_LOCATION_TRY_RELATIVE = 4; - LDrawLoader.FILE_LOCATION_TRY_ABSOLUTE = 5; - LDrawLoader.FILE_LOCATION_NOT_FOUND = 6; - - LDrawLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + load( url, onLoad, onProgress, onError ) { - constructor: LDrawLoader, + if ( ! this.fileMap ) { - load: function ( url, onLoad, onProgress, onError ) { + this.fileMap = {}; - if ( ! this.fileMap ) { - - this.fileMap = {}; - - } - - var scope = this; + } - var fileLoader = new FileLoader( this.manager ); - fileLoader.setPath( this.path ); - fileLoader.setRequestHeader( this.requestHeader ); - fileLoader.setWithCredentials( this.withCredentials ); - fileLoader.load( url, function ( text ) { + const scope = this; - scope.processObject( text, onLoad, null, url ); + const fileLoader = new FileLoader( this.manager ); + fileLoader.setPath( this.path ); + fileLoader.setRequestHeader( this.requestHeader ); + fileLoader.setWithCredentials( this.withCredentials ); + fileLoader.load( url, function ( text ) { - }, onProgress, onError ); + scope.processObject( text, onLoad, null, url ); - }, + }, onProgress, onError ); - parse: function ( text, path, onLoad ) { + } - // Async parse. This function calls onParse with the parsed THREE.Object3D as parameter + parse( text, path, onLoad ) { - this.processObject( text, onLoad, null, path ); + // Async parse. This function calls onParse with the parsed THREE.Object3D as parameter - }, + this.processObject( text, onLoad, null, path ); - setMaterials: function ( materials ) { + } - // Clears parse scopes stack, adds new scope with material library + setMaterials( materials ) { - this.parseScopesStack = []; + // Clears parse scopes stack, adds new scope with material library - this.newParseScopeLevel( materials ); + this.parseScopesStack = []; - this.getCurrentParseScope().isFromParse = false; + this.newParseScopeLevel( materials ); - this.materials = materials; + this.getCurrentParseScope().isFromParse = false; - return this; + this.materials = materials; - }, + return this; - setFileMap: function ( fileMap ) { + } - this.fileMap = fileMap; + setFileMap( fileMap ) { - return this; + this.fileMap = fileMap; - }, + return this; - newParseScopeLevel: function ( materials ) { + } - // Adds a new scope level, assign materials to it and returns it + newParseScopeLevel( materials ) { - var matLib = {}; + // Adds a new scope level, assign materials to it and returns it - if ( materials ) { + const matLib = {}; - for ( var i = 0, n = materials.length; i < n; i ++ ) { + if ( materials ) { - var material = materials[ i ]; - matLib[ material.userData.code ] = material; + for ( let i = 0, n = materials.length; i < n; i ++ ) { - } + const material = materials[ i ]; + matLib[ material.userData.code ] = material; } - var topParseScope = this.getCurrentParseScope(); - var newParseScope = { + } - lib: matLib, - url: null, + const topParseScope = this.getCurrentParseScope(); + const newParseScope = { - // Subobjects - subobjects: null, - numSubobjects: 0, - subobjectIndex: 0, - inverted: false, - category: null, - keywords: null, + lib: matLib, + url: null, - // Current subobject - currentFileName: null, - mainColourCode: topParseScope ? topParseScope.mainColourCode : '16', - mainEdgeColourCode: topParseScope ? topParseScope.mainEdgeColourCode : '24', - currentMatrix: new Matrix4(), - matrix: new Matrix4(), + // Subobjects + subobjects: null, + numSubobjects: 0, + subobjectIndex: 0, + inverted: false, + category: null, + keywords: null, - // If false, it is a root material scope previous to parse - isFromParse: true, + // Current subobject + currentFileName: null, + mainColourCode: topParseScope ? topParseScope.mainColourCode : '16', + mainEdgeColourCode: topParseScope ? topParseScope.mainEdgeColourCode : '24', + currentMatrix: new Matrix4(), + matrix: new Matrix4(), - triangles: null, - lineSegments: null, - conditionalSegments: null, + // If false, it is a root material scope previous to parse + isFromParse: true, - // If true, this object is the start of a construction step - startingConstructionStep: false - }; + triangles: null, + lineSegments: null, + conditionalSegments: null, - this.parseScopesStack.push( newParseScope ); + // If true, this object is the start of a construction step + startingConstructionStep: false + }; - return newParseScope; + this.parseScopesStack.push( newParseScope ); - }, + return newParseScope; - removeScopeLevel: function () { + } - this.parseScopesStack.pop(); + removeScopeLevel() { - return this; + this.parseScopesStack.pop(); - }, + return this; - addMaterial: function ( material ) { + } - // Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array + addMaterial( material ) { - var matLib = this.getCurrentParseScope().lib; + // Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array - if ( ! matLib[ material.userData.code ] ) { + const matLib = this.getCurrentParseScope().lib; - this.materials.push( material ); + if ( ! matLib[ material.userData.code ] ) { - } + this.materials.push( material ); - matLib[ material.userData.code ] = material; + } - return this; + matLib[ material.userData.code ] = material; - }, + return this; - getMaterial: function ( colourCode ) { + } - // Given a colour code search its material in the parse scopes stack + getMaterial( colourCode ) { - if ( colourCode.startsWith( '0x2' ) ) { + // Given a colour code search its material in the parse scopes stack - // Special 'direct' material value (RGB colour) + if ( colourCode.startsWith( '0x2' ) ) { - var colour = colourCode.substring( 3 ); + // Special 'direct' material value (RGB colour) - return this.parseColourMetaDirective( new LineParser( 'Direct_Color_' + colour + ' CODE -1 VALUE #' + colour + ' EDGE #' + colour + '' ) ); + const colour = colourCode.substring( 3 ); - } + return this.parseColourMetaDirective( new LineParser( 'Direct_Color_' + colour + ' CODE -1 VALUE #' + colour + ' EDGE #' + colour + '' ) ); - for ( var i = this.parseScopesStack.length - 1; i >= 0; i -- ) { + } - var material = this.parseScopesStack[ i ].lib[ colourCode ]; + for ( let i = this.parseScopesStack.length - 1; i >= 0; i -- ) { - if ( material ) { + const material = this.parseScopesStack[ i ].lib[ colourCode ]; - return material; + if ( material ) { - } + return material; } - // Material was not found - return null; + } - }, + // Material was not found + return null; - getParentParseScope: function () { + } - if ( this.parseScopesStack.length > 1 ) { + getParentParseScope() { - return this.parseScopesStack[ this.parseScopesStack.length - 2 ]; + if ( this.parseScopesStack.length > 1 ) { - } + return this.parseScopesStack[ this.parseScopesStack.length - 2 ]; - return null; + } - }, + return null; - getCurrentParseScope: function () { + } - if ( this.parseScopesStack.length > 0 ) { + getCurrentParseScope() { - return this.parseScopesStack[ this.parseScopesStack.length - 1 ]; + if ( this.parseScopesStack.length > 0 ) { - } + return this.parseScopesStack[ this.parseScopesStack.length - 1 ]; - return null; + } - }, + return null; - parseColourMetaDirective: function ( lineParser ) { + } - // Parses a colour definition and returns a THREE.Material or null if error + parseColourMetaDirective( lineParser ) { - var code = null; + // Parses a colour definition and returns a THREE.Material or null if error - // Triangle and line colours - var colour = 0xFF00FF; - var edgeColour = 0xFF00FF; + let code = null; - // Transparency - var alpha = 1; - var isTransparent = false; - // Self-illumination: - var luminance = 0; + // Triangle and line colours + let colour = 0xFF00FF; + let edgeColour = 0xFF00FF; - var finishType = LDrawLoader.FINISH_TYPE_DEFAULT; - var canHaveEnvMap = true; + // Transparency + let alpha = 1; + let isTransparent = false; + // Self-illumination: + let luminance = 0; - var edgeMaterial = null; + let finishType = FINISH_TYPE_DEFAULT; + let canHaveEnvMap = true; - var name = lineParser.getToken(); - if ( ! name ) { + let edgeMaterial = null; - throw 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.'; + const name = lineParser.getToken(); + if ( ! name ) { - } + throw 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.'; - // Parse tag tokens and their parameters - var token = null; - while ( true ) { - - token = lineParser.getToken(); + } - if ( ! token ) { + // Parse tag tokens and their parameters + let token = null; + while ( true ) { - break; + token = lineParser.getToken(); - } + if ( ! token ) { - switch ( token.toUpperCase() ) { + break; - case 'CODE': + } - code = lineParser.getToken(); - break; + switch ( token.toUpperCase() ) { - case 'VALUE': + case 'CODE': - colour = lineParser.getToken(); - if ( colour.startsWith( '0x' ) ) { + code = lineParser.getToken(); + break; - colour = '#' + colour.substring( 2 ); + case 'VALUE': - } else if ( ! colour.startsWith( '#' ) ) { + colour = lineParser.getToken(); + if ( colour.startsWith( '0x' ) ) { - throw 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + '.'; + colour = '#' + colour.substring( 2 ); - } + } else if ( ! colour.startsWith( '#' ) ) { - break; + throw 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + '.'; - case 'EDGE': + } - edgeColour = lineParser.getToken(); - if ( edgeColour.startsWith( '0x' ) ) { + break; - edgeColour = '#' + edgeColour.substring( 2 ); + case 'EDGE': - } else if ( ! edgeColour.startsWith( '#' ) ) { + edgeColour = lineParser.getToken(); + if ( edgeColour.startsWith( '0x' ) ) { - // Try to see if edge colour is a colour code - edgeMaterial = this.getMaterial( edgeColour ); - if ( ! edgeMaterial ) { + edgeColour = '#' + edgeColour.substring( 2 ); - throw 'LDrawLoader: Invalid edge colour while parsing material' + lineParser.getLineNumberString() + '.'; + } else if ( ! edgeColour.startsWith( '#' ) ) { - } + // Try to see if edge colour is a colour code + edgeMaterial = this.getMaterial( edgeColour ); + if ( ! edgeMaterial ) { - // Get the edge material for this triangle material - edgeMaterial = edgeMaterial.userData.edgeMaterial; + throw 'LDrawLoader: Invalid edge colour while parsing material' + lineParser.getLineNumberString() + '.'; } - break; + // Get the edge material for this triangle material + edgeMaterial = edgeMaterial.userData.edgeMaterial; + + } - case 'ALPHA': + break; - alpha = parseInt( lineParser.getToken() ); + case 'ALPHA': - if ( isNaN( alpha ) ) { + alpha = parseInt( lineParser.getToken() ); - throw 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.'; + if ( isNaN( alpha ) ) { - } + throw 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.'; - alpha = Math.max( 0, Math.min( 1, alpha / 255 ) ); + } - if ( alpha < 1 ) { + alpha = Math.max( 0, Math.min( 1, alpha / 255 ) ); - isTransparent = true; + if ( alpha < 1 ) { - } + isTransparent = true; - break; + } - case 'LUMINANCE': + break; - luminance = parseInt( lineParser.getToken() ); + case 'LUMINANCE': - if ( isNaN( luminance ) ) { + luminance = parseInt( lineParser.getToken() ); - throw 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.'; + if ( isNaN( luminance ) ) { - } + throw 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.'; - luminance = Math.max( 0, Math.min( 1, luminance / 255 ) ); + } - break; + luminance = Math.max( 0, Math.min( 1, luminance / 255 ) ); - case 'CHROME': - finishType = LDrawLoader.FINISH_TYPE_CHROME; - break; + break; - case 'PEARLESCENT': - finishType = LDrawLoader.FINISH_TYPE_PEARLESCENT; - break; + case 'CHROME': + finishType = FINISH_TYPE_CHROME; + break; - case 'RUBBER': - finishType = LDrawLoader.FINISH_TYPE_RUBBER; - break; + case 'PEARLESCENT': + finishType = FINISH_TYPE_PEARLESCENT; + break; - case 'MATTE_METALLIC': - finishType = LDrawLoader.FINISH_TYPE_MATTE_METALLIC; - break; + case 'RUBBER': + finishType = FINISH_TYPE_RUBBER; + break; - case 'METAL': - finishType = LDrawLoader.FINISH_TYPE_METAL; - break; + case 'MATTE_METALLIC': + finishType = FINISH_TYPE_MATTE_METALLIC; + break; - case 'MATERIAL': - // Not implemented - lineParser.setToEnd(); - break; + case 'METAL': + finishType = FINISH_TYPE_METAL; + break; - default: - throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.'; - break; + case 'MATERIAL': + // Not implemented + lineParser.setToEnd(); + break; - } + default: + throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.'; + break; } - var material = null; + } - switch ( finishType ) { + let material = null; - case LDrawLoader.FINISH_TYPE_DEFAULT: + switch ( finishType ) { - material = new MeshStandardMaterial( { color: colour, roughness: 0.3, envMapIntensity: 0.3, metalness: 0 } ); - break; + case FINISH_TYPE_DEFAULT: - case LDrawLoader.FINISH_TYPE_PEARLESCENT: + material = new MeshStandardMaterial( { color: colour, roughness: 0.3, envMapIntensity: 0.3, metalness: 0 } ); + break; - // Try to imitate pearlescency by setting the specular to the complementary of the color, and low shininess - var specular = new Color( colour ); - var hsl = specular.getHSL( { h: 0, s: 0, l: 0 } ); - hsl.h = ( hsl.h + 0.5 ) % 1; - hsl.l = Math.min( 1, hsl.l + ( 1 - hsl.l ) * 0.7 ); - specular.setHSL( hsl.h, hsl.s, hsl.l ); + case FINISH_TYPE_PEARLESCENT: - material = new MeshPhongMaterial( { color: colour, specular: specular, shininess: 10, reflectivity: 0.3 } ); - break; + // Try to imitate pearlescency by setting the specular to the complementary of the color, and low shininess + const specular = new Color( colour ); + const hsl = specular.getHSL( { h: 0, s: 0, l: 0 } ); + hsl.h = ( hsl.h + 0.5 ) % 1; + hsl.l = Math.min( 1, hsl.l + ( 1 - hsl.l ) * 0.7 ); + specular.setHSL( hsl.h, hsl.s, hsl.l ); - case LDrawLoader.FINISH_TYPE_CHROME: + material = new MeshPhongMaterial( { color: colour, specular: specular, shininess: 10, reflectivity: 0.3 } ); + break; - // Mirror finish surface - material = new MeshStandardMaterial( { color: colour, roughness: 0, metalness: 1 } ); - break; + case FINISH_TYPE_CHROME: - case LDrawLoader.FINISH_TYPE_RUBBER: + // Mirror finish surface + material = new MeshStandardMaterial( { color: colour, roughness: 0, metalness: 1 } ); + break; - // Rubber finish - material = new MeshStandardMaterial( { color: colour, roughness: 0.9, metalness: 0 } ); - canHaveEnvMap = false; - break; + case FINISH_TYPE_RUBBER: - case LDrawLoader.FINISH_TYPE_MATTE_METALLIC: + // Rubber finish + material = new MeshStandardMaterial( { color: colour, roughness: 0.9, metalness: 0 } ); + canHaveEnvMap = false; + break; - // Brushed metal finish - material = new MeshStandardMaterial( { color: colour, roughness: 0.8, metalness: 0.4 } ); - break; + case FINISH_TYPE_MATTE_METALLIC: - case LDrawLoader.FINISH_TYPE_METAL: + // Brushed metal finish + material = new MeshStandardMaterial( { color: colour, roughness: 0.8, metalness: 0.4 } ); + break; - // Average metal finish - material = new MeshStandardMaterial( { color: colour, roughness: 0.2, metalness: 0.85 } ); - break; + case FINISH_TYPE_METAL: - default: - // Should not happen - break; + // Average metal finish + material = new MeshStandardMaterial( { color: colour, roughness: 0.2, metalness: 0.85 } ); + break; - } + default: + // Should not happen + break; - material.transparent = isTransparent; - material.premultipliedAlpha = true; - material.opacity = alpha; - material.depthWrite = ! isTransparent; + } - material.polygonOffset = true; - material.polygonOffsetFactor = 1; + material.transparent = isTransparent; + material.premultipliedAlpha = true; + material.opacity = alpha; + material.depthWrite = ! isTransparent; - material.userData.canHaveEnvMap = canHaveEnvMap; + material.polygonOffset = true; + material.polygonOffsetFactor = 1; - if ( luminance !== 0 ) { + material.userData.canHaveEnvMap = canHaveEnvMap; - material.emissive.set( material.color ).multiplyScalar( luminance ); + if ( luminance !== 0 ) { - } + material.emissive.set( material.color ).multiplyScalar( luminance ); - if ( ! edgeMaterial ) { + } - // This is the material used for edges - edgeMaterial = new LineBasicMaterial( { - color: edgeColour, - transparent: isTransparent, - opacity: alpha, - depthWrite: ! isTransparent - } ); - edgeMaterial.userData.code = code; - edgeMaterial.name = name + ' - Edge'; - edgeMaterial.userData.canHaveEnvMap = false; - - // This is the material used for conditional edges - edgeMaterial.userData.conditionalEdgeMaterial = new ShaderMaterial( { - vertexShader: conditionalLineVertShader, - fragmentShader: conditionalLineFragShader, - uniforms: UniformsUtils.merge( [ - UniformsLib.fog, - { - diffuse: { - value: new Color( edgeColour ) - }, - opacity: { - value: alpha - } - } - ] ), - fog: true, - transparent: isTransparent, - depthWrite: ! isTransparent - } ); - edgeMaterial.userData.conditionalEdgeMaterial.userData.canHaveEnvMap = false; + if ( ! edgeMaterial ) { - } + // This is the material used for edges + edgeMaterial = new LineBasicMaterial( { + color: edgeColour, + transparent: isTransparent, + opacity: alpha, + depthWrite: ! isTransparent + } ); + edgeMaterial.userData.code = code; + edgeMaterial.name = name + ' - Edge'; + edgeMaterial.userData.canHaveEnvMap = false; + + // This is the material used for conditional edges + edgeMaterial.userData.conditionalEdgeMaterial = new ShaderMaterial( { + vertexShader: conditionalLineVertShader, + fragmentShader: conditionalLineFragShader, + uniforms: UniformsUtils.merge( [ + UniformsLib.fog, + { + diffuse: { + value: new Color( edgeColour ) + }, + opacity: { + value: alpha + } + } + ] ), + fog: true, + transparent: isTransparent, + depthWrite: ! isTransparent + } ); + edgeMaterial.userData.conditionalEdgeMaterial.userData.canHaveEnvMap = false; - material.userData.code = code; - material.name = name; + } - material.userData.edgeMaterial = edgeMaterial; + material.userData.code = code; + material.name = name; - return material; + material.userData.edgeMaterial = edgeMaterial; - }, + return material; - // + } - objectParse: function ( text ) { + // - // Retrieve data from the parent parse scope - var parentParseScope = this.getParentParseScope(); + objectParse( text ) { - // Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object) - var mainColourCode = parentParseScope.mainColourCode; - var mainEdgeColourCode = parentParseScope.mainEdgeColourCode; + // Retrieve data from the parent parse scope + const parentParseScope = this.getParentParseScope(); - var currentParseScope = this.getCurrentParseScope(); + // Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object) + const mainColourCode = parentParseScope.mainColourCode; + const mainEdgeColourCode = parentParseScope.mainEdgeColourCode; - // Parse result variables - var triangles; - var lineSegments; - var conditionalSegments; + const currentParseScope = this.getCurrentParseScope(); - var subobjects = []; + // Parse result variables + let triangles; + let lineSegments; + let conditionalSegments; - var category = null; - var keywords = null; + const subobjects = []; - if ( text.indexOf( '\r\n' ) !== - 1 ) { + let category = null; + let keywords = null; - // This is faster than String.split with regex that splits on both - text = text.replace( /\r\n/g, '\n' ); + if ( text.indexOf( '\r\n' ) !== - 1 ) { - } + // This is faster than String.split with regex that splits on both + text = text.replace( /\r\n/g, '\n' ); - var lines = text.split( '\n' ); - var numLines = lines.length; - var lineIndex = 0; + } - var parsingEmbeddedFiles = false; - var currentEmbeddedFileName = null; - var currentEmbeddedText = null; + const lines = text.split( '\n' ); + const numLines = lines.length; - var bfcCertified = false; - var bfcCCW = true; - var bfcInverted = false; - var bfcCull = true; - var type = ''; + let parsingEmbeddedFiles = false; + let currentEmbeddedFileName = null; + let currentEmbeddedText = null; - var startingConstructionStep = false; + let bfcCertified = false; + let bfcCCW = true; + let bfcInverted = false; + let bfcCull = true; + let type = ''; - var scope = this; - function parseColourCode( lineParser, forEdge ) { + let startingConstructionStep = false; - // Parses next colour code and returns a THREE.Material + const scope = this; + function parseColourCode( lineParser, forEdge ) { - var colourCode = lineParser.getToken(); + // Parses next colour code and returns a THREE.Material - if ( ! forEdge && colourCode === '16' ) { + let colourCode = lineParser.getToken(); - colourCode = mainColourCode; + if ( ! forEdge && colourCode === '16' ) { - } + colourCode = mainColourCode; - if ( forEdge && colourCode === '24' ) { + } - colourCode = mainEdgeColourCode; + if ( forEdge && colourCode === '24' ) { - } + colourCode = mainEdgeColourCode; - var material = scope.getMaterial( colourCode ); + } - if ( ! material ) { + const material = scope.getMaterial( colourCode ); - throw 'LDrawLoader: Unknown colour code "' + colourCode + '" is used' + lineParser.getLineNumberString() + ' but it was not defined previously.'; + if ( ! material ) { - } - - return material; + throw 'LDrawLoader: Unknown colour code "' + colourCode + '" is used' + lineParser.getLineNumberString() + ' but it was not defined previously.'; } - function parseVector( lp ) { + return material; - var v = new Vector3( parseFloat( lp.getToken() ), parseFloat( lp.getToken() ), parseFloat( lp.getToken() ) ); + } - if ( ! scope.separateObjects ) { + function parseVector( lp ) { - v.applyMatrix4( currentParseScope.currentMatrix ); + const v = new Vector3( parseFloat( lp.getToken() ), parseFloat( lp.getToken() ), parseFloat( lp.getToken() ) ); - } + if ( ! scope.separateObjects ) { - return v; + v.applyMatrix4( currentParseScope.currentMatrix ); } - // Parse all line commands - for ( lineIndex = 0; lineIndex < numLines; lineIndex ++ ) { + return v; - var line = lines[ lineIndex ]; + } - if ( line.length === 0 ) continue; + // Parse all line commands + for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) { - if ( parsingEmbeddedFiles ) { + const line = lines[ lineIndex ]; - if ( line.startsWith( '0 FILE ' ) ) { + if ( line.length === 0 ) continue; - // Save previous embedded file in the cache - this.subobjectCache[ currentEmbeddedFileName.toLowerCase() ] = currentEmbeddedText; + if ( parsingEmbeddedFiles ) { - // New embedded text file - currentEmbeddedFileName = line.substring( 7 ); - currentEmbeddedText = ''; + if ( line.startsWith( '0 FILE ' ) ) { - } else { + // Save previous embedded file in the cache + this.subobjectCache[ currentEmbeddedFileName.toLowerCase() ] = currentEmbeddedText; - currentEmbeddedText += line + '\n'; + // New embedded text file + currentEmbeddedFileName = line.substring( 7 ); + currentEmbeddedText = ''; - } + } else { - continue; + currentEmbeddedText += line + '\n'; } - var lp = new LineParser( line, lineIndex + 1 ); + continue; - lp.seekNonSpace(); + } - if ( lp.isAtTheEnd() ) { + const lp = new LineParser( line, lineIndex + 1 ); - // Empty line - continue; + lp.seekNonSpace(); - } + if ( lp.isAtTheEnd() ) { - // Parse the line type - var lineType = lp.getToken(); + // Empty line + continue; - switch ( lineType ) { + } - // Line type 0: Comment or META - case '0': + // Parse the line type + const lineType = lp.getToken(); - // Parse meta directive - var meta = lp.getToken(); + let material; + let segment; + let inverted; + let ccw; + let doubleSided; + let v0, v1, v2, v3, faceNormal; - if ( meta ) { + switch ( lineType ) { - switch ( meta ) { + // Line type 0: Comment or META + case '0': - case '!LDRAW_ORG': + // Parse meta directive + const meta = lp.getToken(); - type = lp.getToken(); + if ( meta ) { - currentParseScope.triangles = []; - currentParseScope.lineSegments = []; - currentParseScope.conditionalSegments = []; - currentParseScope.type = type; + switch ( meta ) { - var isRoot = ! parentParseScope.isFromParse; - if ( isRoot || scope.separateObjects && ! isPrimitiveType( type ) ) { + case '!LDRAW_ORG': - currentParseScope.groupObject = new Group(); + type = lp.getToken(); - currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep; + currentParseScope.triangles = []; + currentParseScope.lineSegments = []; + currentParseScope.conditionalSegments = []; + currentParseScope.type = type; - } + const isRoot = ! parentParseScope.isFromParse; + if ( isRoot || scope.separateObjects && ! isPrimitiveType( type ) ) { + + currentParseScope.groupObject = new Group(); - // If the scale of the object is negated then the triangle winding order - // needs to be flipped. - var matrix = currentParseScope.matrix; - if ( - matrix.determinant() < 0 && ( - scope.separateObjects && isPrimitiveType( type ) || + 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; + currentParseScope.inverted = ! currentParseScope.inverted; - } + } - triangles = currentParseScope.triangles; - lineSegments = currentParseScope.lineSegments; - conditionalSegments = currentParseScope.conditionalSegments; + triangles = currentParseScope.triangles; + lineSegments = currentParseScope.lineSegments; + conditionalSegments = currentParseScope.conditionalSegments; - break; + break; - case '!COLOUR': + case '!COLOUR': - var material = this.parseColourMetaDirective( lp ); - if ( material ) { + material = this.parseColourMetaDirective( lp ); + if ( material ) { - this.addMaterial( material ); + this.addMaterial( material ); - } else { + } else { - console.warn( 'LDrawLoader: Error parsing material' + lp.getLineNumberString() ); + console.warn( 'LDrawLoader: Error parsing material' + lp.getLineNumberString() ); - } + } - break; + break; - case '!CATEGORY': + case '!CATEGORY': - category = lp.getToken(); - break; + category = lp.getToken(); + break; - case '!KEYWORDS': + case '!KEYWORDS': - var newKeywords = lp.getRemainingString().split( ',' ); - if ( newKeywords.length > 0 ) { + const newKeywords = lp.getRemainingString().split( ',' ); + if ( newKeywords.length > 0 ) { - if ( ! keywords ) { + if ( ! keywords ) { - keywords = []; + keywords = []; - } + } - newKeywords.forEach( function ( keyword ) { + newKeywords.forEach( function ( keyword ) { - keywords.push( keyword.trim() ); + keywords.push( keyword.trim() ); - } ); + } ); - } + } - break; + break; - case 'FILE': + case 'FILE': - if ( lineIndex > 0 ) { + if ( lineIndex > 0 ) { - // Start embedded text files parsing - parsingEmbeddedFiles = true; - currentEmbeddedFileName = lp.getRemainingString(); - currentEmbeddedText = ''; + // Start embedded text files parsing + parsingEmbeddedFiles = true; + currentEmbeddedFileName = lp.getRemainingString(); + currentEmbeddedText = ''; - bfcCertified = false; - bfcCCW = true; + bfcCertified = false; + bfcCCW = true; - } + } - break; + break; - case 'BFC': + case 'BFC': - // Changes to the backface culling state - while ( ! lp.isAtTheEnd() ) { + // Changes to the backface culling state + while ( ! lp.isAtTheEnd() ) { - var token = lp.getToken(); + const token = lp.getToken(); - switch ( token ) { + switch ( token ) { - case 'CERTIFY': - case 'NOCERTIFY': + case 'CERTIFY': + case 'NOCERTIFY': - bfcCertified = token === 'CERTIFY'; - bfcCCW = true; + bfcCertified = token === 'CERTIFY'; + bfcCCW = true; - break; + break; - case 'CW': - case 'CCW': + case 'CW': + case 'CCW': - bfcCCW = token === 'CCW'; + bfcCCW = token === 'CCW'; - break; + break; - case 'INVERTNEXT': + case 'INVERTNEXT': - bfcInverted = true; + bfcInverted = true; - break; + break; - case 'CLIP': - case 'NOCLIP': + case 'CLIP': + case 'NOCLIP': bfcCull = token === 'CLIP'; - break; - - default: + break; - console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' ); + default: - break; + console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' ); - } + break; } - break; + } - case 'STEP': + break; - startingConstructionStep = true; + case 'STEP': - break; + startingConstructionStep = true; - default: - // Other meta directives are not implemented - break; + break; - } + default: + // Other meta directives are not implemented + break; } - break; + } - // Line type 1: Sub-object file - case '1': + break; - var material = parseColourCode( lp ); + // Line type 1: Sub-object file + case '1': - var posX = parseFloat( lp.getToken() ); - var posY = parseFloat( lp.getToken() ); - var posZ = parseFloat( lp.getToken() ); - var m0 = parseFloat( lp.getToken() ); - var m1 = parseFloat( lp.getToken() ); - var m2 = parseFloat( lp.getToken() ); - var m3 = parseFloat( lp.getToken() ); - var m4 = parseFloat( lp.getToken() ); - var m5 = parseFloat( lp.getToken() ); - var m6 = parseFloat( lp.getToken() ); - var m7 = parseFloat( lp.getToken() ); - var m8 = parseFloat( lp.getToken() ); + material = parseColourCode( lp ); - var matrix = new Matrix4().set( - m0, m1, m2, posX, - m3, m4, m5, posY, - m6, m7, m8, posZ, - 0, 0, 0, 1 - ); + const posX = parseFloat( lp.getToken() ); + const posY = parseFloat( lp.getToken() ); + const posZ = parseFloat( lp.getToken() ); + const m0 = parseFloat( lp.getToken() ); + const m1 = parseFloat( lp.getToken() ); + const m2 = parseFloat( lp.getToken() ); + const m3 = parseFloat( lp.getToken() ); + const m4 = parseFloat( lp.getToken() ); + const m5 = parseFloat( lp.getToken() ); + const m6 = parseFloat( lp.getToken() ); + const m7 = parseFloat( lp.getToken() ); + const m8 = parseFloat( lp.getToken() ); - var fileName = lp.getRemainingString().trim().replace( /\\/g, '/' ); + const matrix = new Matrix4().set( + m0, m1, m2, posX, + m3, m4, m5, posY, + m6, m7, m8, posZ, + 0, 0, 0, 1 + ); - if ( scope.fileMap[ fileName ] ) { + let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' ); - // Found the subobject path in the preloaded file path map - fileName = scope.fileMap[ fileName ]; + if ( scope.fileMap[ fileName ] ) { - } else { + // Found the subobject path in the preloaded file path map + fileName = scope.fileMap[ fileName ]; - // Standardized subfolders - if ( fileName.startsWith( 's/' ) ) { + } else { - fileName = 'parts/' + fileName; + // Standardized subfolders + if ( fileName.startsWith( 's/' ) ) { - } else if ( fileName.startsWith( '48/' ) ) { + fileName = 'parts/' + fileName; - fileName = 'p/' + fileName; + } else if ( fileName.startsWith( '48/' ) ) { - } + fileName = 'p/' + fileName; } - subobjects.push( { - material: material, - matrix: matrix, - fileName: fileName, - originalFileName: fileName, - locationState: LDrawLoader.FILE_LOCATION_AS_IS, - url: null, - triedLowerCase: false, - inverted: bfcInverted !== currentParseScope.inverted, - startingConstructionStep: startingConstructionStep - } ); + } - bfcInverted = false; + subobjects.push( { + material: material, + matrix: matrix, + fileName: fileName, + originalFileName: fileName, + locationState: FILE_LOCATION_AS_IS, + url: null, + triedLowerCase: false, + inverted: bfcInverted !== currentParseScope.inverted, + startingConstructionStep: startingConstructionStep + } ); + + bfcInverted = false; - break; + break; // Line type 2: Line segment - case '2': + case '2': - var material = parseColourCode( lp, true ); + material = parseColourCode( lp, true ); - var segment = { - material: material.userData.edgeMaterial, - colourCode: material.userData.code, - v0: parseVector( lp ), - v1: parseVector( lp ) - }; + segment = { + material: material.userData.edgeMaterial, + colourCode: material.userData.code, + v0: parseVector( lp ), + v1: parseVector( lp ) + }; - lineSegments.push( segment ); + lineSegments.push( segment ); - break; + break; // Line type 5: Conditional Line segment - case '5': + case '5': - var material = parseColourCode( lp, true ); + material = parseColourCode( lp, true ); - var segment = { - material: material.userData.edgeMaterial.userData.conditionalEdgeMaterial, - colourCode: material.userData.code, - v0: parseVector( lp ), - v1: parseVector( lp ), - c0: parseVector( lp ), - c1: parseVector( lp ) - }; + segment = { + material: material.userData.edgeMaterial.userData.conditionalEdgeMaterial, + colourCode: material.userData.code, + v0: parseVector( lp ), + v1: parseVector( lp ), + c0: parseVector( lp ), + c1: parseVector( lp ) + }; - conditionalSegments.push( segment ); + conditionalSegments.push( segment ); - break; + break; // Line type 3: Triangle - case '3': + case '3': - var material = parseColourCode( lp ); + material = parseColourCode( lp ); - var inverted = currentParseScope.inverted; - var ccw = bfcCCW !== inverted; - var doubleSided = ! bfcCertified || ! bfcCull; - var v0, v1, v2, faceNormal; + inverted = currentParseScope.inverted; + ccw = bfcCCW !== inverted; + doubleSided = ! bfcCertified || ! bfcCull; - if ( ccw === true ) { + if ( ccw === true ) { - v0 = parseVector( lp ); - v1 = parseVector( lp ); - v2 = parseVector( lp ); + v0 = parseVector( lp ); + v1 = parseVector( lp ); + v2 = parseVector( lp ); - } else { + } else { - v2 = parseVector( lp ); - v1 = parseVector( lp ); - v0 = parseVector( lp ); + v2 = parseVector( lp ); + v1 = parseVector( lp ); + v0 = parseVector( lp ); - } + } - tempVec0.subVectors( v1, v0 ); - tempVec1.subVectors( v2, v1 ); - faceNormal = new Vector3() - .crossVectors( tempVec0, tempVec1 ) - .normalize(); + _tempVec0.subVectors( v1, v0 ); + _tempVec1.subVectors( v2, v1 ); + faceNormal = new Vector3() + .crossVectors( _tempVec0, _tempVec1 ) + .normalize(); + + triangles.push( { + material: material, + colourCode: material.userData.code, + v0: v0, + v1: v1, + v2: v2, + faceNormal: faceNormal, + n0: null, + n1: null, + n2: null + } ); + + if ( doubleSided === true ) { triangles.push( { material: material, colourCode: material.userData.code, v0: v0, - v1: v1, - v2: v2, + v1: v2, + v2: v1, faceNormal: faceNormal, n0: null, n1: null, n2: null } ); - if ( doubleSided === true ) { + } - triangles.push( { - material: material, - colourCode: material.userData.code, - v0: v0, - v1: v2, - v2: v1, - faceNormal: faceNormal, - n0: null, - n1: null, - n2: null - } ); + break; - } + // Line type 4: Quadrilateral + case '4': - break; + material = parseColourCode( lp ); - // Line type 4: Quadrilateral - case '4': + inverted = currentParseScope.inverted; + ccw = bfcCCW !== inverted; + doubleSided = ! bfcCertified || ! bfcCull; - var material = parseColourCode( lp ); + if ( ccw === true ) { - var inverted = currentParseScope.inverted; - var ccw = bfcCCW !== inverted; - var doubleSided = ! bfcCertified || ! bfcCull; - var v0, v1, v2, v3, faceNormal; + v0 = parseVector( lp ); + v1 = parseVector( lp ); + v2 = parseVector( lp ); + v3 = parseVector( lp ); - if ( ccw === true ) { + } else { - v0 = parseVector( lp ); - v1 = parseVector( lp ); - v2 = parseVector( lp ); - v3 = parseVector( lp ); + v3 = parseVector( lp ); + v2 = parseVector( lp ); + v1 = parseVector( lp ); + v0 = parseVector( lp ); - } else { + } - v3 = parseVector( lp ); - v2 = parseVector( lp ); - v1 = parseVector( lp ); - v0 = parseVector( lp ); + _tempVec0.subVectors( v1, v0 ); + _tempVec1.subVectors( v2, v1 ); + faceNormal = new Vector3() + .crossVectors( _tempVec0, _tempVec1 ) + .normalize(); + + triangles.push( { + material: material, + colourCode: material.userData.code, + v0: v0, + v1: v1, + v2: v2, + faceNormal: faceNormal, + n0: null, + n1: null, + n2: null + } ); - } + triangles.push( { + material: material, + colourCode: material.userData.code, + v0: v0, + v1: v2, + v2: v3, + faceNormal: faceNormal, + n0: null, + n1: null, + n2: null + } ); - tempVec0.subVectors( v1, v0 ); - tempVec1.subVectors( v2, v1 ); - faceNormal = new Vector3() - .crossVectors( tempVec0, tempVec1 ) - .normalize(); + if ( doubleSided === true ) { triangles.push( { material: material, colourCode: material.userData.code, v0: v0, - v1: v1, - v2: v2, + v1: v2, + v2: v1, faceNormal: faceNormal, n0: null, n1: null, @@ -1555,418 +1576,388 @@ var LDrawLoader = ( function () { material: material, colourCode: material.userData.code, v0: v0, - v1: v2, - v2: v3, + v1: v3, + v2: v2, faceNormal: faceNormal, n0: null, n1: null, n2: null } ); - if ( doubleSided === true ) { - - triangles.push( { - material: material, - colourCode: material.userData.code, - v0: v0, - v1: v2, - v2: v1, - faceNormal: faceNormal, - n0: null, - n1: null, - n2: null - } ); - - triangles.push( { - material: material, - colourCode: material.userData.code, - v0: v0, - v1: v3, - v2: v2, - faceNormal: faceNormal, - n0: null, - n1: null, - n2: null - } ); - - } - - break; + } - default: - throw 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.'; - break; + break; - } + default: + throw 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.'; + break; } - if ( parsingEmbeddedFiles ) { + } - this.subobjectCache[ currentEmbeddedFileName.toLowerCase() ] = currentEmbeddedText; + if ( parsingEmbeddedFiles ) { - } + this.subobjectCache[ currentEmbeddedFileName.toLowerCase() ] = currentEmbeddedText; - currentParseScope.category = category; - currentParseScope.keywords = keywords; - currentParseScope.subobjects = subobjects; - currentParseScope.numSubobjects = subobjects.length; - currentParseScope.subobjectIndex = 0; - - }, + } - computeConstructionSteps: function ( model ) { + currentParseScope.category = category; + currentParseScope.keywords = keywords; + currentParseScope.subobjects = subobjects; + currentParseScope.numSubobjects = subobjects.length; + currentParseScope.subobjectIndex = 0; - // Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object. + } - var stepNumber = 0; + computeConstructionSteps( model ) { - model.traverse( c => { + // Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object. - if ( c.isGroup ) { + let stepNumber = 0; - if ( c.userData.startingConstructionStep ) { + model.traverse( c => { - stepNumber ++; + if ( c.isGroup ) { - } + if ( c.userData.startingConstructionStep ) { - c.userData.constructionStep = stepNumber; + stepNumber ++; } - } ); + c.userData.constructionStep = stepNumber; - model.userData.numConstructionSteps = stepNumber + 1; + } - }, + } ); - processObject: function ( text, onProcessed, subobject, url ) { + model.userData.numConstructionSteps = stepNumber + 1; - var scope = this; + } - var parseScope = scope.newParseScopeLevel(); - parseScope.url = url; + processObject( text, onProcessed, subobject, url ) { - var parentParseScope = scope.getParentParseScope(); + const scope = this; - // Set current matrix - if ( subobject ) { + const parseScope = scope.newParseScopeLevel(); + parseScope.url = url; - parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix ); - parseScope.matrix.copy( subobject.matrix ); - parseScope.inverted = subobject.inverted; - parseScope.startingConstructionStep = subobject.startingConstructionStep; + const parentParseScope = scope.getParentParseScope(); - } + // Set current matrix + if ( subobject ) { - // Add to cache - var currentFileName = parentParseScope.currentFileName; - if ( currentFileName !== null ) { + parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix ); + parseScope.matrix.copy( subobject.matrix ); + parseScope.inverted = subobject.inverted; + parseScope.startingConstructionStep = subobject.startingConstructionStep; - currentFileName = parentParseScope.currentFileName.toLowerCase(); + } - } + // Add to cache + let currentFileName = parentParseScope.currentFileName; + if ( currentFileName !== null ) { - if ( scope.subobjectCache[ currentFileName ] === undefined ) { + currentFileName = parentParseScope.currentFileName.toLowerCase(); - scope.subobjectCache[ currentFileName ] = text; + } - } + if ( scope.subobjectCache[ currentFileName ] === undefined ) { + scope.subobjectCache[ currentFileName ] = text; - // Parse the object (returns a Group) - scope.objectParse( text ); - var finishedCount = 0; - onSubobjectFinish(); + } - function onSubobjectFinish() { - finishedCount ++; + // Parse the object (returns a Group) + scope.objectParse( text ); + let finishedCount = 0; + onSubobjectFinish(); - if ( finishedCount === parseScope.subobjects.length + 1 ) { + function onSubobjectFinish() { - finalizeObject(); + finishedCount ++; - } else { + if ( finishedCount === parseScope.subobjects.length + 1 ) { - // Once the previous subobject has finished we can start processing the next one in the list. - // The subobject processing shares scope in processing so it's important that they be loaded serially - // to avoid race conditions. - // Promise.resolve is used as an approach to asynchronously schedule a task _before_ this frame ends to - // avoid stack overflow exceptions when loading many subobjects from the cache. RequestAnimationFrame - // will work but causes the load to happen after the next frame which causes the load to take significantly longer. - var subobject = parseScope.subobjects[ parseScope.subobjectIndex ]; - Promise.resolve().then( function () { + finalizeObject(); - loadSubobject( subobject ); + } else { - } ); - parseScope.subobjectIndex ++; + // Once the previous subobject has finished we can start processing the next one in the list. + // The subobject processing shares scope in processing so it's important that they be loaded serially + // to avoid race conditions. + // Promise.resolve is used as an approach to asynchronously schedule a task _before_ this frame ends to + // avoid stack overflow exceptions when loading many subobjects from the cache. RequestAnimationFrame + // will work but causes the load to happen after the next frame which causes the load to take significantly longer. + const subobject = parseScope.subobjects[ parseScope.subobjectIndex ]; + Promise.resolve().then( function () { - } + loadSubobject( subobject ); - } + } ); + parseScope.subobjectIndex ++; - function finalizeObject() { + } - if ( scope.smoothNormals && parseScope.type === 'Part' ) { + } - smoothNormals( parseScope.triangles, parseScope.lineSegments ); + function finalizeObject() { - } + if ( scope.smoothNormals && parseScope.type === 'Part' ) { - var isRoot = ! parentParseScope.isFromParse; - if ( scope.separateObjects && ! isPrimitiveType( parseScope.type ) || isRoot ) { + smoothNormals( parseScope.triangles, parseScope.lineSegments ); - const objGroup = parseScope.groupObject; + } - if ( parseScope.triangles.length > 0 ) { + const isRoot = ! parentParseScope.isFromParse; + if ( scope.separateObjects && ! isPrimitiveType( parseScope.type ) || isRoot ) { - objGroup.add( createObject( parseScope.triangles, 3 ) ); + const objGroup = parseScope.groupObject; - } + if ( parseScope.triangles.length > 0 ) { - if ( parseScope.lineSegments.length > 0 ) { + objGroup.add( createObject( parseScope.triangles, 3 ) ); - objGroup.add( createObject( parseScope.lineSegments, 2 ) ); + } - } + if ( parseScope.lineSegments.length > 0 ) { - if ( parseScope.conditionalSegments.length > 0 ) { + objGroup.add( createObject( parseScope.lineSegments, 2 ) ); - objGroup.add( createObject( parseScope.conditionalSegments, 2, true ) ); + } - } + if ( parseScope.conditionalSegments.length > 0 ) { - if ( parentParseScope.groupObject ) { + objGroup.add( createObject( parseScope.conditionalSegments, 2, true ) ); - objGroup.name = parseScope.fileName; - objGroup.userData.category = parseScope.category; - objGroup.userData.keywords = parseScope.keywords; - parseScope.matrix.decompose( objGroup.position, objGroup.quaternion, objGroup.scale ); + } - parentParseScope.groupObject.add( objGroup ); + if ( parentParseScope.groupObject ) { - } + objGroup.name = parseScope.fileName; + objGroup.userData.category = parseScope.category; + objGroup.userData.keywords = parseScope.keywords; + parseScope.matrix.decompose( objGroup.position, objGroup.quaternion, objGroup.scale ); - } else { + parentParseScope.groupObject.add( objGroup ); - var separateObjects = scope.separateObjects; - var parentLineSegments = parentParseScope.lineSegments; - var parentConditionalSegments = parentParseScope.conditionalSegments; - var parentTriangles = parentParseScope.triangles; + } - var lineSegments = parseScope.lineSegments; - var conditionalSegments = parseScope.conditionalSegments; - var triangles = parseScope.triangles; + } else { - for ( var i = 0, l = lineSegments.length; i < l; i ++ ) { + const separateObjects = scope.separateObjects; + const parentLineSegments = parentParseScope.lineSegments; + const parentConditionalSegments = parentParseScope.conditionalSegments; + const parentTriangles = parentParseScope.triangles; - var ls = lineSegments[ i ]; + const lineSegments = parseScope.lineSegments; + const conditionalSegments = parseScope.conditionalSegments; + const triangles = parseScope.triangles; - if ( separateObjects ) { + for ( let i = 0, l = lineSegments.length; i < l; i ++ ) { - ls.v0.applyMatrix4( parseScope.matrix ); - ls.v1.applyMatrix4( parseScope.matrix ); + const ls = lineSegments[ i ]; - } + if ( separateObjects ) { - parentLineSegments.push( ls ); + ls.v0.applyMatrix4( parseScope.matrix ); + ls.v1.applyMatrix4( parseScope.matrix ); } - for ( var i = 0, l = conditionalSegments.length; i < l; i ++ ) { + parentLineSegments.push( ls ); - var os = conditionalSegments[ i ]; + } - if ( separateObjects ) { + for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) { - os.v0.applyMatrix4( parseScope.matrix ); - os.v1.applyMatrix4( parseScope.matrix ); - os.c0.applyMatrix4( parseScope.matrix ); - os.c1.applyMatrix4( parseScope.matrix ); + const os = conditionalSegments[ i ]; - } + if ( separateObjects ) { - parentConditionalSegments.push( os ); + os.v0.applyMatrix4( parseScope.matrix ); + os.v1.applyMatrix4( parseScope.matrix ); + os.c0.applyMatrix4( parseScope.matrix ); + os.c1.applyMatrix4( parseScope.matrix ); } - for ( var i = 0, l = triangles.length; i < l; i ++ ) { + parentConditionalSegments.push( os ); - var tri = triangles[ i ]; + } - if ( separateObjects ) { + for ( let i = 0, l = triangles.length; i < l; i ++ ) { - tri.v0 = tri.v0.clone().applyMatrix4( parseScope.matrix ); - tri.v1 = tri.v1.clone().applyMatrix4( parseScope.matrix ); - tri.v2 = tri.v2.clone().applyMatrix4( parseScope.matrix ); + const tri = triangles[ i ]; - tempVec0.subVectors( tri.v1, tri.v0 ); - tempVec1.subVectors( tri.v2, tri.v1 ); - tri.faceNormal.crossVectors( tempVec0, tempVec1 ).normalize(); + if ( separateObjects ) { - } + tri.v0 = tri.v0.clone().applyMatrix4( parseScope.matrix ); + tri.v1 = tri.v1.clone().applyMatrix4( parseScope.matrix ); + tri.v2 = tri.v2.clone().applyMatrix4( parseScope.matrix ); - parentTriangles.push( tri ); + _tempVec0.subVectors( tri.v1, tri.v0 ); + _tempVec1.subVectors( tri.v2, tri.v1 ); + tri.faceNormal.crossVectors( _tempVec0, _tempVec1 ).normalize(); } + parentTriangles.push( tri ); + } - scope.removeScopeLevel(); + } - // If it is root object, compute construction steps - if ( ! parentParseScope.isFromParse ) { + scope.removeScopeLevel(); - scope.computeConstructionSteps( parseScope.groupObject ); + // If it is root object, compute construction steps + if ( ! parentParseScope.isFromParse ) { - } + scope.computeConstructionSteps( parseScope.groupObject ); - if ( onProcessed ) { + } - onProcessed( parseScope.groupObject ); + if ( onProcessed ) { - } + onProcessed( parseScope.groupObject ); } - function loadSubobject( subobject ) { + } - parseScope.mainColourCode = subobject.material.userData.code; - parseScope.mainEdgeColourCode = subobject.material.userData.edgeMaterial.userData.code; - parseScope.currentFileName = subobject.originalFileName; + function loadSubobject( subobject ) { + parseScope.mainColourCode = subobject.material.userData.code; + parseScope.mainEdgeColourCode = subobject.material.userData.edgeMaterial.userData.code; + parseScope.currentFileName = subobject.originalFileName; - // If subobject was cached previously, use the cached one - var cached = scope.subobjectCache[ subobject.originalFileName.toLowerCase() ]; - if ( cached ) { - scope.processObject( cached, function ( subobjectGroup ) { + // If subobject was cached previously, use the cached one + const cached = scope.subobjectCache[ subobject.originalFileName.toLowerCase() ]; + if ( cached ) { - onSubobjectLoaded( subobjectGroup, subobject ); - onSubobjectFinish(); + scope.processObject( cached, function ( subobjectGroup ) { - }, subobject, url ); + onSubobjectLoaded( subobjectGroup, subobject ); + onSubobjectFinish(); - return; - - } + }, subobject, url ); - // Adjust file name to locate the subobject file path in standard locations (always under directory scope.path) - // Update also subobject.locationState for the next try if this load fails. - var subobjectURL = subobject.fileName; - var newLocationState = LDrawLoader.FILE_LOCATION_NOT_FOUND; + return; - switch ( subobject.locationState ) { + } - case LDrawLoader.FILE_LOCATION_AS_IS: - newLocationState = subobject.locationState + 1; - break; + // Adjust file name to locate the subobject file path in standard locations (always under directory scope.path) + // Update also subobject.locationState for the next try if this load fails. + let subobjectURL = subobject.fileName; + let newLocationState = FILE_LOCATION_NOT_FOUND; - case LDrawLoader.FILE_LOCATION_TRY_PARTS: - subobjectURL = 'parts/' + subobjectURL; - newLocationState = subobject.locationState + 1; - break; + switch ( subobject.locationState ) { - case LDrawLoader.FILE_LOCATION_TRY_P: - subobjectURL = 'p/' + subobjectURL; - newLocationState = subobject.locationState + 1; - break; + case FILE_LOCATION_AS_IS: + newLocationState = subobject.locationState + 1; + break; - case LDrawLoader.FILE_LOCATION_TRY_MODELS: - subobjectURL = 'models/' + subobjectURL; - newLocationState = subobject.locationState + 1; - break; + case FILE_LOCATION_TRY_PARTS: + subobjectURL = 'parts/' + subobjectURL; + newLocationState = subobject.locationState + 1; + break; - case LDrawLoader.FILE_LOCATION_TRY_RELATIVE: - subobjectURL = url.substring( 0, url.lastIndexOf( '/' ) + 1 ) + subobjectURL; - newLocationState = subobject.locationState + 1; - break; + case FILE_LOCATION_TRY_P: + subobjectURL = 'p/' + subobjectURL; + newLocationState = subobject.locationState + 1; + break; - case LDrawLoader.FILE_LOCATION_TRY_ABSOLUTE: + case FILE_LOCATION_TRY_MODELS: + subobjectURL = 'models/' + subobjectURL; + newLocationState = subobject.locationState + 1; + break; - if ( subobject.triedLowerCase ) { + case FILE_LOCATION_TRY_RELATIVE: + subobjectURL = url.substring( 0, url.lastIndexOf( '/' ) + 1 ) + subobjectURL; + newLocationState = subobject.locationState + 1; + break; - // Try absolute path - newLocationState = LDrawLoader.FILE_LOCATION_NOT_FOUND; + case FILE_LOCATION_TRY_ABSOLUTE: - } else { + if ( subobject.triedLowerCase ) { - // Next attempt is lower case - subobject.fileName = subobject.fileName.toLowerCase(); - subobjectURL = subobject.fileName; - subobject.triedLowerCase = true; - newLocationState = LDrawLoader.FILE_LOCATION_AS_IS; + // Try absolute path + newLocationState = FILE_LOCATION_NOT_FOUND; - } + } else { - break; + // Next attempt is lower case + subobject.fileName = subobject.fileName.toLowerCase(); + subobjectURL = subobject.fileName; + subobject.triedLowerCase = true; + newLocationState = FILE_LOCATION_AS_IS; - case LDrawLoader.FILE_LOCATION_NOT_FOUND: + } - // All location possibilities have been tried, give up loading this object - console.warn( 'LDrawLoader: Subobject "' + subobject.originalFileName + '" could not be found.' ); + break; - return; + case FILE_LOCATION_NOT_FOUND: - } + // All location possibilities have been tried, give up loading this object + console.warn( 'LDrawLoader: Subobject "' + subobject.originalFileName + '" could not be found.' ); - subobject.locationState = newLocationState; - subobject.url = subobjectURL; + return; - // Load the subobject - // Use another file loader here so we can keep track of the subobject information - // and use it when processing the next model. - var fileLoader = new FileLoader( scope.manager ); - fileLoader.setPath( scope.path ); - fileLoader.setRequestHeader( scope.requestHeader ); - fileLoader.setWithCredentials( scope.withCredentials ); - fileLoader.load( subobjectURL, function ( text ) { + } - scope.processObject( text, function ( subobjectGroup ) { + subobject.locationState = newLocationState; + subobject.url = subobjectURL; - onSubobjectLoaded( subobjectGroup, subobject ); - onSubobjectFinish(); + // Load the subobject + // Use another file loader here so we can keep track of the subobject information + // and use it when processing the next model. + const fileLoader = new FileLoader( scope.manager ); + fileLoader.setPath( scope.path ); + fileLoader.setRequestHeader( scope.requestHeader ); + fileLoader.setWithCredentials( scope.withCredentials ); + fileLoader.load( subobjectURL, function ( text ) { - }, subobject, url ); + scope.processObject( text, function ( subobjectGroup ) { - }, undefined, function ( err ) { + onSubobjectLoaded( subobjectGroup, subobject ); + onSubobjectFinish(); - onSubobjectError( err, subobject ); + }, subobject, url ); - }, subobject ); + }, undefined, function ( err ) { - } + onSubobjectError( err, subobject ); - function onSubobjectLoaded( subobjectGroup, subobject ) { + }, subobject ); - if ( subobjectGroup === null ) { + } - // Try to reload - loadSubobject( subobject ); - return; + function onSubobjectLoaded( subobjectGroup, subobject ) { - } + if ( subobjectGroup === null ) { - scope.fileMap[ subobject.originalFileName ] = subobject.url; + // Try to reload + loadSubobject( subobject ); + return; } - function onSubobjectError( err, subobject ) { + scope.fileMap[ subobject.originalFileName ] = subobject.url; - // Retry download from a different default possible location - loadSubobject( subobject ); + } - } + function onSubobjectError( err, subobject ) { - } + // Retry download from a different default possible location + loadSubobject( subobject ); - } ); + } - return LDrawLoader; + } -} )(); +} export { LDrawLoader }; diff --git a/examples/jsm/loaders/LWOLoader.js b/examples/jsm/loaders/LWOLoader.js index 3c8e38ddf2718b..93434d50641e7f 100644 --- a/examples/jsm/loaders/LWOLoader.js +++ b/examples/jsm/loaders/LWOLoader.js @@ -41,32 +41,28 @@ import { import { IFFParser } from './lwo/IFFParser.js'; -var lwoTree; +let _lwoTree; -var LWOLoader = function ( manager, parameters ) { +class LWOLoader extends Loader { - Loader.call( this, manager ); + constructor( manager, parameters = {} ) { - parameters = parameters || {}; + super( manager ); - this.resourcePath = ( parameters.resourcePath !== undefined ) ? parameters.resourcePath : ''; + this.resourcePath = ( parameters.resourcePath !== undefined ) ? parameters.resourcePath : ''; -}; - -LWOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: LWOLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var path = ( scope.path === '' ) ? extractParentUrl( url, 'Objects' ) : scope.path; + const path = ( scope.path === '' ) ? extractParentUrl( url, 'Objects' ) : scope.path; // give the mesh a default name based on the filename - var modelName = url.split( path ).pop().split( '.' )[ 0 ]; + const modelName = url.split( path ).pop().split( '.' )[ 0 ]; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); @@ -98,34 +94,32 @@ LWOLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( iffBuffer, path, modelName ) { + parse( iffBuffer, path, modelName ) { - lwoTree = new IFFParser().parse( iffBuffer ); + _lwoTree = new IFFParser().parse( iffBuffer ); // console.log( 'lwoTree', lwoTree ); - var textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); + const textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); return new LWOTreeParser( textureLoader ).parse( modelName ); } -} ); +} // Parse the lwoTree object -function LWOTreeParser( textureLoader ) { - - this.textureLoader = textureLoader; +class LWOTreeParser { -} + constructor( textureLoader ) { -LWOTreeParser.prototype = { + this.textureLoader = textureLoader; - constructor: LWOTreeParser, + } - parse: function ( modelName ) { + parse( modelName ) { this.materials = new MaterialParser( this.textureLoader ).parse(); this.defaultLayerName = modelName; @@ -137,24 +131,24 @@ LWOTreeParser.prototype = { meshes: this.meshes, }; - }, + } parseLayers() { // array of all meshes for building hierarchy - var meshes = []; + const meshes = []; // final array containing meshes with scene graph hierarchy set up - var finalMeshes = []; + const finalMeshes = []; - var geometryParser = new GeometryParser(); + const geometryParser = new GeometryParser(); - var scope = this; - lwoTree.layers.forEach( function ( layer ) { + const scope = this; + _lwoTree.layers.forEach( function ( layer ) { - var geometry = geometryParser.parse( layer.geometry, layer ); + const geometry = geometryParser.parse( layer.geometry, layer ); - var mesh = scope.parseMesh( geometry, layer ); + const mesh = scope.parseMesh( geometry, layer ); meshes[ layer.number ] = mesh; @@ -168,13 +162,13 @@ LWOTreeParser.prototype = { return finalMeshes; - }, + } parseMesh( geometry, layer ) { - var mesh; + let mesh; - var materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type ); + const materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type ); this.duplicateUVs( geometry, materials ); @@ -189,7 +183,7 @@ LWOTreeParser.prototype = { return mesh; - }, + } // TODO: may need to be reversed in z to convert LWO to three.js coordinates applyPivots( meshes ) { @@ -198,7 +192,7 @@ LWOTreeParser.prototype = { mesh.traverse( function ( child ) { - var pivot = child.userData.pivot; + const pivot = child.userData.pivot; child.position.x += pivot[ 0 ]; child.position.y += pivot[ 1 ]; @@ -206,7 +200,7 @@ LWOTreeParser.prototype = { if ( child.parent ) { - var parentPivot = child.parent.userData.pivot; + const parentPivot = child.parent.userData.pivot; child.position.x -= parentPivot[ 0 ]; child.position.y -= parentPivot[ 1 ]; @@ -218,13 +212,13 @@ LWOTreeParser.prototype = { } ); - }, + } getMaterials( namesArray, type ) { - var materials = []; + const materials = []; - var scope = this; + const scope = this; namesArray.forEach( function ( name, i ) { @@ -237,7 +231,7 @@ LWOTreeParser.prototype = { materials.forEach( function ( mat, i ) { - var spec = { + const spec = { color: mat.color, }; @@ -259,12 +253,12 @@ LWOTreeParser.prototype = { } // if there is only one material, return that directly instead of array - var filtered = materials.filter( Boolean ); + const filtered = materials.filter( Boolean ); if ( filtered.length === 1 ) return filtered[ 0 ]; return materials; - }, + } getMaterialByName( name ) { @@ -274,12 +268,12 @@ LWOTreeParser.prototype = { } )[ 0 ]; - }, + } // If the material has an aoMap, duplicate UVs duplicateUVs( geometry, materials ) { - var duplicateUVs = false; + let duplicateUVs = false; if ( ! Array.isArray( materials ) ) { @@ -299,34 +293,32 @@ LWOTreeParser.prototype = { geometry.setAttribute( 'uv2', new BufferAttribute( geometry.attributes.uv.array, 2 ) ); - }, - -}; + } -function MaterialParser( textureLoader ) { +} - this.textureLoader = textureLoader; +class MaterialParser { -} + constructor( textureLoader ) { -MaterialParser.prototype = { + this.textureLoader = textureLoader; - constructor: MaterialParser, + } - parse: function () { + parse() { - var materials = []; + const materials = []; this.textures = {}; - for ( var name in lwoTree.materials ) { + for ( const name in _lwoTree.materials ) { - if ( lwoTree.format === 'LWO3' ) { + if ( _lwoTree.format === 'LWO3' ) { - materials.push( this.parseMaterial( lwoTree.materials[ name ], name, lwoTree.textures ) ); + materials.push( this.parseMaterial( _lwoTree.materials[ name ], name, _lwoTree.textures ) ); - } else if ( lwoTree.format === 'LWO2' ) { + } else if ( _lwoTree.format === 'LWO2' ) { - materials.push( this.parseMaterialLwo2( lwoTree.materials[ name ], name, lwoTree.textures ) ); + materials.push( this.parseMaterialLwo2( _lwoTree.materials[ name ], name, _lwoTree.textures ) ); } @@ -334,48 +326,48 @@ MaterialParser.prototype = { return materials; - }, + } parseMaterial( materialData, name, textures ) { - var params = { + let params = { name: name, side: this.getSide( materialData.attributes ), flatShading: this.getSmooth( materialData.attributes ), }; - var connections = this.parseConnections( materialData.connections, materialData.nodes ); + const connections = this.parseConnections( materialData.connections, materialData.nodes ); - var maps = this.parseTextureNodes( connections.maps ); + const maps = this.parseTextureNodes( connections.maps ); this.parseAttributeImageMaps( connections.attributes, textures, maps, materialData.maps ); - var attributes = this.parseAttributes( connections.attributes, maps ); + const attributes = this.parseAttributes( connections.attributes, maps ); this.parseEnvMap( connections, maps, attributes ); params = Object.assign( maps, params ); params = Object.assign( params, attributes ); - var materialType = this.getMaterialType( connections.attributes ); + const materialType = this.getMaterialType( connections.attributes ); return new materialType( params ); - }, + } parseMaterialLwo2( materialData, name/*, textures*/ ) { - var params = { + let params = { name: name, side: this.getSide( materialData.attributes ), flatShading: this.getSmooth( materialData.attributes ), }; - var attributes = this.parseAttributes( materialData.attributes, {} ); + const attributes = this.parseAttributes( materialData.attributes, {} ); params = Object.assign( params, attributes ); return new MeshPhongMaterial( params ); - }, + } // Note: converting from left to right handed coords by switching x -> -x in vertices, and // then switching mat FrontSide -> BackSide @@ -394,31 +386,31 @@ MaterialParser.prototype = { } - }, + } getSmooth( attributes ) { if ( ! attributes.smooth ) return true; return ! attributes.smooth; - }, + } parseConnections( connections, nodes ) { - var materialConnections = { + const materialConnections = { maps: {} }; - var inputName = connections.inputName; - var inputNodeName = connections.inputNodeName; - var nodeName = connections.nodeName; + const inputName = connections.inputName; + const inputNodeName = connections.inputNodeName; + const nodeName = connections.nodeName; - var scope = this; + const scope = this; inputName.forEach( function ( name, index ) { if ( name === 'Material' ) { - var matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes ); + const matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes ); materialConnections.attributes = matNode.attributes; materialConnections.envMap = matNode.fileName; materialConnections.name = inputNodeName[ index ]; @@ -439,30 +431,30 @@ MaterialParser.prototype = { return materialConnections; - }, + } getNodeByRefName( refName, nodes ) { - for ( var name in nodes ) { + for ( const name in nodes ) { if ( nodes[ name ].refName === refName ) return nodes[ name ]; } - }, + } parseTextureNodes( textureNodes ) { - var maps = {}; + const maps = {}; - for ( var name in textureNodes ) { + for ( const name in textureNodes ) { - var node = textureNodes[ name ]; - var path = node.fileName; + const node = textureNodes[ name ]; + const path = node.fileName; if ( ! path ) return; - var texture = this.loadTexture( path ); + const texture = this.loadTexture( path ); if ( node.widthWrappingMode !== undefined ) texture.wrapS = this.getWrappingType( node.widthWrappingMode ); if ( node.heightWrappingMode !== undefined ) texture.wrapT = this.getWrappingType( node.heightWrappingMode ); @@ -513,24 +505,24 @@ MaterialParser.prototype = { return maps; - }, + } // maps can also be defined on individual material attributes, parse those here // This occurs on Standard (Phong) surfaces parseAttributeImageMaps( attributes, textures, maps ) { - for ( var name in attributes ) { + for ( const name in attributes ) { - var attribute = attributes[ name ]; + const attribute = attributes[ name ]; if ( attribute.maps ) { - var mapData = attribute.maps[ 0 ]; + const mapData = attribute.maps[ 0 ]; - var path = this.getTexturePathByIndex( mapData.imageIndex, textures ); + const path = this.getTexturePathByIndex( mapData.imageIndex, textures ); if ( ! path ) return; - var texture = this.loadTexture( path ); + const texture = this.loadTexture( path ); if ( mapData.wrap !== undefined ) texture.wrapS = this.getWrappingType( mapData.wrap.w ); if ( mapData.wrap !== undefined ) texture.wrapT = this.getWrappingType( mapData.wrap.h ); @@ -577,11 +569,11 @@ MaterialParser.prototype = { } - }, + } parseAttributes( attributes, maps ) { - var params = {}; + const params = {}; // don't use color data if color map is present if ( attributes.Color && ! maps.map ) { @@ -608,7 +600,7 @@ MaterialParser.prototype = { return params; - }, + } parsePhysicalAttributes( params, attributes/*, maps*/ ) { @@ -624,7 +616,7 @@ MaterialParser.prototype = { } - }, + } parseStandardAttributes( params, attributes, maps ) { @@ -648,7 +640,7 @@ MaterialParser.prototype = { if ( attributes.Roughness && ! maps.roughnessMap ) params.roughness = attributes.Roughness.value; if ( attributes.Metallic && ! maps.metalnessMap ) params.metalness = attributes.Metallic.value; - }, + } parsePhongAttributes( params, attributes, maps ) { @@ -694,13 +686,13 @@ MaterialParser.prototype = { if ( params.specular && attributes.Glossiness ) params.shininess = 7 + Math.pow( 2, attributes.Glossiness.value * 12 + 2 ); - }, + } parseEnvMap( connections, maps, attributes ) { if ( connections.envMap ) { - var envMap = this.loadTexture( connections.envMap ); + const envMap = this.loadTexture( connections.envMap ); if ( attributes.transparent && attributes.opacity < 0.999 ) { @@ -726,16 +718,16 @@ MaterialParser.prototype = { } - }, + } // get texture defined at top level by its index getTexturePathByIndex( index ) { - var fileName = ''; + let fileName = ''; - if ( ! lwoTree.textures ) return fileName; + if ( ! _lwoTree.textures ) return fileName; - lwoTree.textures.forEach( function ( texture ) { + _lwoTree.textures.forEach( function ( texture ) { if ( texture.index === index ) fileName = texture.fileName; @@ -743,15 +735,13 @@ MaterialParser.prototype = { return fileName; - }, + } loadTexture( path ) { if ( ! path ) return null; - var texture; - - texture = this.textureLoader.load( + const texture = this.textureLoader.load( path, undefined, undefined, @@ -764,7 +754,7 @@ MaterialParser.prototype = { return texture; - }, + } // 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge getWrappingType( num ) { @@ -780,7 +770,7 @@ MaterialParser.prototype = { } - }, + } getMaterialType( nodeData ) { @@ -790,21 +780,17 @@ MaterialParser.prototype = { } -}; - -function GeometryParser() {} - -GeometryParser.prototype = { +} - constructor: GeometryParser, +class GeometryParser { parse( geoData, layer ) { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new Float32BufferAttribute( geoData.points, 3 ) ); - var indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions ); + const indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions ); geometry.setIndex( indices ); this.parseGroups( geometry, geoData ); @@ -817,25 +803,25 @@ GeometryParser.prototype = { // TODO: z may need to be reversed to account for coordinate system change geometry.translate( - layer.pivot[ 0 ], - layer.pivot[ 1 ], - layer.pivot[ 2 ] ); - // var userData = geometry.userData; + // let userData = geometry.userData; // geometry = geometry.toNonIndexed() // geometry.userData = userData; return geometry; - }, + } // split quads into tris splitIndices( indices, polygonDimensions ) { - var remappedIndices = []; + const remappedIndices = []; - var i = 0; + let i = 0; polygonDimensions.forEach( function ( dim ) { if ( dim < 4 ) { - for ( var k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] ); + for ( let k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] ); } else if ( dim === 4 ) { @@ -852,7 +838,7 @@ GeometryParser.prototype = { } else if ( dim > 4 ) { - for ( var k = 1; k < dim - 1; k ++ ) { + for ( let k = 1; k < dim - 1; k ++ ) { remappedIndices.push( indices[ i ], indices[ i + k ], indices[ i + k + 1 ] ); @@ -868,31 +854,32 @@ GeometryParser.prototype = { return remappedIndices; - }, + } // NOTE: currently ignoring poly indices and assuming that they are intelligently ordered parseGroups( geometry, geoData ) { - var tags = lwoTree.tags; - var matNames = []; + const tags = _lwoTree.tags; + const matNames = []; - var elemSize = 3; + let elemSize = 3; if ( geoData.type === 'lines' ) elemSize = 2; if ( geoData.type === 'points' ) elemSize = 1; - var remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices ); + const remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices ); - var indexNum = 0; // create new indices in numerical order - var indexPairs = {}; // original indices mapped to numerical indices + let indexNum = 0; // create new indices in numerical order + const indexPairs = {}; // original indices mapped to numerical indices - var prevMaterialIndex; + let prevMaterialIndex; + let materialIndex; - var prevStart = 0; - var currentCount = 0; + let prevStart = 0; + let currentCount = 0; - for ( var i = 0; i < remappedIndices.length; i += 2 ) { + for ( let i = 0; i < remappedIndices.length; i += 2 ) { - var materialIndex = remappedIndices[ i + 1 ]; + materialIndex = remappedIndices[ i + 1 ]; if ( i === 0 ) matNames[ indexNum ] = tags[ materialIndex ]; @@ -900,7 +887,7 @@ GeometryParser.prototype = { if ( materialIndex !== prevMaterialIndex ) { - var currentIndex; + let currentIndex; if ( indexPairs[ tags[ prevMaterialIndex ] ] ) { currentIndex = indexPairs[ tags[ prevMaterialIndex ] ]; @@ -930,7 +917,7 @@ GeometryParser.prototype = { // the loop above doesn't add the last group, do that here. if ( geometry.groups.length > 0 ) { - var currentIndex; + let currentIndex; if ( indexPairs[ tags[ materialIndex ] ] ) { currentIndex = indexPairs[ tags[ materialIndex ] ]; @@ -950,11 +937,11 @@ GeometryParser.prototype = { // Mat names from TAGS chunk, used to build up an array of materials for this geometry geometry.userData.matNames = matNames; - }, + } splitMaterialIndices( polygonDimensions, indices ) { - var remappedIndices = []; + const remappedIndices = []; polygonDimensions.forEach( function ( dim, i ) { @@ -969,7 +956,7 @@ GeometryParser.prototype = { } else { // ignore > 4 for now - for ( var k = 0; k < dim - 2; k ++ ) { + for ( let k = 0; k < dim - 2; k ++ ) { remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ] ); @@ -981,7 +968,7 @@ GeometryParser.prototype = { return remappedIndices; - }, + } // UV maps: // 1: are defined via index into an array of points, not into a geometry @@ -995,16 +982,16 @@ GeometryParser.prototype = { parseUVs( geometry, layer ) { // start by creating a UV map set to zero for the whole geometry - var remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () { + const remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () { return 0; } ); - for ( var name in layer.uvs ) { + for ( const name in layer.uvs ) { - var uvs = layer.uvs[ name ].uvs; - var uvIndices = layer.uvs[ name ].uvIndices; + const uvs = layer.uvs[ name ].uvs; + const uvIndices = layer.uvs[ name ].uvIndices; uvIndices.forEach( function ( i, j ) { @@ -1017,20 +1004,20 @@ GeometryParser.prototype = { geometry.setAttribute( 'uv', new Float32BufferAttribute( remappedUVs, 2 ) ); - }, + } parseMorphTargets( geometry, layer ) { - var num = 0; - for ( var name in layer.morphTargets ) { + let num = 0; + for ( const name in layer.morphTargets ) { - var remappedPoints = geometry.attributes.position.array.slice(); + const remappedPoints = geometry.attributes.position.array.slice(); if ( ! geometry.morphAttributes.position ) geometry.morphAttributes.position = []; - var morphPoints = layer.morphTargets[ name ].points; - var morphIndices = layer.morphTargets[ name ].indices; - var type = layer.morphTargets[ name ].type; + const morphPoints = layer.morphTargets[ name ].points; + const morphIndices = layer.morphTargets[ name ].indices; + const type = layer.morphTargets[ name ].type; morphIndices.forEach( function ( i, j ) { @@ -1059,16 +1046,16 @@ GeometryParser.prototype = { geometry.morphTargetsRelative = false; - }, + } -}; +} // ************** UTILITY FUNCTIONS ************** function extractParentUrl( url, dir ) { - var index = url.indexOf( dir ); + const index = url.indexOf( dir ); if ( index === - 1 ) return './'; diff --git a/examples/jsm/loaders/LottieLoader.js b/examples/jsm/loaders/LottieLoader.js index b40cbc70098047..ab14db6733c879 100644 --- a/examples/jsm/loaders/LottieLoader.js +++ b/examples/jsm/loaders/LottieLoader.js @@ -36,7 +36,6 @@ class LottieLoader extends Loader { container.style.height = data.h + 'px'; document.body.appendChild( container ); - // eslint-disable-next-line no-undef const animation = bodymovin.loadAnimation( { container: container, animType: 'canvas', diff --git a/examples/jsm/loaders/MD2Loader.js b/examples/jsm/loaders/MD2Loader.js index 38850caf7342d3..b0c7248dea1501 100644 --- a/examples/jsm/loaders/MD2Loader.js +++ b/examples/jsm/loaders/MD2Loader.js @@ -7,21 +7,103 @@ import { Vector3 } from '../../../build/three.module.js'; -var MD2Loader = function ( manager ) { - - Loader.call( this, manager ); - -}; - -MD2Loader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: MD2Loader, - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new FileLoader( scope.manager ); +const _normalData = [ + [ - 0.525731, 0.000000, 0.850651 ], [ - 0.442863, 0.238856, 0.864188 ], + [ - 0.295242, 0.000000, 0.955423 ], [ - 0.309017, 0.500000, 0.809017 ], + [ - 0.162460, 0.262866, 0.951056 ], [ 0.000000, 0.000000, 1.000000 ], + [ 0.000000, 0.850651, 0.525731 ], [ - 0.147621, 0.716567, 0.681718 ], + [ 0.147621, 0.716567, 0.681718 ], [ 0.000000, 0.525731, 0.850651 ], + [ 0.309017, 0.500000, 0.809017 ], [ 0.525731, 0.000000, 0.850651 ], + [ 0.295242, 0.000000, 0.955423 ], [ 0.442863, 0.238856, 0.864188 ], + [ 0.162460, 0.262866, 0.951056 ], [ - 0.681718, 0.147621, 0.716567 ], + [ - 0.809017, 0.309017, 0.500000 ], [ - 0.587785, 0.425325, 0.688191 ], + [ - 0.850651, 0.525731, 0.000000 ], [ - 0.864188, 0.442863, 0.238856 ], + [ - 0.716567, 0.681718, 0.147621 ], [ - 0.688191, 0.587785, 0.425325 ], + [ - 0.500000, 0.809017, 0.309017 ], [ - 0.238856, 0.864188, 0.442863 ], + [ - 0.425325, 0.688191, 0.587785 ], [ - 0.716567, 0.681718, - 0.147621 ], + [ - 0.500000, 0.809017, - 0.309017 ], [ - 0.525731, 0.850651, 0.000000 ], + [ 0.000000, 0.850651, - 0.525731 ], [ - 0.238856, 0.864188, - 0.442863 ], + [ 0.000000, 0.955423, - 0.295242 ], [ - 0.262866, 0.951056, - 0.162460 ], + [ 0.000000, 1.000000, 0.000000 ], [ 0.000000, 0.955423, 0.295242 ], + [ - 0.262866, 0.951056, 0.162460 ], [ 0.238856, 0.864188, 0.442863 ], + [ 0.262866, 0.951056, 0.162460 ], [ 0.500000, 0.809017, 0.309017 ], + [ 0.238856, 0.864188, - 0.442863 ], [ 0.262866, 0.951056, - 0.162460 ], + [ 0.500000, 0.809017, - 0.309017 ], [ 0.850651, 0.525731, 0.000000 ], + [ 0.716567, 0.681718, 0.147621 ], [ 0.716567, 0.681718, - 0.147621 ], + [ 0.525731, 0.850651, 0.000000 ], [ 0.425325, 0.688191, 0.587785 ], + [ 0.864188, 0.442863, 0.238856 ], [ 0.688191, 0.587785, 0.425325 ], + [ 0.809017, 0.309017, 0.500000 ], [ 0.681718, 0.147621, 0.716567 ], + [ 0.587785, 0.425325, 0.688191 ], [ 0.955423, 0.295242, 0.000000 ], + [ 1.000000, 0.000000, 0.000000 ], [ 0.951056, 0.162460, 0.262866 ], + [ 0.850651, - 0.525731, 0.000000 ], [ 0.955423, - 0.295242, 0.000000 ], + [ 0.864188, - 0.442863, 0.238856 ], [ 0.951056, - 0.162460, 0.262866 ], + [ 0.809017, - 0.309017, 0.500000 ], [ 0.681718, - 0.147621, 0.716567 ], + [ 0.850651, 0.000000, 0.525731 ], [ 0.864188, 0.442863, - 0.238856 ], + [ 0.809017, 0.309017, - 0.500000 ], [ 0.951056, 0.162460, - 0.262866 ], + [ 0.525731, 0.000000, - 0.850651 ], [ 0.681718, 0.147621, - 0.716567 ], + [ 0.681718, - 0.147621, - 0.716567 ], [ 0.850651, 0.000000, - 0.525731 ], + [ 0.809017, - 0.309017, - 0.500000 ], [ 0.864188, - 0.442863, - 0.238856 ], + [ 0.951056, - 0.162460, - 0.262866 ], [ 0.147621, 0.716567, - 0.681718 ], + [ 0.309017, 0.500000, - 0.809017 ], [ 0.425325, 0.688191, - 0.587785 ], + [ 0.442863, 0.238856, - 0.864188 ], [ 0.587785, 0.425325, - 0.688191 ], + [ 0.688191, 0.587785, - 0.425325 ], [ - 0.147621, 0.716567, - 0.681718 ], + [ - 0.309017, 0.500000, - 0.809017 ], [ 0.000000, 0.525731, - 0.850651 ], + [ - 0.525731, 0.000000, - 0.850651 ], [ - 0.442863, 0.238856, - 0.864188 ], + [ - 0.295242, 0.000000, - 0.955423 ], [ - 0.162460, 0.262866, - 0.951056 ], + [ 0.000000, 0.000000, - 1.000000 ], [ 0.295242, 0.000000, - 0.955423 ], + [ 0.162460, 0.262866, - 0.951056 ], [ - 0.442863, - 0.238856, - 0.864188 ], + [ - 0.309017, - 0.500000, - 0.809017 ], [ - 0.162460, - 0.262866, - 0.951056 ], + [ 0.000000, - 0.850651, - 0.525731 ], [ - 0.147621, - 0.716567, - 0.681718 ], + [ 0.147621, - 0.716567, - 0.681718 ], [ 0.000000, - 0.525731, - 0.850651 ], + [ 0.309017, - 0.500000, - 0.809017 ], [ 0.442863, - 0.238856, - 0.864188 ], + [ 0.162460, - 0.262866, - 0.951056 ], [ 0.238856, - 0.864188, - 0.442863 ], + [ 0.500000, - 0.809017, - 0.309017 ], [ 0.425325, - 0.688191, - 0.587785 ], + [ 0.716567, - 0.681718, - 0.147621 ], [ 0.688191, - 0.587785, - 0.425325 ], + [ 0.587785, - 0.425325, - 0.688191 ], [ 0.000000, - 0.955423, - 0.295242 ], + [ 0.000000, - 1.000000, 0.000000 ], [ 0.262866, - 0.951056, - 0.162460 ], + [ 0.000000, - 0.850651, 0.525731 ], [ 0.000000, - 0.955423, 0.295242 ], + [ 0.238856, - 0.864188, 0.442863 ], [ 0.262866, - 0.951056, 0.162460 ], + [ 0.500000, - 0.809017, 0.309017 ], [ 0.716567, - 0.681718, 0.147621 ], + [ 0.525731, - 0.850651, 0.000000 ], [ - 0.238856, - 0.864188, - 0.442863 ], + [ - 0.500000, - 0.809017, - 0.309017 ], [ - 0.262866, - 0.951056, - 0.162460 ], + [ - 0.850651, - 0.525731, 0.000000 ], [ - 0.716567, - 0.681718, - 0.147621 ], + [ - 0.716567, - 0.681718, 0.147621 ], [ - 0.525731, - 0.850651, 0.000000 ], + [ - 0.500000, - 0.809017, 0.309017 ], [ - 0.238856, - 0.864188, 0.442863 ], + [ - 0.262866, - 0.951056, 0.162460 ], [ - 0.864188, - 0.442863, 0.238856 ], + [ - 0.809017, - 0.309017, 0.500000 ], [ - 0.688191, - 0.587785, 0.425325 ], + [ - 0.681718, - 0.147621, 0.716567 ], [ - 0.442863, - 0.238856, 0.864188 ], + [ - 0.587785, - 0.425325, 0.688191 ], [ - 0.309017, - 0.500000, 0.809017 ], + [ - 0.147621, - 0.716567, 0.681718 ], [ - 0.425325, - 0.688191, 0.587785 ], + [ - 0.162460, - 0.262866, 0.951056 ], [ 0.442863, - 0.238856, 0.864188 ], + [ 0.162460, - 0.262866, 0.951056 ], [ 0.309017, - 0.500000, 0.809017 ], + [ 0.147621, - 0.716567, 0.681718 ], [ 0.000000, - 0.525731, 0.850651 ], + [ 0.425325, - 0.688191, 0.587785 ], [ 0.587785, - 0.425325, 0.688191 ], + [ 0.688191, - 0.587785, 0.425325 ], [ - 0.955423, 0.295242, 0.000000 ], + [ - 0.951056, 0.162460, 0.262866 ], [ - 1.000000, 0.000000, 0.000000 ], + [ - 0.850651, 0.000000, 0.525731 ], [ - 0.955423, - 0.295242, 0.000000 ], + [ - 0.951056, - 0.162460, 0.262866 ], [ - 0.864188, 0.442863, - 0.238856 ], + [ - 0.951056, 0.162460, - 0.262866 ], [ - 0.809017, 0.309017, - 0.500000 ], + [ - 0.864188, - 0.442863, - 0.238856 ], [ - 0.951056, - 0.162460, - 0.262866 ], + [ - 0.809017, - 0.309017, - 0.500000 ], [ - 0.681718, 0.147621, - 0.716567 ], + [ - 0.681718, - 0.147621, - 0.716567 ], [ - 0.850651, 0.000000, - 0.525731 ], + [ - 0.688191, 0.587785, - 0.425325 ], [ - 0.587785, 0.425325, - 0.688191 ], + [ - 0.425325, 0.688191, - 0.587785 ], [ - 0.425325, - 0.688191, - 0.587785 ], + [ - 0.587785, - 0.425325, - 0.688191 ], [ - 0.688191, - 0.587785, - 0.425325 ] +]; + +class MD2Loader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -50,355 +132,267 @@ MD2Loader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, - - parse: ( function () { - - var normalData = [ - [ - 0.525731, 0.000000, 0.850651 ], [ - 0.442863, 0.238856, 0.864188 ], - [ - 0.295242, 0.000000, 0.955423 ], [ - 0.309017, 0.500000, 0.809017 ], - [ - 0.162460, 0.262866, 0.951056 ], [ 0.000000, 0.000000, 1.000000 ], - [ 0.000000, 0.850651, 0.525731 ], [ - 0.147621, 0.716567, 0.681718 ], - [ 0.147621, 0.716567, 0.681718 ], [ 0.000000, 0.525731, 0.850651 ], - [ 0.309017, 0.500000, 0.809017 ], [ 0.525731, 0.000000, 0.850651 ], - [ 0.295242, 0.000000, 0.955423 ], [ 0.442863, 0.238856, 0.864188 ], - [ 0.162460, 0.262866, 0.951056 ], [ - 0.681718, 0.147621, 0.716567 ], - [ - 0.809017, 0.309017, 0.500000 ], [ - 0.587785, 0.425325, 0.688191 ], - [ - 0.850651, 0.525731, 0.000000 ], [ - 0.864188, 0.442863, 0.238856 ], - [ - 0.716567, 0.681718, 0.147621 ], [ - 0.688191, 0.587785, 0.425325 ], - [ - 0.500000, 0.809017, 0.309017 ], [ - 0.238856, 0.864188, 0.442863 ], - [ - 0.425325, 0.688191, 0.587785 ], [ - 0.716567, 0.681718, - 0.147621 ], - [ - 0.500000, 0.809017, - 0.309017 ], [ - 0.525731, 0.850651, 0.000000 ], - [ 0.000000, 0.850651, - 0.525731 ], [ - 0.238856, 0.864188, - 0.442863 ], - [ 0.000000, 0.955423, - 0.295242 ], [ - 0.262866, 0.951056, - 0.162460 ], - [ 0.000000, 1.000000, 0.000000 ], [ 0.000000, 0.955423, 0.295242 ], - [ - 0.262866, 0.951056, 0.162460 ], [ 0.238856, 0.864188, 0.442863 ], - [ 0.262866, 0.951056, 0.162460 ], [ 0.500000, 0.809017, 0.309017 ], - [ 0.238856, 0.864188, - 0.442863 ], [ 0.262866, 0.951056, - 0.162460 ], - [ 0.500000, 0.809017, - 0.309017 ], [ 0.850651, 0.525731, 0.000000 ], - [ 0.716567, 0.681718, 0.147621 ], [ 0.716567, 0.681718, - 0.147621 ], - [ 0.525731, 0.850651, 0.000000 ], [ 0.425325, 0.688191, 0.587785 ], - [ 0.864188, 0.442863, 0.238856 ], [ 0.688191, 0.587785, 0.425325 ], - [ 0.809017, 0.309017, 0.500000 ], [ 0.681718, 0.147621, 0.716567 ], - [ 0.587785, 0.425325, 0.688191 ], [ 0.955423, 0.295242, 0.000000 ], - [ 1.000000, 0.000000, 0.000000 ], [ 0.951056, 0.162460, 0.262866 ], - [ 0.850651, - 0.525731, 0.000000 ], [ 0.955423, - 0.295242, 0.000000 ], - [ 0.864188, - 0.442863, 0.238856 ], [ 0.951056, - 0.162460, 0.262866 ], - [ 0.809017, - 0.309017, 0.500000 ], [ 0.681718, - 0.147621, 0.716567 ], - [ 0.850651, 0.000000, 0.525731 ], [ 0.864188, 0.442863, - 0.238856 ], - [ 0.809017, 0.309017, - 0.500000 ], [ 0.951056, 0.162460, - 0.262866 ], - [ 0.525731, 0.000000, - 0.850651 ], [ 0.681718, 0.147621, - 0.716567 ], - [ 0.681718, - 0.147621, - 0.716567 ], [ 0.850651, 0.000000, - 0.525731 ], - [ 0.809017, - 0.309017, - 0.500000 ], [ 0.864188, - 0.442863, - 0.238856 ], - [ 0.951056, - 0.162460, - 0.262866 ], [ 0.147621, 0.716567, - 0.681718 ], - [ 0.309017, 0.500000, - 0.809017 ], [ 0.425325, 0.688191, - 0.587785 ], - [ 0.442863, 0.238856, - 0.864188 ], [ 0.587785, 0.425325, - 0.688191 ], - [ 0.688191, 0.587785, - 0.425325 ], [ - 0.147621, 0.716567, - 0.681718 ], - [ - 0.309017, 0.500000, - 0.809017 ], [ 0.000000, 0.525731, - 0.850651 ], - [ - 0.525731, 0.000000, - 0.850651 ], [ - 0.442863, 0.238856, - 0.864188 ], - [ - 0.295242, 0.000000, - 0.955423 ], [ - 0.162460, 0.262866, - 0.951056 ], - [ 0.000000, 0.000000, - 1.000000 ], [ 0.295242, 0.000000, - 0.955423 ], - [ 0.162460, 0.262866, - 0.951056 ], [ - 0.442863, - 0.238856, - 0.864188 ], - [ - 0.309017, - 0.500000, - 0.809017 ], [ - 0.162460, - 0.262866, - 0.951056 ], - [ 0.000000, - 0.850651, - 0.525731 ], [ - 0.147621, - 0.716567, - 0.681718 ], - [ 0.147621, - 0.716567, - 0.681718 ], [ 0.000000, - 0.525731, - 0.850651 ], - [ 0.309017, - 0.500000, - 0.809017 ], [ 0.442863, - 0.238856, - 0.864188 ], - [ 0.162460, - 0.262866, - 0.951056 ], [ 0.238856, - 0.864188, - 0.442863 ], - [ 0.500000, - 0.809017, - 0.309017 ], [ 0.425325, - 0.688191, - 0.587785 ], - [ 0.716567, - 0.681718, - 0.147621 ], [ 0.688191, - 0.587785, - 0.425325 ], - [ 0.587785, - 0.425325, - 0.688191 ], [ 0.000000, - 0.955423, - 0.295242 ], - [ 0.000000, - 1.000000, 0.000000 ], [ 0.262866, - 0.951056, - 0.162460 ], - [ 0.000000, - 0.850651, 0.525731 ], [ 0.000000, - 0.955423, 0.295242 ], - [ 0.238856, - 0.864188, 0.442863 ], [ 0.262866, - 0.951056, 0.162460 ], - [ 0.500000, - 0.809017, 0.309017 ], [ 0.716567, - 0.681718, 0.147621 ], - [ 0.525731, - 0.850651, 0.000000 ], [ - 0.238856, - 0.864188, - 0.442863 ], - [ - 0.500000, - 0.809017, - 0.309017 ], [ - 0.262866, - 0.951056, - 0.162460 ], - [ - 0.850651, - 0.525731, 0.000000 ], [ - 0.716567, - 0.681718, - 0.147621 ], - [ - 0.716567, - 0.681718, 0.147621 ], [ - 0.525731, - 0.850651, 0.000000 ], - [ - 0.500000, - 0.809017, 0.309017 ], [ - 0.238856, - 0.864188, 0.442863 ], - [ - 0.262866, - 0.951056, 0.162460 ], [ - 0.864188, - 0.442863, 0.238856 ], - [ - 0.809017, - 0.309017, 0.500000 ], [ - 0.688191, - 0.587785, 0.425325 ], - [ - 0.681718, - 0.147621, 0.716567 ], [ - 0.442863, - 0.238856, 0.864188 ], - [ - 0.587785, - 0.425325, 0.688191 ], [ - 0.309017, - 0.500000, 0.809017 ], - [ - 0.147621, - 0.716567, 0.681718 ], [ - 0.425325, - 0.688191, 0.587785 ], - [ - 0.162460, - 0.262866, 0.951056 ], [ 0.442863, - 0.238856, 0.864188 ], - [ 0.162460, - 0.262866, 0.951056 ], [ 0.309017, - 0.500000, 0.809017 ], - [ 0.147621, - 0.716567, 0.681718 ], [ 0.000000, - 0.525731, 0.850651 ], - [ 0.425325, - 0.688191, 0.587785 ], [ 0.587785, - 0.425325, 0.688191 ], - [ 0.688191, - 0.587785, 0.425325 ], [ - 0.955423, 0.295242, 0.000000 ], - [ - 0.951056, 0.162460, 0.262866 ], [ - 1.000000, 0.000000, 0.000000 ], - [ - 0.850651, 0.000000, 0.525731 ], [ - 0.955423, - 0.295242, 0.000000 ], - [ - 0.951056, - 0.162460, 0.262866 ], [ - 0.864188, 0.442863, - 0.238856 ], - [ - 0.951056, 0.162460, - 0.262866 ], [ - 0.809017, 0.309017, - 0.500000 ], - [ - 0.864188, - 0.442863, - 0.238856 ], [ - 0.951056, - 0.162460, - 0.262866 ], - [ - 0.809017, - 0.309017, - 0.500000 ], [ - 0.681718, 0.147621, - 0.716567 ], - [ - 0.681718, - 0.147621, - 0.716567 ], [ - 0.850651, 0.000000, - 0.525731 ], - [ - 0.688191, 0.587785, - 0.425325 ], [ - 0.587785, 0.425325, - 0.688191 ], - [ - 0.425325, 0.688191, - 0.587785 ], [ - 0.425325, - 0.688191, - 0.587785 ], - [ - 0.587785, - 0.425325, - 0.688191 ], [ - 0.688191, - 0.587785, - 0.425325 ] - ]; + } - return function ( buffer ) { + parse( buffer ) { - var data = new DataView( buffer ); + const data = new DataView( buffer ); - // http://tfc.duke.free.fr/coding/md2-specs-en.html + // http://tfc.duke.free.fr/coding/md2-specs-en.html - var header = {}; - var headerNames = [ - 'ident', 'version', - 'skinwidth', 'skinheight', - 'framesize', - 'num_skins', 'num_vertices', 'num_st', 'num_tris', 'num_glcmds', 'num_frames', - 'offset_skins', 'offset_st', 'offset_tris', 'offset_frames', 'offset_glcmds', 'offset_end' - ]; + const header = {}; + const headerNames = [ + 'ident', 'version', + 'skinwidth', 'skinheight', + 'framesize', + 'num_skins', 'num_vertices', 'num_st', 'num_tris', 'num_glcmds', 'num_frames', + 'offset_skins', 'offset_st', 'offset_tris', 'offset_frames', 'offset_glcmds', 'offset_end' + ]; - for ( var i = 0; i < headerNames.length; i ++ ) { + for ( let i = 0; i < headerNames.length; i ++ ) { - header[ headerNames[ i ] ] = data.getInt32( i * 4, true ); + header[ headerNames[ i ] ] = data.getInt32( i * 4, true ); - } + } - if ( header.ident !== 844121161 || header.version !== 8 ) { + if ( header.ident !== 844121161 || header.version !== 8 ) { - console.error( 'Not a valid MD2 file' ); - return; + console.error( 'Not a valid MD2 file' ); + return; - } + } - if ( header.offset_end !== data.byteLength ) { - - console.error( 'Corrupted MD2 file' ); - return; - - } + if ( header.offset_end !== data.byteLength ) { - // + console.error( 'Corrupted MD2 file' ); + return; - var geometry = new BufferGeometry(); + } - // uvs + // - var uvsTemp = []; - var offset = header.offset_st; + const geometry = new BufferGeometry(); - for ( var i = 0, l = header.num_st; i < l; i ++ ) { + // uvs - var u = data.getInt16( offset + 0, true ); - var v = data.getInt16( offset + 2, true ); + const uvsTemp = []; + let offset = header.offset_st; - uvsTemp.push( u / header.skinwidth, 1 - ( v / header.skinheight ) ); + for ( let i = 0, l = header.num_st; i < l; i ++ ) { - offset += 4; + const u = data.getInt16( offset + 0, true ); + const v = data.getInt16( offset + 2, true ); - } + uvsTemp.push( u / header.skinwidth, 1 - ( v / header.skinheight ) ); - // triangles + offset += 4; - offset = header.offset_tris; + } - var vertexIndices = []; - var uvIndices = []; + // triangles - for ( var i = 0, l = header.num_tris; i < l; i ++ ) { + offset = header.offset_tris; - vertexIndices.push( - data.getUint16( offset + 0, true ), - data.getUint16( offset + 2, true ), - data.getUint16( offset + 4, true ) - ); + const vertexIndices = []; + const uvIndices = []; - uvIndices.push( - data.getUint16( offset + 6, true ), - data.getUint16( offset + 8, true ), - data.getUint16( offset + 10, true ) - ); + for ( let i = 0, l = header.num_tris; i < l; i ++ ) { - offset += 12; + vertexIndices.push( + data.getUint16( offset + 0, true ), + data.getUint16( offset + 2, true ), + data.getUint16( offset + 4, true ) + ); - } + uvIndices.push( + data.getUint16( offset + 6, true ), + data.getUint16( offset + 8, true ), + data.getUint16( offset + 10, true ) + ); - // frames + offset += 12; - var translation = new Vector3(); - var scale = new Vector3(); - var string = []; + } - var frames = []; + // frames - offset = header.offset_frames; + const translation = new Vector3(); + const scale = new Vector3(); + const string = []; - for ( var i = 0, l = header.num_frames; i < l; i ++ ) { + const frames = []; - scale.set( - data.getFloat32( offset + 0, true ), - data.getFloat32( offset + 4, true ), - data.getFloat32( offset + 8, true ) - ); + offset = header.offset_frames; - translation.set( - data.getFloat32( offset + 12, true ), - data.getFloat32( offset + 16, true ), - data.getFloat32( offset + 20, true ) - ); + for ( let i = 0, l = header.num_frames; i < l; i ++ ) { - offset += 24; + scale.set( + data.getFloat32( offset + 0, true ), + data.getFloat32( offset + 4, true ), + data.getFloat32( offset + 8, true ) + ); - for ( var j = 0; j < 16; j ++ ) { + translation.set( + data.getFloat32( offset + 12, true ), + data.getFloat32( offset + 16, true ), + data.getFloat32( offset + 20, true ) + ); - var character = data.getUint8( offset + j, true ); - if ( character === 0 ) break; + offset += 24; - string[ j ] = character; + for ( let j = 0; j < 16; j ++ ) { - } + const character = data.getUint8( offset + j, true ); + if ( character === 0 ) break; - var frame = { - name: String.fromCharCode.apply( null, string ), - vertices: [], - normals: [] - }; + string[ j ] = character; - offset += 16; + } - for ( var j = 0; j < header.num_vertices; j ++ ) { + const frame = { + name: String.fromCharCode.apply( null, string ), + vertices: [], + normals: [] + }; - var x = data.getUint8( offset ++, true ); - var y = data.getUint8( offset ++, true ); - var z = data.getUint8( offset ++, true ); - var n = normalData[ data.getUint8( offset ++, true ) ]; + offset += 16; - x = x * scale.x + translation.x; - y = y * scale.y + translation.y; - z = z * scale.z + translation.z; + for ( let j = 0; j < header.num_vertices; j ++ ) { - frame.vertices.push( x, z, y ); // convert to Y-up - frame.normals.push( n[ 0 ], n[ 2 ], n[ 1 ] ); // convert to Y-up + let x = data.getUint8( offset ++, true ); + let y = data.getUint8( offset ++, true ); + let z = data.getUint8( offset ++, true ); + const n = _normalData[ data.getUint8( offset ++, true ) ]; - } + x = x * scale.x + translation.x; + y = y * scale.y + translation.y; + z = z * scale.z + translation.z; - frames.push( frame ); + frame.vertices.push( x, z, y ); // convert to Y-up + frame.normals.push( n[ 0 ], n[ 2 ], n[ 1 ] ); // convert to Y-up } - // static - - var positions = []; - var normals = []; - var uvs = []; + frames.push( frame ); - var verticesTemp = frames[ 0 ].vertices; - var normalsTemp = frames[ 0 ].normals; + } - for ( var i = 0, l = vertexIndices.length; i < l; i ++ ) { + // static - var vertexIndex = vertexIndices[ i ]; - var stride = vertexIndex * 3; + const positions = []; + const normals = []; + const uvs = []; - // + const verticesTemp = frames[ 0 ].vertices; + const normalsTemp = frames[ 0 ].normals; - var x = verticesTemp[ stride ]; - var y = verticesTemp[ stride + 1 ]; - var z = verticesTemp[ stride + 2 ]; + for ( let i = 0, l = vertexIndices.length; i < l; i ++ ) { - positions.push( x, y, z ); + const vertexIndex = vertexIndices[ i ]; + let stride = vertexIndex * 3; - // + // - var nx = normalsTemp[ stride ]; - var ny = normalsTemp[ stride + 1 ]; - var nz = normalsTemp[ stride + 2 ]; + const x = verticesTemp[ stride ]; + const y = verticesTemp[ stride + 1 ]; + const z = verticesTemp[ stride + 2 ]; - normals.push( nx, ny, nz ); + positions.push( x, y, z ); - // + // - var uvIndex = uvIndices[ i ]; - stride = uvIndex * 2; + const nx = normalsTemp[ stride ]; + const ny = normalsTemp[ stride + 1 ]; + const nz = normalsTemp[ stride + 2 ]; - var u = uvsTemp[ stride ]; - var v = uvsTemp[ stride + 1 ]; + normals.push( nx, ny, nz ); - uvs.push( u, v ); + // - } + const uvIndex = uvIndices[ i ]; + stride = uvIndex * 2; - geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + const u = uvsTemp[ stride ]; + const v = uvsTemp[ stride + 1 ]; - // animation + uvs.push( u, v ); - var morphPositions = []; - var morphNormals = []; + } - for ( var i = 0, l = frames.length; i < l; i ++ ) { + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - var frame = frames[ i ]; - var attributeName = frame.name; + // animation - if ( frame.vertices.length > 0 ) { + const morphPositions = []; + const morphNormals = []; - var positions = []; + for ( let i = 0, l = frames.length; i < l; i ++ ) { - for ( var j = 0, jl = vertexIndices.length; j < jl; j ++ ) { + const frame = frames[ i ]; + const attributeName = frame.name; - var vertexIndex = vertexIndices[ j ]; - var stride = vertexIndex * 3; + if ( frame.vertices.length > 0 ) { - var x = frame.vertices[ stride ]; - var y = frame.vertices[ stride + 1 ]; - var z = frame.vertices[ stride + 2 ]; + const positions = []; - positions.push( x, y, z ); + for ( let j = 0, jl = vertexIndices.length; j < jl; j ++ ) { - } + const vertexIndex = vertexIndices[ j ]; + const stride = vertexIndex * 3; - var positionAttribute = new Float32BufferAttribute( positions, 3 ); - positionAttribute.name = attributeName; + const x = frame.vertices[ stride ]; + const y = frame.vertices[ stride + 1 ]; + const z = frame.vertices[ stride + 2 ]; - morphPositions.push( positionAttribute ); + positions.push( x, y, z ); } - if ( frame.normals.length > 0 ) { + const positionAttribute = new Float32BufferAttribute( positions, 3 ); + positionAttribute.name = attributeName; - var normals = []; + morphPositions.push( positionAttribute ); - for ( var j = 0, jl = vertexIndices.length; j < jl; j ++ ) { + } - var vertexIndex = vertexIndices[ j ]; - var stride = vertexIndex * 3; + if ( frame.normals.length > 0 ) { - var nx = frame.normals[ stride ]; - var ny = frame.normals[ stride + 1 ]; - var nz = frame.normals[ stride + 2 ]; + const normals = []; - normals.push( nx, ny, nz ); + for ( let j = 0, jl = vertexIndices.length; j < jl; j ++ ) { - } + const vertexIndex = vertexIndices[ j ]; + const stride = vertexIndex * 3; - var normalAttribute = new Float32BufferAttribute( normals, 3 ); - normalAttribute.name = attributeName; + const nx = frame.normals[ stride ]; + const ny = frame.normals[ stride + 1 ]; + const nz = frame.normals[ stride + 2 ]; - morphNormals.push( normalAttribute ); + normals.push( nx, ny, nz ); } + const normalAttribute = new Float32BufferAttribute( normals, 3 ); + normalAttribute.name = attributeName; + + morphNormals.push( normalAttribute ); + } - geometry.morphAttributes.position = morphPositions; - geometry.morphAttributes.normal = morphNormals; - geometry.morphTargetsRelative = false; + } - geometry.animations = AnimationClip.CreateClipsFromMorphTargetSequences( frames, 10 ); + geometry.morphAttributes.position = morphPositions; + geometry.morphAttributes.normal = morphNormals; + geometry.morphTargetsRelative = false; - return geometry; + geometry.animations = AnimationClip.CreateClipsFromMorphTargetSequences( frames, 10 ); - }; + return geometry; - } )() + } -} ); +} export { MD2Loader }; diff --git a/examples/jsm/loaders/MDDLoader.js b/examples/jsm/loaders/MDDLoader.js index b38b7e6d1a9c53..1f1007fbc43d84 100644 --- a/examples/jsm/loaders/MDDLoader.js +++ b/examples/jsm/loaders/MDDLoader.js @@ -18,21 +18,19 @@ import { NumberKeyframeTrack } from '../../../build/three.module.js'; -var MDDLoader = function ( manager ) { +class MDDLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -MDDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: MDDLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); loader.load( url, function ( data ) { @@ -41,43 +39,43 @@ MDDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { - var view = new DataView( data ); + const view = new DataView( data ); - var totalFrames = view.getUint32( 0 ); - var totalPoints = view.getUint32( 4 ); + const totalFrames = view.getUint32( 0 ); + const totalPoints = view.getUint32( 4 ); - var offset = 8; + let offset = 8; // animation clip - var times = new Float32Array( totalFrames ); - var values = new Float32Array( totalFrames * totalFrames ).fill( 0 ); + const times = new Float32Array( totalFrames ); + const values = new Float32Array( totalFrames * totalFrames ).fill( 0 ); - for ( var i = 0; i < totalFrames; i ++ ) { + for ( let i = 0; i < totalFrames; i ++ ) { times[ i ] = view.getFloat32( offset ); offset += 4; values[ ( totalFrames * i ) + i ] = 1; } - var track = new NumberKeyframeTrack( '.morphTargetInfluences', times, values ); - var clip = new AnimationClip( 'default', times[ times.length - 1 ], [ track ] ); + const track = new NumberKeyframeTrack( '.morphTargetInfluences', times, values ); + const clip = new AnimationClip( 'default', times[ times.length - 1 ], [ track ] ); // morph targets - var morphTargets = []; + const morphTargets = []; - for ( var i = 0; i < totalFrames; i ++ ) { + for ( let i = 0; i < totalFrames; i ++ ) { - var morphTarget = new Float32Array( totalPoints * 3 ); + const morphTarget = new Float32Array( totalPoints * 3 ); - for ( var j = 0; j < totalPoints; j ++ ) { + for ( let j = 0; j < totalPoints; j ++ ) { - var stride = ( j * 3 ); + const stride = ( j * 3 ); morphTarget[ stride + 0 ] = view.getFloat32( offset ); offset += 4; // x morphTarget[ stride + 1 ] = view.getFloat32( offset ); offset += 4; // y @@ -85,7 +83,7 @@ MDDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var attribute = new BufferAttribute( morphTarget, 3 ); + const attribute = new BufferAttribute( morphTarget, 3 ); attribute.name = 'morph_' + i; morphTargets.push( attribute ); @@ -99,6 +97,6 @@ MDDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { MDDLoader }; diff --git a/examples/jsm/loaders/MMDLoader.js b/examples/jsm/loaders/MMDLoader.js index 63662a8582efc8..4870e806a0b392 100644 --- a/examples/jsm/loaders/MMDLoader.js +++ b/examples/jsm/loaders/MMDLoader.js @@ -62,14 +62,14 @@ import { MMDParser } from '../libs/mmdparser.module.js'; * - shadow support. */ -var MMDLoader = ( function () { +/** + * @param {THREE.LoadingManager} manager + */ +class MMDLoader extends Loader { - /** - * @param {THREE.LoadingManager} manager - */ - function MMDLoader( manager ) { + constructor( manager ) { - Loader.call( this, manager ); + super( manager ); this.loader = new FileLoader( this.manager ); @@ -79,1027 +79,1010 @@ var MMDLoader = ( function () { } - MMDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: MMDLoader, - - /** - * @param {string} animationPath - * @return {MMDLoader} - */ - setAnimationPath: function ( animationPath ) { + /** + * @param {string} animationPath + * @return {MMDLoader} + */ + setAnimationPath( animationPath ) { - this.animationPath = animationPath; - return this; + this.animationPath = animationPath; + return this; - }, + } - // Load MMD assets as Three.js Object + // Load MMD assets as Three.js Object - /** - * Loads Model file (.pmd or .pmx) as a SkinnedMesh. - * - * @param {string} url - url to Model(.pmd or .pmx) file - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - load: function ( url, onLoad, onProgress, onError ) { + /** + * Loads Model file (.pmd or .pmx) as a SkinnedMesh. + * + * @param {string} url - url to Model(.pmd or .pmx) file + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + load( url, onLoad, onProgress, onError ) { - var builder = this.meshBuilder.setCrossOrigin( this.crossOrigin ); + const builder = this.meshBuilder.setCrossOrigin( this.crossOrigin ); - // resource path + // resource path - var resourcePath; + let resourcePath; - if ( this.resourcePath !== '' ) { + if ( this.resourcePath !== '' ) { - resourcePath = this.resourcePath; + resourcePath = this.resourcePath; - } else if ( this.path !== '' ) { + } else if ( this.path !== '' ) { - resourcePath = this.path; + resourcePath = this.path; - } else { + } else { - resourcePath = LoaderUtils.extractUrlBase( url ); + resourcePath = LoaderUtils.extractUrlBase( url ); - } - - var modelExtension = this._extractExtension( url ).toLowerCase(); + } - // Should I detect by seeing header? - if ( modelExtension !== 'pmd' && modelExtension !== 'pmx' ) { + const modelExtension = this._extractExtension( url ).toLowerCase(); - if ( onError ) onError( new Error( 'THREE.MMDLoader: Unknown model file extension .' + modelExtension + '.' ) ); + // Should I detect by seeing header? + if ( modelExtension !== 'pmd' && modelExtension !== 'pmx' ) { - return; + if ( onError ) onError( new Error( 'THREE.MMDLoader: Unknown model file extension .' + modelExtension + '.' ) ); - } + return; - this[ modelExtension === 'pmd' ? 'loadPMD' : 'loadPMX' ]( url, function ( data ) { + } - onLoad( builder.build( data, resourcePath, onProgress, onError ) ); + this[ modelExtension === 'pmd' ? 'loadPMD' : 'loadPMX' ]( url, function ( data ) { - }, onProgress, onError ); + onLoad( builder.build( data, resourcePath, onProgress, onError ) ); - }, + }, onProgress, onError ); - /** - * Loads Motion file(s) (.vmd) as a AnimationClip. - * If two or more files are specified, they'll be merged. - * - * @param {string|Array} url - url(s) to animation(.vmd) file(s) - * @param {SkinnedMesh|THREE.Camera} object - tracks will be fitting to this object - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - loadAnimation: function ( url, object, onLoad, onProgress, onError ) { + } - var builder = this.animationBuilder; + /** + * Loads Motion file(s) (.vmd) as a AnimationClip. + * If two or more files are specified, they'll be merged. + * + * @param {string|Array} url - url(s) to animation(.vmd) file(s) + * @param {SkinnedMesh|THREE.Camera} object - tracks will be fitting to this object + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + loadAnimation( url, object, onLoad, onProgress, onError ) { - this.loadVMD( url, function ( vmd ) { + const builder = this.animationBuilder; - onLoad( object.isCamera - ? builder.buildCameraAnimation( vmd ) - : builder.build( vmd, object ) ); + this.loadVMD( url, function ( vmd ) { - }, onProgress, onError ); + onLoad( object.isCamera + ? builder.buildCameraAnimation( vmd ) + : builder.build( vmd, object ) ); - }, + }, onProgress, onError ); - /** - * Loads mode file and motion file(s) as an object containing - * a SkinnedMesh and a AnimationClip. - * Tracks of AnimationClip are fitting to the model. - * - * @param {string} modelUrl - url to Model(.pmd or .pmx) file - * @param {string|Array{string}} vmdUrl - url(s) to animation(.vmd) file - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - loadWithAnimation: function ( modelUrl, vmdUrl, onLoad, onProgress, onError ) { + } - var scope = this; + /** + * Loads mode file and motion file(s) as an object containing + * a SkinnedMesh and a AnimationClip. + * Tracks of AnimationClip are fitting to the model. + * + * @param {string} modelUrl - url to Model(.pmd or .pmx) file + * @param {string|Array{string}} vmdUrl - url(s) to animation(.vmd) file + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + loadWithAnimation( modelUrl, vmdUrl, onLoad, onProgress, onError ) { - this.load( modelUrl, function ( mesh ) { + const scope = this; - scope.loadAnimation( vmdUrl, mesh, function ( animation ) { + this.load( modelUrl, function ( mesh ) { - onLoad( { - mesh: mesh, - animation: animation - } ); + scope.loadAnimation( vmdUrl, mesh, function ( animation ) { - }, onProgress, onError ); + onLoad( { + mesh: mesh, + animation: animation + } ); }, onProgress, onError ); - }, + }, onProgress, onError ); - // Load MMD assets as Object data parsed by MMDParser - - /** - * Loads .pmd file as an Object. - * - * @param {string} url - url to .pmd file - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - loadPMD: function ( url, onLoad, onProgress, onError ) { + } - var parser = this._getParser(); + // Load MMD assets as Object data parsed by MMDParser - this.loader - .setMimeType( undefined ) - .setPath( this.path ) - .setResponseType( 'arraybuffer' ) - .setRequestHeader( this.requestHeader ) - .setWithCredentials( this.withCredentials ) - .load( url, function ( buffer ) { + /** + * Loads .pmd file as an Object. + * + * @param {string} url - url to .pmd file + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + loadPMD( url, onLoad, onProgress, onError ) { - onLoad( parser.parsePmd( buffer, true ) ); + const parser = this._getParser(); - }, onProgress, onError ); + this.loader + .setMimeType( undefined ) + .setPath( this.path ) + .setResponseType( 'arraybuffer' ) + .setRequestHeader( this.requestHeader ) + .setWithCredentials( this.withCredentials ) + .load( url, function ( buffer ) { - }, + onLoad( parser.parsePmd( buffer, true ) ); - /** - * Loads .pmx file as an Object. - * - * @param {string} url - url to .pmx file - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - loadPMX: function ( url, onLoad, onProgress, onError ) { + }, onProgress, onError ); - var parser = this._getParser(); + } - this.loader - .setMimeType( undefined ) - .setPath( this.path ) - .setResponseType( 'arraybuffer' ) - .setRequestHeader( this.requestHeader ) - .setWithCredentials( this.withCredentials ) - .load( url, function ( buffer ) { + /** + * Loads .pmx file as an Object. + * + * @param {string} url - url to .pmx file + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + loadPMX( url, onLoad, onProgress, onError ) { - onLoad( parser.parsePmx( buffer, true ) ); + const parser = this._getParser(); - }, onProgress, onError ); + this.loader + .setMimeType( undefined ) + .setPath( this.path ) + .setResponseType( 'arraybuffer' ) + .setRequestHeader( this.requestHeader ) + .setWithCredentials( this.withCredentials ) + .load( url, function ( buffer ) { - }, + onLoad( parser.parsePmx( buffer, true ) ); - /** - * Loads .vmd file as an Object. If two or more files are specified - * they'll be merged. - * - * @param {string|Array} url - url(s) to .vmd file(s) - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - loadVMD: function ( url, onLoad, onProgress, onError ) { + }, onProgress, onError ); - var urls = Array.isArray( url ) ? url : [ url ]; + } - var vmds = []; - var vmdNum = urls.length; + /** + * Loads .vmd file as an Object. If two or more files are specified + * they'll be merged. + * + * @param {string|Array} url - url(s) to .vmd file(s) + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + loadVMD( url, onLoad, onProgress, onError ) { - var parser = this._getParser(); + const urls = Array.isArray( url ) ? url : [ url ]; - this.loader - .setMimeType( undefined ) - .setPath( this.animationPath ) - .setResponseType( 'arraybuffer' ) - .setRequestHeader( this.requestHeader ) - .setWithCredentials( this.withCredentials ); + const vmds = []; + const vmdNum = urls.length; - for ( var i = 0, il = urls.length; i < il; i ++ ) { + const parser = this._getParser(); - this.loader.load( urls[ i ], function ( buffer ) { + this.loader + .setMimeType( undefined ) + .setPath( this.animationPath ) + .setResponseType( 'arraybuffer' ) + .setRequestHeader( this.requestHeader ) + .setWithCredentials( this.withCredentials ); - vmds.push( parser.parseVmd( buffer, true ) ); + for ( let i = 0, il = urls.length; i < il; i ++ ) { - if ( vmds.length === vmdNum ) onLoad( parser.mergeVmds( vmds ) ); + this.loader.load( urls[ i ], function ( buffer ) { - }, onProgress, onError ); + vmds.push( parser.parseVmd( buffer, true ) ); - } + if ( vmds.length === vmdNum ) onLoad( parser.mergeVmds( vmds ) ); - }, + }, onProgress, onError ); - /** - * Loads .vpd file as an Object. - * - * @param {string} url - url to .vpd file - * @param {boolean} isUnicode - * @param {function} onLoad - * @param {function} onProgress - * @param {function} onError - */ - loadVPD: function ( url, isUnicode, onLoad, onProgress, onError ) { + } - var parser = this._getParser(); + } - this.loader - .setMimeType( isUnicode ? undefined : 'text/plain; charset=shift_jis' ) - .setPath( this.animationPath ) - .setResponseType( 'text' ) - .setRequestHeader( this.requestHeader ) - .setWithCredentials( this.withCredentials ) - .load( url, function ( text ) { + /** + * Loads .vpd file as an Object. + * + * @param {string} url - url to .vpd file + * @param {boolean} isUnicode + * @param {function} onLoad + * @param {function} onProgress + * @param {function} onError + */ + loadVPD( url, isUnicode, onLoad, onProgress, onError ) { - onLoad( parser.parseVpd( text, true ) ); + const parser = this._getParser(); - }, onProgress, onError ); + this.loader + .setMimeType( isUnicode ? undefined : 'text/plain; charset=shift_jis' ) + .setPath( this.animationPath ) + .setResponseType( 'text' ) + .setRequestHeader( this.requestHeader ) + .setWithCredentials( this.withCredentials ) + .load( url, function ( text ) { - }, + onLoad( parser.parseVpd( text, true ) ); - // private methods + }, onProgress, onError ); - _extractExtension: function ( url ) { + } - var index = url.lastIndexOf( '.' ); - return index < 0 ? '' : url.slice( index + 1 ); + // private methods - }, + _extractExtension( url ) { - _getParser: function () { + const index = url.lastIndexOf( '.' ); + return index < 0 ? '' : url.slice( index + 1 ); - if ( this.parser === null ) { + } - if ( typeof MMDParser === 'undefined' ) { + _getParser() { - throw new Error( 'THREE.MMDLoader: Import MMDParser https://github.com/takahirox/mmd-parser' ); + if ( this.parser === null ) { - } + if ( typeof MMDParser === 'undefined' ) { - this.parser = new MMDParser.Parser(); // eslint-disable-line no-undef + throw new Error( 'THREE.MMDLoader: Import MMDParser https://github.com/takahirox/mmd-parser' ); } - return this.parser; + this.parser = new MMDParser.Parser(); // eslint-disable-line no-undef } - } ); + return this.parser; + + } + +} - // Utilities +// Utilities - /* +/* * 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 */ - var DEFAULT_TOON_TEXTURES = [ - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=' - ]; - - // Builders. They build Three.js object from Object data parsed by MMDParser. +const DEFAULT_TOON_TEXTURES = [ + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=', + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=' +]; + +// Builders. They build Three.js object from Object data parsed by MMDParser. - /** - * @param {THREE.LoadingManager} manager - */ - function MeshBuilder( manager ) { +/** + * @param {THREE.LoadingManager} manager + */ +class MeshBuilder { + + constructor( manager ) { + this.crossOrigin = 'anonymous'; this.geometryBuilder = new GeometryBuilder(); this.materialBuilder = new MaterialBuilder( manager ); } - MeshBuilder.prototype = { - - constructor: MeshBuilder, - - crossOrigin: 'anonymous', - - /** - * @param {string} crossOrigin - * @return {MeshBuilder} - */ - setCrossOrigin: function ( crossOrigin ) { - - this.crossOrigin = crossOrigin; - return this; + /** + * @param {string} crossOrigin + * @return {MeshBuilder} + */ + setCrossOrigin( crossOrigin ) { - }, + this.crossOrigin = crossOrigin; + return this; - /** - * @param {Object} data - parsed PMD/PMX data - * @param {string} resourcePath - * @param {function} onProgress - * @param {function} onError - * @return {SkinnedMesh} - */ - build: function ( data, resourcePath, onProgress, onError ) { + } - var geometry = this.geometryBuilder.build( data ); - var material = this.materialBuilder - .setCrossOrigin( this.crossOrigin ) - .setResourcePath( resourcePath ) - .build( data, geometry, onProgress, onError ); + /** + * @param {Object} data - parsed PMD/PMX data + * @param {string} resourcePath + * @param {function} onProgress + * @param {function} onError + * @return {SkinnedMesh} + */ + build( data, resourcePath, onProgress, onError ) { - var mesh = new SkinnedMesh( geometry, material ); + const geometry = this.geometryBuilder.build( data ); + const material = this.materialBuilder + .setCrossOrigin( this.crossOrigin ) + .setResourcePath( resourcePath ) + .build( data, geometry, onProgress, onError ); - var skeleton = new Skeleton( initBones( mesh ) ); - mesh.bind( skeleton ); + const mesh = new SkinnedMesh( geometry, material ); - // console.log( mesh ); // for console debug + const skeleton = new Skeleton( initBones( mesh ) ); + mesh.bind( skeleton ); - return mesh; + // console.log( mesh ); // for console debug - } + return mesh; - }; + } - // TODO: Try to remove this function +} - function initBones( mesh ) { +// TODO: Try to remove this function - var geometry = mesh.geometry; +function initBones( mesh ) { - var bones = [], bone, gbone; - var i, il; + const geometry = mesh.geometry; - if ( geometry && geometry.bones !== undefined ) { + const bones = []; - // first, create array of 'Bone' objects from geometry data + if ( geometry && geometry.bones !== undefined ) { - for ( i = 0, il = geometry.bones.length; i < il; i ++ ) { + // first, create array of 'Bone' objects from geometry data - gbone = geometry.bones[ i ]; + for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) { - // create new 'Bone' object + const gbone = geometry.bones[ i ]; - bone = new Bone(); - bones.push( bone ); + // create new 'Bone' object - // apply values + const bone = new Bone(); + bones.push( bone ); - bone.name = gbone.name; - bone.position.fromArray( gbone.pos ); - bone.quaternion.fromArray( gbone.rotq ); - if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl ); + // apply values - } + bone.name = gbone.name; + bone.position.fromArray( gbone.pos ); + bone.quaternion.fromArray( gbone.rotq ); + if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl ); - // second, create bone hierarchy + } - for ( i = 0, il = geometry.bones.length; i < il; i ++ ) { + // second, create bone hierarchy - gbone = geometry.bones[ i ]; + for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) { - if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { + const gbone = geometry.bones[ i ]; - // subsequent bones in the hierarchy + if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { - bones[ gbone.parent ].add( bones[ i ] ); + // subsequent bones in the hierarchy - } else { + bones[ gbone.parent ].add( bones[ i ] ); - // topmost bone, immediate child of the skinned mesh + } else { - mesh.add( bones[ i ] ); + // topmost bone, immediate child of the skinned mesh - } + mesh.add( bones[ i ] ); } } - // now the bones are part of the scene graph and children of the skinned mesh. - // let's update the corresponding matrices - - mesh.updateMatrixWorld( true ); - - return bones; - } - // + // now the bones are part of the scene graph and children of the skinned mesh. + // let's update the corresponding matrices - function GeometryBuilder() { + mesh.updateMatrixWorld( true ); - } + return bones; - GeometryBuilder.prototype = { +} - constructor: GeometryBuilder, +// - /** - * @param {Object} data - parsed PMD/PMX data - * @return {BufferGeometry} - */ - build: function ( data ) { +class GeometryBuilder { - // for geometry - var positions = []; - var uvs = []; - var normals = []; + /** + * @param {Object} data - parsed PMD/PMX data + * @return {BufferGeometry} + */ + build( data ) { - var indices = []; + // for geometry + const positions = []; + const uvs = []; + const normals = []; - var groups = []; + const indices = []; - var bones = []; - var skinIndices = []; - var skinWeights = []; + const groups = []; - var morphTargets = []; - var morphPositions = []; + const bones = []; + const skinIndices = []; + const skinWeights = []; - var iks = []; - var grants = []; + const morphTargets = []; + const morphPositions = []; - var rigidBodies = []; - var constraints = []; + const iks = []; + const grants = []; - // for work - var offset = 0; - var boneTypeTable = {}; + const rigidBodies = []; + const constraints = []; - // positions, normals, uvs, skinIndices, skinWeights + // for work + let offset = 0; + const boneTypeTable = {}; - for ( var i = 0; i < data.metadata.vertexCount; i ++ ) { + // positions, normals, uvs, skinIndices, skinWeights - var v = data.vertices[ i ]; + for ( let i = 0; i < data.metadata.vertexCount; i ++ ) { - for ( var j = 0, jl = v.position.length; j < jl; j ++ ) { + const v = data.vertices[ i ]; - positions.push( v.position[ j ] ); + for ( let j = 0, jl = v.position.length; j < jl; j ++ ) { - } + positions.push( v.position[ j ] ); - for ( var j = 0, jl = v.normal.length; j < jl; j ++ ) { + } - normals.push( v.normal[ j ] ); + for ( let j = 0, jl = v.normal.length; j < jl; j ++ ) { - } + normals.push( v.normal[ j ] ); - for ( var j = 0, jl = v.uv.length; j < jl; j ++ ) { + } - uvs.push( v.uv[ j ] ); + for ( let j = 0, jl = v.uv.length; j < jl; j ++ ) { - } + uvs.push( v.uv[ j ] ); - for ( var j = 0; j < 4; j ++ ) { + } - skinIndices.push( v.skinIndices.length - 1 >= j ? v.skinIndices[ j ] : 0.0 ); + for ( let j = 0; j < 4; j ++ ) { - } + skinIndices.push( v.skinIndices.length - 1 >= j ? v.skinIndices[ j ] : 0.0 ); - for ( var j = 0; j < 4; j ++ ) { + } - skinWeights.push( v.skinWeights.length - 1 >= j ? v.skinWeights[ j ] : 0.0 ); + for ( let j = 0; j < 4; j ++ ) { - } + skinWeights.push( v.skinWeights.length - 1 >= j ? v.skinWeights[ j ] : 0.0 ); } - // indices + } - for ( var i = 0; i < data.metadata.faceCount; i ++ ) { + // indices - var face = data.faces[ i ]; + for ( let i = 0; i < data.metadata.faceCount; i ++ ) { - for ( var j = 0, jl = face.indices.length; j < jl; j ++ ) { + const face = data.faces[ i ]; - indices.push( face.indices[ j ] ); + for ( let j = 0, jl = face.indices.length; j < jl; j ++ ) { - } + indices.push( face.indices[ j ] ); } - // groups - - for ( var i = 0; i < data.metadata.materialCount; i ++ ) { + } - var material = data.materials[ i ]; + // groups - groups.push( { - offset: offset * 3, - count: material.faceCount * 3 - } ); + for ( let i = 0; i < data.metadata.materialCount; i ++ ) { - offset += material.faceCount; + const material = data.materials[ i ]; - } + groups.push( { + offset: offset * 3, + count: material.faceCount * 3 + } ); - // bones + offset += material.faceCount; - for ( var i = 0; i < data.metadata.rigidBodyCount; i ++ ) { + } - var body = data.rigidBodies[ i ]; - var value = boneTypeTable[ body.boneIndex ]; + // bones - // keeps greater number if already value is set without any special reasons - value = value === undefined ? body.type : Math.max( body.type, value ); + for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) { - boneTypeTable[ body.boneIndex ] = value; + const body = data.rigidBodies[ i ]; + let value = boneTypeTable[ body.boneIndex ]; - } + // keeps greater number if already value is set without any special reasons + value = value === undefined ? body.type : Math.max( body.type, value ); - for ( var i = 0; i < data.metadata.boneCount; i ++ ) { + boneTypeTable[ body.boneIndex ] = value; - var boneData = data.bones[ i ]; + } - var bone = { - index: i, - transformationClass: boneData.transformationClass, - parent: boneData.parentIndex, - name: boneData.name, - pos: boneData.position.slice( 0, 3 ), - rotq: [ 0, 0, 0, 1 ], - scl: [ 1, 1, 1 ], - rigidBodyType: boneTypeTable[ i ] !== undefined ? boneTypeTable[ i ] : - 1 - }; + for ( let i = 0; i < data.metadata.boneCount; i ++ ) { - if ( bone.parent !== - 1 ) { + const boneData = data.bones[ i ]; - bone.pos[ 0 ] -= data.bones[ bone.parent ].position[ 0 ]; - bone.pos[ 1 ] -= data.bones[ bone.parent ].position[ 1 ]; - bone.pos[ 2 ] -= data.bones[ bone.parent ].position[ 2 ]; + const bone = { + index: i, + transformationClass: boneData.transformationClass, + parent: boneData.parentIndex, + name: boneData.name, + pos: boneData.position.slice( 0, 3 ), + rotq: [ 0, 0, 0, 1 ], + scl: [ 1, 1, 1 ], + rigidBodyType: boneTypeTable[ i ] !== undefined ? boneTypeTable[ i ] : - 1 + }; - } + if ( bone.parent !== - 1 ) { - bones.push( bone ); + bone.pos[ 0 ] -= data.bones[ bone.parent ].position[ 0 ]; + bone.pos[ 1 ] -= data.bones[ bone.parent ].position[ 1 ]; + bone.pos[ 2 ] -= data.bones[ bone.parent ].position[ 2 ]; } - // iks + bones.push( bone ); - // TODO: remove duplicated codes between PMD and PMX - if ( data.metadata.format === 'pmd' ) { + } - for ( var i = 0; i < data.metadata.ikCount; i ++ ) { + // iks - var ik = data.iks[ i ]; + // TODO: remove duplicated codes between PMD and PMX + if ( data.metadata.format === 'pmd' ) { - var param = { - target: ik.target, - effector: ik.effector, - iteration: ik.iteration, - maxAngle: ik.maxAngle * 4, - links: [] - }; + for ( let i = 0; i < data.metadata.ikCount; i ++ ) { - for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) { + const ik = data.iks[ i ]; - var link = {}; - link.index = ik.links[ j ].index; - link.enabled = true; + const param = { + target: ik.target, + effector: ik.effector, + iteration: ik.iteration, + maxAngle: ik.maxAngle * 4, + links: [] + }; - if ( data.bones[ link.index ].name.indexOf( 'ひざ' ) >= 0 ) { + for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { - link.limitation = new Vector3( 1.0, 0.0, 0.0 ); + const link = {}; + link.index = ik.links[ j ].index; + link.enabled = true; - } + if ( data.bones[ link.index ].name.indexOf( 'ひざ' ) >= 0 ) { - param.links.push( link ); + link.limitation = new Vector3( 1.0, 0.0, 0.0 ); } - iks.push( param ); + param.links.push( link ); } - } else { + iks.push( param ); - for ( var i = 0; i < data.metadata.boneCount; i ++ ) { + } - var ik = data.bones[ i ].ik; + } else { - if ( ik === undefined ) continue; + for ( let i = 0; i < data.metadata.boneCount; i ++ ) { - var param = { - target: i, - effector: ik.effector, - iteration: ik.iteration, - maxAngle: ik.maxAngle, - links: [] - }; + const ik = data.bones[ i ].ik; - for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) { + if ( ik === undefined ) continue; - var link = {}; - link.index = ik.links[ j ].index; - link.enabled = true; + const param = { + target: i, + effector: ik.effector, + iteration: ik.iteration, + maxAngle: ik.maxAngle, + links: [] + }; - if ( ik.links[ j ].angleLimitation === 1 ) { + for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) { - // Revert if rotationMin/Max doesn't work well - // link.limitation = new Vector3( 1.0, 0.0, 0.0 ); + const link = {}; + link.index = ik.links[ j ].index; + link.enabled = true; - var rotationMin = ik.links[ j ].lowerLimitationAngle; - var rotationMax = ik.links[ j ].upperLimitationAngle; + if ( ik.links[ j ].angleLimitation === 1 ) { - // Convert Left to Right coordinate by myself because - // MMDParser doesn't convert. It's a MMDParser's bug + // Revert if rotationMin/Max doesn't work well + // link.limitation = new Vector3( 1.0, 0.0, 0.0 ); - var tmp1 = - rotationMax[ 0 ]; - var tmp2 = - rotationMax[ 1 ]; - rotationMax[ 0 ] = - rotationMin[ 0 ]; - rotationMax[ 1 ] = - rotationMin[ 1 ]; - rotationMin[ 0 ] = tmp1; - rotationMin[ 1 ] = tmp2; + const rotationMin = ik.links[ j ].lowerLimitationAngle; + const rotationMax = ik.links[ j ].upperLimitationAngle; - link.rotationMin = new Vector3().fromArray( rotationMin ); - link.rotationMax = new Vector3().fromArray( rotationMax ); + // Convert Left to Right coordinate by myself because + // MMDParser doesn't convert. It's a MMDParser's bug - } + const tmp1 = - rotationMax[ 0 ]; + const tmp2 = - rotationMax[ 1 ]; + rotationMax[ 0 ] = - rotationMin[ 0 ]; + rotationMax[ 1 ] = - rotationMin[ 1 ]; + rotationMin[ 0 ] = tmp1; + rotationMin[ 1 ] = tmp2; - param.links.push( link ); + link.rotationMin = new Vector3().fromArray( rotationMin ); + link.rotationMax = new Vector3().fromArray( rotationMax ); } - iks.push( param ); - - // Save the reference even from bone data for efficiently - // simulating PMX animation system - bones[ i ].ik = param; + param.links.push( link ); } + iks.push( param ); + + // Save the reference even from bone data for efficiently + // simulating PMX animation system + bones[ i ].ik = param; + } - // grants + } - if ( data.metadata.format === 'pmx' ) { + // grants - // bone index -> grant entry map - var grantEntryMap = {}; + if ( data.metadata.format === 'pmx' ) { - for ( var i = 0; i < data.metadata.boneCount; i ++ ) { + // bone index -> grant entry map + const grantEntryMap = {}; - var boneData = data.bones[ i ]; - var grant = boneData.grant; + for ( let i = 0; i < data.metadata.boneCount; i ++ ) { - if ( grant === undefined ) continue; + const boneData = data.bones[ i ]; + const grant = boneData.grant; - var param = { - index: i, - parentIndex: grant.parentIndex, - ratio: grant.ratio, - isLocal: grant.isLocal, - affectRotation: grant.affectRotation, - affectPosition: grant.affectPosition, - transformationClass: boneData.transformationClass - }; + if ( grant === undefined ) continue; - grantEntryMap[ i ] = { parent: null, children: [], param: param, visited: false }; + const param = { + index: i, + parentIndex: grant.parentIndex, + ratio: grant.ratio, + isLocal: grant.isLocal, + affectRotation: grant.affectRotation, + affectPosition: grant.affectPosition, + transformationClass: boneData.transformationClass + }; - } + grantEntryMap[ i ] = { parent: null, children: [], param: param, visited: false }; - var rootEntry = { parent: null, children: [], param: null, visited: false }; + } - // Build a tree representing grant hierarchy + const rootEntry = { parent: null, children: [], param: null, visited: false }; - for ( var boneIndex in grantEntryMap ) { + // Build a tree representing grant hierarchy - var grantEntry = grantEntryMap[ boneIndex ]; - var parentGrantEntry = grantEntryMap[ grantEntry.parentIndex ] || rootEntry; + for ( const boneIndex in grantEntryMap ) { - grantEntry.parent = parentGrantEntry; - parentGrantEntry.children.push( grantEntry ); + const grantEntry = grantEntryMap[ boneIndex ]; + const parentGrantEntry = grantEntryMap[ grantEntry.parentIndex ] || rootEntry; - } + grantEntry.parent = parentGrantEntry; + parentGrantEntry.children.push( grantEntry ); - // Sort grant parameters from parents to children because - // grant uses parent's transform that parent's grant is already applied - // so grant should be applied in order from parents to children + } - function traverse( entry ) { + // Sort grant parameters from parents to children because + // grant uses parent's transform that parent's grant is already applied + // so grant should be applied in order from parents to children - if ( entry.param ) { + function traverse( entry ) { - grants.push( entry.param ); + if ( entry.param ) { - // Save the reference even from bone data for efficiently - // simulating PMX animation system - bones[ entry.param.index ].grant = entry.param; + grants.push( entry.param ); - } + // Save the reference even from bone data for efficiently + // simulating PMX animation system + bones[ entry.param.index ].grant = entry.param; - entry.visited = true; + } - for ( var i = 0, il = entry.children.length; i < il; i ++ ) { + entry.visited = true; - var child = entry.children[ i ]; + for ( let i = 0, il = entry.children.length; i < il; i ++ ) { - // Cut off a loop if exists. (Is a grant loop invalid?) - if ( ! child.visited ) traverse( child ); + const child = entry.children[ i ]; - } + // Cut off a loop if exists. (Is a grant loop invalid?) + if ( ! child.visited ) traverse( child ); } - traverse( rootEntry ); - } - // morph + traverse( rootEntry ); - function updateAttributes( attribute, morph, ratio ) { + } - for ( var i = 0; i < morph.elementCount; i ++ ) { + // morph - var element = morph.elements[ i ]; + function updateAttributes( attribute, morph, ratio ) { - var index; + for ( let i = 0; i < morph.elementCount; i ++ ) { - if ( data.metadata.format === 'pmd' ) { + const element = morph.elements[ i ]; - index = data.morphs[ 0 ].elements[ element.index ].index; + let index; - } else { + if ( data.metadata.format === 'pmd' ) { - index = element.index; + index = data.morphs[ 0 ].elements[ element.index ].index; - } + } else { - attribute.array[ index * 3 + 0 ] += element.position[ 0 ] * ratio; - attribute.array[ index * 3 + 1 ] += element.position[ 1 ] * ratio; - attribute.array[ index * 3 + 2 ] += element.position[ 2 ] * ratio; + index = element.index; } + attribute.array[ index * 3 + 0 ] += element.position[ 0 ] * ratio; + attribute.array[ index * 3 + 1 ] += element.position[ 1 ] * ratio; + attribute.array[ index * 3 + 2 ] += element.position[ 2 ] * ratio; + } - for ( var i = 0; i < data.metadata.morphCount; i ++ ) { + } - var morph = data.morphs[ i ]; - var params = { name: morph.name }; + for ( let i = 0; i < data.metadata.morphCount; i ++ ) { - var attribute = new Float32BufferAttribute( data.metadata.vertexCount * 3, 3 ); - attribute.name = morph.name; + const morph = data.morphs[ i ]; + const params = { name: morph.name }; - for ( var j = 0; j < data.metadata.vertexCount * 3; j ++ ) { + const attribute = new Float32BufferAttribute( data.metadata.vertexCount * 3, 3 ); + attribute.name = morph.name; - attribute.array[ j ] = positions[ j ]; + for ( let j = 0; j < data.metadata.vertexCount * 3; j ++ ) { - } + attribute.array[ j ] = positions[ j ]; - if ( data.metadata.format === 'pmd' ) { + } - if ( i !== 0 ) { + if ( data.metadata.format === 'pmd' ) { - updateAttributes( attribute, morph, 1.0 ); + if ( i !== 0 ) { - } + updateAttributes( attribute, morph, 1.0 ); - } else { + } - if ( morph.type === 0 ) { // group + } else { - for ( var j = 0; j < morph.elementCount; j ++ ) { + if ( morph.type === 0 ) { // group - var morph2 = data.morphs[ morph.elements[ j ].index ]; - var ratio = morph.elements[ j ].ratio; + for ( let j = 0; j < morph.elementCount; j ++ ) { - if ( morph2.type === 1 ) { + const morph2 = data.morphs[ morph.elements[ j ].index ]; + const ratio = morph.elements[ j ].ratio; - updateAttributes( attribute, morph2, ratio ); + if ( morph2.type === 1 ) { - } else { + updateAttributes( attribute, morph2, ratio ); - // TODO: implement + } else { - } + // TODO: implement } - } else if ( morph.type === 1 ) { // vertex + } - updateAttributes( attribute, morph, 1.0 ); + } else if ( morph.type === 1 ) { // vertex - } else if ( morph.type === 2 ) { // bone + updateAttributes( attribute, morph, 1.0 ); - // TODO: implement + } else if ( morph.type === 2 ) { // bone - } else if ( morph.type === 3 ) { // uv + // TODO: implement - // TODO: implement + } else if ( morph.type === 3 ) { // uv - } else if ( morph.type === 4 ) { // additional uv1 + // TODO: implement - // TODO: implement + } else if ( morph.type === 4 ) { // additional uv1 - } else if ( morph.type === 5 ) { // additional uv2 + // TODO: implement - // TODO: implement + } else if ( morph.type === 5 ) { // additional uv2 - } else if ( morph.type === 6 ) { // additional uv3 + // TODO: implement - // TODO: implement + } else if ( morph.type === 6 ) { // additional uv3 - } else if ( morph.type === 7 ) { // additional uv4 + // TODO: implement - // TODO: implement + } else if ( morph.type === 7 ) { // additional uv4 - } else if ( morph.type === 8 ) { // material + // TODO: implement - // TODO: implement + } else if ( morph.type === 8 ) { // material - } + // TODO: implement } - morphTargets.push( params ); - morphPositions.push( attribute ); - } - // rigid bodies from rigidBodies field. + morphTargets.push( params ); + morphPositions.push( attribute ); - for ( var i = 0; i < data.metadata.rigidBodyCount; i ++ ) { + } - var rigidBody = data.rigidBodies[ i ]; - var params = {}; + // rigid bodies from rigidBodies field. - for ( var key in rigidBody ) { + for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) { - params[ key ] = rigidBody[ key ]; + const rigidBody = data.rigidBodies[ i ]; + const params = {}; - } + for ( const key in rigidBody ) { - /* + params[ key ] = rigidBody[ key ]; + + } + + /* * RigidBody position parameter in PMX seems global position * while the one in PMD seems offset from corresponding bone. * So unify being offset. */ - if ( data.metadata.format === 'pmx' ) { + if ( data.metadata.format === 'pmx' ) { - if ( params.boneIndex !== - 1 ) { + if ( params.boneIndex !== - 1 ) { - var bone = data.bones[ params.boneIndex ]; - params.position[ 0 ] -= bone.position[ 0 ]; - params.position[ 1 ] -= bone.position[ 1 ]; - params.position[ 2 ] -= bone.position[ 2 ]; - - } + const bone = data.bones[ params.boneIndex ]; + params.position[ 0 ] -= bone.position[ 0 ]; + params.position[ 1 ] -= bone.position[ 1 ]; + params.position[ 2 ] -= bone.position[ 2 ]; } - rigidBodies.push( params ); - } - // constraints from constraints field. + rigidBodies.push( params ); - for ( var i = 0; i < data.metadata.constraintCount; i ++ ) { + } - var constraint = data.constraints[ i ]; - var params = {}; + // constraints from constraints field. - for ( var key in constraint ) { + for ( let i = 0; i < data.metadata.constraintCount; i ++ ) { - params[ key ] = constraint[ key ]; + const constraint = data.constraints[ i ]; + const params = {}; - } + for ( const key in constraint ) { - var bodyA = rigidBodies[ params.rigidBodyIndex1 ]; - var bodyB = rigidBodies[ params.rigidBodyIndex2 ]; + params[ key ] = constraint[ key ]; - // Refer to http://www20.atpages.jp/katwat/wp/?p=4135 - if ( bodyA.type !== 0 && bodyB.type === 2 ) { + } - if ( bodyA.boneIndex !== - 1 && bodyB.boneIndex !== - 1 && - data.bones[ bodyB.boneIndex ].parentIndex === bodyA.boneIndex ) { + const bodyA = rigidBodies[ params.rigidBodyIndex1 ]; + const bodyB = rigidBodies[ params.rigidBodyIndex2 ]; - bodyB.type = 1; + // Refer to http://www20.atpages.jp/katwat/wp/?p=4135 + if ( bodyA.type !== 0 && bodyB.type === 2 ) { - } + if ( bodyA.boneIndex !== - 1 && bodyB.boneIndex !== - 1 && + data.bones[ bodyB.boneIndex ].parentIndex === bodyA.boneIndex ) { - } + bodyB.type = 1; - constraints.push( params ); + } } - // build BufferGeometry. + constraints.push( params ); - var geometry = new BufferGeometry(); + } - geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - geometry.setAttribute( 'skinIndex', new Uint16BufferAttribute( skinIndices, 4 ) ); - geometry.setAttribute( 'skinWeight', new Float32BufferAttribute( skinWeights, 4 ) ); - geometry.setIndex( indices ); + // build BufferGeometry. - for ( var i = 0, il = groups.length; i < il; i ++ ) { + const geometry = new BufferGeometry(); - geometry.addGroup( groups[ i ].offset, groups[ i ].count, i ); + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + geometry.setAttribute( 'skinIndex', new Uint16BufferAttribute( skinIndices, 4 ) ); + geometry.setAttribute( 'skinWeight', new Float32BufferAttribute( skinWeights, 4 ) ); + geometry.setIndex( indices ); - } + for ( let i = 0, il = groups.length; i < il; i ++ ) { - geometry.bones = bones; + geometry.addGroup( groups[ i ].offset, groups[ i ].count, i ); - geometry.morphTargets = morphTargets; - geometry.morphAttributes.position = morphPositions; - geometry.morphTargetsRelative = false; + } - geometry.userData.MMD = { - bones: bones, - iks: iks, - grants: grants, - rigidBodies: rigidBodies, - constraints: constraints, - format: data.metadata.format - }; + geometry.bones = bones; - geometry.computeBoundingSphere(); + geometry.morphTargets = morphTargets; + geometry.morphAttributes.position = morphPositions; + geometry.morphTargetsRelative = false; - return geometry; + geometry.userData.MMD = { + bones: bones, + iks: iks, + grants: grants, + rigidBodies: rigidBodies, + constraints: constraints, + format: data.metadata.format + }; - } + geometry.computeBoundingSphere(); + + return geometry; - }; + } - // +} - /** - * @param {THREE.LoadingManager} manager - */ - function MaterialBuilder( manager ) { +// + +/** + * @param {THREE.LoadingManager} manager + */ +class MaterialBuilder { + + constructor( manager ) { this.manager = manager; this.textureLoader = new TextureLoader( this.manager ); this.tgaLoader = null; // lazy generation - } - - MaterialBuilder.prototype = { - - constructor: MaterialBuilder, - - crossOrigin: 'anonymous', + this.crossOrigin = 'anonymous'; + this.resourcePath = undefined; - resourcePath: undefined, + } - /** - * @param {string} crossOrigin - * @return {MaterialBuilder} - */ - setCrossOrigin: function ( crossOrigin ) { + /** + * @param {string} crossOrigin + * @return {MaterialBuilder} + */ + setCrossOrigin( crossOrigin ) { - this.crossOrigin = crossOrigin; - return this; + this.crossOrigin = crossOrigin; + return this; - }, + } - /** - * @param {string} resourcePath - * @return {MaterialBuilder} - */ - setResourcePath: function ( resourcePath ) { + /** + * @param {string} resourcePath + * @return {MaterialBuilder} + */ + setResourcePath( resourcePath ) { - this.resourcePath = resourcePath; - return this; + this.resourcePath = resourcePath; + return this; - }, + } - /** - * @param {Object} data - parsed PMD/PMX data - * @param {BufferGeometry} geometry - some properties are dependend on geometry - * @param {function} onProgress - * @param {function} onError - * @return {Array} - */ - build: function ( data, geometry /*, onProgress, onError */ ) { + /** + * @param {Object} data - parsed PMD/PMX data + * @param {BufferGeometry} geometry - some properties are dependend on geometry + * @param {function} onProgress + * @param {function} onError + * @return {Array} + */ + build( data, geometry /*, onProgress, onError */ ) { - var materials = []; + const materials = []; - var textures = {}; + const textures = {}; - this.textureLoader.setCrossOrigin( this.crossOrigin ); + this.textureLoader.setCrossOrigin( this.crossOrigin ); - // materials + // materials - for ( var i = 0; i < data.metadata.materialCount; i ++ ) { + for ( let i = 0; i < data.metadata.materialCount; i ++ ) { - var material = data.materials[ i ]; + const material = data.materials[ i ]; - var params = { userData: {} }; + const params = { userData: {} }; - if ( material.name !== undefined ) params.name = material.name; + if ( material.name !== undefined ) params.name = material.name; - /* + /* * Color * * MMD MeshToonMaterial @@ -1110,890 +1093,880 @@ var MMDLoader = ( function () { * MeshToonMaterial doesn't have ambient. Set it to emissive instead. * It'll be too bright if material has map texture so using coef 0.2. */ - params.color = new Color().fromArray( material.diffuse ); - params.opacity = material.diffuse[ 3 ]; - params.emissive = new Color().fromArray( material.ambient ); - params.transparent = params.opacity !== 1.0; - - // + params.color = new Color().fromArray( material.diffuse ); + params.opacity = material.diffuse[ 3 ]; + params.emissive = new Color().fromArray( material.ambient ); + params.transparent = params.opacity !== 1.0; - params.skinning = geometry.bones.length > 0 ? true : false; - params.morphTargets = geometry.morphTargets.length > 0 ? true : false; - params.fog = true; + // - // blend + params.skinning = geometry.bones.length > 0 ? true : false; + params.morphTargets = geometry.morphTargets.length > 0 ? true : false; + params.fog = true; - params.blending = CustomBlending; - params.blendSrc = SrcAlphaFactor; - params.blendDst = OneMinusSrcAlphaFactor; - params.blendSrcAlpha = SrcAlphaFactor; - params.blendDstAlpha = DstAlphaFactor; + // blend - // side + params.blending = CustomBlending; + params.blendSrc = SrcAlphaFactor; + params.blendDst = OneMinusSrcAlphaFactor; + params.blendSrcAlpha = SrcAlphaFactor; + params.blendDstAlpha = DstAlphaFactor; - if ( data.metadata.format === 'pmx' && ( material.flag & 0x1 ) === 1 ) { + // side - params.side = DoubleSide; + if ( data.metadata.format === 'pmx' && ( material.flag & 0x1 ) === 1 ) { - } else { + params.side = DoubleSide; - params.side = params.opacity === 1.0 ? FrontSide : DoubleSide; + } else { - } + params.side = params.opacity === 1.0 ? FrontSide : DoubleSide; - if ( data.metadata.format === 'pmd' ) { + } - // map, envMap + if ( data.metadata.format === 'pmd' ) { - if ( material.fileName ) { + // map, envMap - var fileName = material.fileName; - var fileNames = fileName.split( '*' ); + if ( material.fileName ) { - // fileNames[ 0 ]: mapFileName - // fileNames[ 1 ]: envMapFileName( optional ) + const fileName = material.fileName; + const fileNames = fileName.split( '*' ); - params.map = this._loadTexture( fileNames[ 0 ], textures ); + // fileNames[ 0 ]: mapFileName + // fileNames[ 1 ]: envMapFileName( optional ) - if ( fileNames.length > 1 ) { + params.map = this._loadTexture( fileNames[ 0 ], textures ); - var extension = fileNames[ 1 ].slice( - 4 ).toLowerCase(); + if ( fileNames.length > 1 ) { - params.envMap = this._loadTexture( - fileNames[ 1 ], - textures - ); + const extension = fileNames[ 1 ].slice( - 4 ).toLowerCase(); - params.combine = extension === '.sph' - ? MultiplyOperation - : AddOperation; + params.envMap = this._loadTexture( + fileNames[ 1 ], + textures + ); - } + params.combine = extension === '.sph' + ? MultiplyOperation + : AddOperation; } - // gradientMap - - var toonFileName = ( material.toonIndex === - 1 ) - ? 'toon00.bmp' - : data.toonTextures[ material.toonIndex ].fileName; - - params.gradientMap = this._loadTexture( - toonFileName, - textures, - { - isToonTexture: true, - isDefaultToonTexture: this._isDefaultToonTexture( toonFileName ) - } - ); + } - // parameters for OutlineEffect + // gradientMap - params.userData.outlineParameters = { - thickness: material.edgeFlag === 1 ? 0.003 : 0.0, - color: [ 0, 0, 0 ], - alpha: 1.0, - visible: material.edgeFlag === 1 - }; + const toonFileName = ( material.toonIndex === - 1 ) + ? 'toon00.bmp' + : data.toonTextures[ material.toonIndex ].fileName; - } else { + params.gradientMap = this._loadTexture( + toonFileName, + textures, + { + isToonTexture: true, + isDefaultToonTexture: this._isDefaultToonTexture( toonFileName ) + } + ); - // map + // parameters for OutlineEffect - if ( material.textureIndex !== - 1 ) { + params.userData.outlineParameters = { + thickness: material.edgeFlag === 1 ? 0.003 : 0.0, + color: [ 0, 0, 0 ], + alpha: 1.0, + visible: material.edgeFlag === 1 + }; - params.map = this._loadTexture( data.textures[ material.textureIndex ], textures ); + } else { - } + // map - // envMap TODO: support m.envFlag === 3 + if ( material.textureIndex !== - 1 ) { - if ( material.envTextureIndex !== - 1 && ( material.envFlag === 1 || material.envFlag == 2 ) ) { + params.map = this._loadTexture( data.textures[ material.textureIndex ], textures ); - params.envMap = this._loadTexture( - data.textures[ material.envTextureIndex ], - textures - ); + } - params.combine = material.envFlag === 1 - ? MultiplyOperation - : AddOperation; + // envMap TODO: support m.envFlag === 3 - } + if ( material.envTextureIndex !== - 1 && ( material.envFlag === 1 || material.envFlag == 2 ) ) { - // gradientMap + params.envMap = this._loadTexture( + data.textures[ material.envTextureIndex ], + textures + ); - var toonFileName, isDefaultToon; + params.combine = material.envFlag === 1 + ? MultiplyOperation + : AddOperation; - if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) { + } - toonFileName = 'toon' + ( '0' + ( material.toonIndex + 1 ) ).slice( - 2 ) + '.bmp'; - isDefaultToon = true; + // gradientMap - } else { + let toonFileName, isDefaultToon; - toonFileName = data.textures[ material.toonIndex ]; - isDefaultToon = false; + if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) { - } + toonFileName = 'toon' + ( '0' + ( material.toonIndex + 1 ) ).slice( - 2 ) + '.bmp'; + isDefaultToon = true; - params.gradientMap = this._loadTexture( - toonFileName, - textures, - { - isToonTexture: true, - isDefaultToonTexture: isDefaultToon - } - ); + } else { - // parameters for OutlineEffect - params.userData.outlineParameters = { - thickness: material.edgeSize / 300, // TODO: better calculation? - color: material.edgeColor.slice( 0, 3 ), - alpha: material.edgeColor[ 3 ], - visible: ( material.flag & 0x10 ) !== 0 && material.edgeSize > 0.0 - }; + toonFileName = data.textures[ material.toonIndex ]; + isDefaultToon = false; } - if ( params.map !== undefined ) { + params.gradientMap = this._loadTexture( + toonFileName, + textures, + { + isToonTexture: true, + isDefaultToonTexture: isDefaultToon + } + ); + + // parameters for OutlineEffect + params.userData.outlineParameters = { + thickness: material.edgeSize / 300, // TODO: better calculation? + color: material.edgeColor.slice( 0, 3 ), + alpha: material.edgeColor[ 3 ], + visible: ( material.flag & 0x10 ) !== 0 && material.edgeSize > 0.0 + }; - if ( ! params.transparent ) { + } - this._checkImageTransparency( params.map, geometry, i ); + if ( params.map !== undefined ) { - } + if ( ! params.transparent ) { - params.emissive.multiplyScalar( 0.2 ); + this._checkImageTransparency( params.map, geometry, i ); } - materials.push( new MeshToonMaterial( params ) ); + params.emissive.multiplyScalar( 0.2 ); } - if ( data.metadata.format === 'pmx' ) { + materials.push( new MeshToonMaterial( params ) ); - // set transparent true if alpha morph is defined. + } - function checkAlphaMorph( elements, materials ) { + if ( data.metadata.format === 'pmx' ) { - for ( var i = 0, il = elements.length; i < il; i ++ ) { + // set transparent true if alpha morph is defined. - var element = elements[ i ]; + function checkAlphaMorph( elements, materials ) { - if ( element.index === - 1 ) continue; + for ( let i = 0, il = elements.length; i < il; i ++ ) { - var material = materials[ element.index ]; + const element = elements[ i ]; - if ( material.opacity !== element.diffuse[ 3 ] ) { + if ( element.index === - 1 ) continue; - material.transparent = true; + const material = materials[ element.index ]; - } + if ( material.opacity !== element.diffuse[ 3 ] ) { + + material.transparent = true; } } - for ( var i = 0, il = data.morphs.length; i < il; i ++ ) { + } - var morph = data.morphs[ i ]; - var elements = morph.elements; + for ( let i = 0, il = data.morphs.length; i < il; i ++ ) { - if ( morph.type === 0 ) { + const morph = data.morphs[ i ]; + const elements = morph.elements; - for ( var j = 0, jl = elements.length; j < jl; j ++ ) { + if ( morph.type === 0 ) { - var morph2 = data.morphs[ elements[ j ].index ]; + for ( let j = 0, jl = elements.length; j < jl; j ++ ) { - if ( morph2.type !== 8 ) continue; + const morph2 = data.morphs[ elements[ j ].index ]; - checkAlphaMorph( morph2.elements, materials ); + if ( morph2.type !== 8 ) continue; - } + checkAlphaMorph( morph2.elements, materials ); - } else if ( morph.type === 8 ) { + } - checkAlphaMorph( elements, materials ); + } else if ( morph.type === 8 ) { - } + checkAlphaMorph( elements, materials ); } } - return materials; - - }, + } - // private methods + return materials; - _getTGALoader: function () { + } - if ( this.tgaLoader === null ) { + // private methods - if ( TGALoader === undefined ) { + _getTGALoader() { - throw new Error( 'THREE.MMDLoader: Import TGALoader' ); + if ( this.tgaLoader === null ) { - } + if ( TGALoader === undefined ) { - this.tgaLoader = new TGALoader( this.manager ); + throw new Error( 'THREE.MMDLoader: Import TGALoader' ); } - return this.tgaLoader; - - }, + this.tgaLoader = new TGALoader( this.manager ); - _isDefaultToonTexture: function ( name ) { + } - if ( name.length !== 10 ) return false; + return this.tgaLoader; - return /toon(10|0[0-9])\.bmp/.test( name ); + } - }, + _isDefaultToonTexture( name ) { - _loadTexture: function ( filePath, textures, params, onProgress, onError ) { + if ( name.length !== 10 ) return false; - params = params || {}; + return /toon(10|0[0-9])\.bmp/.test( name ); - var scope = this; + } - var fullPath; + _loadTexture( filePath, textures, params, onProgress, onError ) { - if ( params.isDefaultToonTexture === true ) { + params = params || {}; - var index; + const scope = this; - try { + let fullPath; - index = parseInt( filePath.match( /toon([0-9]{2})\.bmp$/ )[ 1 ] ); + if ( params.isDefaultToonTexture === true ) { - } catch ( e ) { + let index; - console.warn( 'THREE.MMDLoader: ' + filePath + ' seems like a ' - + 'not right default texture path. Using toon00.bmp instead.' ); + try { - index = 0; + index = parseInt( filePath.match( /toon([0-9]{2})\.bmp$/ )[ 1 ] ); - } + } catch ( e ) { - fullPath = DEFAULT_TOON_TEXTURES[ index ]; - - } else { + console.warn( 'THREE.MMDLoader: ' + filePath + ' seems like a ' + + 'not right default texture path. Using toon00.bmp instead.' ); - fullPath = this.resourcePath + filePath; + index = 0; } - if ( textures[ fullPath ] !== undefined ) return textures[ fullPath ]; + fullPath = DEFAULT_TOON_TEXTURES[ index ]; - var loader = this.manager.getHandler( fullPath ); + } else { - if ( loader === null ) { + fullPath = this.resourcePath + filePath; - loader = ( filePath.slice( - 4 ).toLowerCase() === '.tga' ) - ? this._getTGALoader() - : this.textureLoader; + } - } + if ( textures[ fullPath ] !== undefined ) return textures[ fullPath ]; - var texture = loader.load( fullPath, function ( t ) { + let loader = this.manager.getHandler( fullPath ); - // MMD toon texture is Axis-Y oriented - // but Three.js gradient map is Axis-X oriented. - // So here replaces the toon texture image with the rotated one. - if ( params.isToonTexture === true ) { + if ( loader === null ) { - t.image = scope._getRotatedImage( t.image ); + loader = ( filePath.slice( - 4 ).toLowerCase() === '.tga' ) + ? this._getTGALoader() + : this.textureLoader; - t.magFilter = NearestFilter; - t.minFilter = NearestFilter; + } - } + const texture = loader.load( fullPath, function ( t ) { - t.flipY = false; - t.wrapS = RepeatWrapping; - t.wrapT = RepeatWrapping; + // MMD toon texture is Axis-Y oriented + // but Three.js gradient map is Axis-X oriented. + // So here replaces the toon texture image with the rotated one. + if ( params.isToonTexture === true ) { - for ( var i = 0; i < texture.readyCallbacks.length; i ++ ) { + t.image = scope._getRotatedImage( t.image ); - texture.readyCallbacks[ i ]( texture ); + t.magFilter = NearestFilter; + t.minFilter = NearestFilter; - } + } - delete texture.readyCallbacks; + t.flipY = false; + t.wrapS = RepeatWrapping; + t.wrapT = RepeatWrapping; - }, onProgress, onError ); + for ( let i = 0; i < texture.readyCallbacks.length; i ++ ) { + + texture.readyCallbacks[ i ]( texture ); - texture.readyCallbacks = []; + } - textures[ fullPath ] = texture; + delete texture.readyCallbacks; - return texture; + }, onProgress, onError ); - }, + texture.readyCallbacks = []; - _getRotatedImage: function ( image ) { + textures[ fullPath ] = texture; - var canvas = document.createElement( 'canvas' ); - var context = canvas.getContext( '2d' ); + return texture; - var width = image.width; - var height = image.height; + } - canvas.width = width; - canvas.height = height; + _getRotatedImage( image ) { - context.clearRect( 0, 0, width, height ); - context.translate( width / 2.0, height / 2.0 ); - context.rotate( 0.5 * Math.PI ); // 90.0 * Math.PI / 180.0 - context.translate( - width / 2.0, - height / 2.0 ); - context.drawImage( image, 0, 0 ); + const canvas = document.createElement( 'canvas' ); + const context = canvas.getContext( '2d' ); - return context.getImageData( 0, 0, width, height ); + const width = image.width; + const height = image.height; - }, + canvas.width = width; + canvas.height = height; - // Check if the partial image area used by the texture is transparent. - _checkImageTransparency: function ( map, geometry, groupIndex ) { + context.clearRect( 0, 0, width, height ); + context.translate( width / 2.0, height / 2.0 ); + context.rotate( 0.5 * Math.PI ); // 90.0 * Math.PI / 180.0 + context.translate( - width / 2.0, - height / 2.0 ); + context.drawImage( image, 0, 0 ); - map.readyCallbacks.push( function ( texture ) { + return context.getImageData( 0, 0, width, height ); - // Is there any efficient ways? - function createImageData( image ) { + } - var canvas = document.createElement( 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; + // Check if the partial image area used by the texture is transparent. + _checkImageTransparency( map, geometry, groupIndex ) { - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0 ); + map.readyCallbacks.push( function ( texture ) { - return context.getImageData( 0, 0, canvas.width, canvas.height ); + // Is there any efficient ways? + function createImageData( image ) { - } + const canvas = document.createElement( 'canvas' ); + canvas.width = image.width; + canvas.height = image.height; - function detectImageTransparency( image, uvs, indices ) { + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0 ); - var width = image.width; - var height = image.height; - var data = image.data; - var threshold = 253; + return context.getImageData( 0, 0, canvas.width, canvas.height ); - if ( data.length / ( width * height ) !== 4 ) return false; + } - for ( var i = 0; i < indices.length; i += 3 ) { + function detectImageTransparency( image, uvs, indices ) { - var centerUV = { x: 0.0, y: 0.0 }; + const width = image.width; + const height = image.height; + const data = image.data; + const threshold = 253; - for ( var j = 0; j < 3; j ++ ) { + if ( data.length / ( width * height ) !== 4 ) return false; - var index = indices[ i * 3 + j ]; - var uv = { x: uvs[ index * 2 + 0 ], y: uvs[ index * 2 + 1 ] }; + for ( let i = 0; i < indices.length; i += 3 ) { - if ( getAlphaByUv( image, uv ) < threshold ) return true; + const centerUV = { x: 0.0, y: 0.0 }; - centerUV.x += uv.x; - centerUV.y += uv.y; + for ( let j = 0; j < 3; j ++ ) { - } + const index = indices[ i * 3 + j ]; + const uv = { x: uvs[ index * 2 + 0 ], y: uvs[ index * 2 + 1 ] }; - centerUV.x /= 3; - centerUV.y /= 3; + if ( getAlphaByUv( image, uv ) < threshold ) return true; - if ( getAlphaByUv( image, centerUV ) < threshold ) return true; + centerUV.x += uv.x; + centerUV.y += uv.y; } - return false; + centerUV.x /= 3; + centerUV.y /= 3; + + if ( getAlphaByUv( image, centerUV ) < threshold ) return true; } - /* + return false; + + } + + /* * This method expects * texture.flipY = false * texture.wrapS = RepeatWrapping * texture.wrapT = RepeatWrapping * TODO: more precise */ - function getAlphaByUv( image, uv ) { + function getAlphaByUv( image, uv ) { - var width = image.width; - var height = image.height; + const width = image.width; + const height = image.height; - var x = Math.round( uv.x * width ) % width; - var y = Math.round( uv.y * height ) % height; + let x = Math.round( uv.x * width ) % width; + let y = Math.round( uv.y * height ) % height; - if ( x < 0 ) x += width; - if ( y < 0 ) y += height; + if ( x < 0 ) x += width; + if ( y < 0 ) y += height; - var index = y * width + x; + const index = y * width + x; - return image.data[ index * 4 + 3 ]; + return image.data[ index * 4 + 3 ]; - } - - var imageData = texture.image.data !== undefined - ? texture.image - : createImageData( texture.image ); - - var group = geometry.groups[ groupIndex ]; - - if ( detectImageTransparency( - imageData, - geometry.attributes.uv.array, - geometry.index.array.slice( group.start, group.start + group.count ) ) ) { - - map.transparent = true; + } - } + const imageData = texture.image.data !== undefined + ? texture.image + : createImageData( texture.image ); - } ); + const group = geometry.groups[ groupIndex ]; - } + if ( detectImageTransparency( + imageData, + geometry.attributes.uv.array, + geometry.index.array.slice( group.start, group.start + group.count ) ) ) { - }; + map.transparent = true; - // + } - function AnimationBuilder() { + } ); } - AnimationBuilder.prototype = { - - constructor: AnimationBuilder, +} - /** - * @param {Object} vmd - parsed VMD data - * @param {SkinnedMesh} mesh - tracks will be fitting to mesh - * @return {AnimationClip} - */ - build: function ( vmd, mesh ) { +// - // combine skeletal and morph animations +class AnimationBuilder { - var tracks = this.buildSkeletalAnimation( vmd, mesh ).tracks; - var tracks2 = this.buildMorphAnimation( vmd, mesh ).tracks; + /** + * @param {Object} vmd - parsed VMD data + * @param {SkinnedMesh} mesh - tracks will be fitting to mesh + * @return {AnimationClip} + */ + build( vmd, mesh ) { - for ( var i = 0, il = tracks2.length; i < il; i ++ ) { + // combine skeletal and morph animations - tracks.push( tracks2[ i ] ); + const tracks = this.buildSkeletalAnimation( vmd, mesh ).tracks; + const tracks2 = this.buildMorphAnimation( vmd, mesh ).tracks; - } + for ( let i = 0, il = tracks2.length; i < il; i ++ ) { - return new AnimationClip( '', - 1, tracks ); + tracks.push( tracks2[ i ] ); - }, + } - /** - * @param {Object} vmd - parsed VMD data - * @param {SkinnedMesh} mesh - tracks will be fitting to mesh - * @return {AnimationClip} - */ - buildSkeletalAnimation: function ( vmd, mesh ) { + return new AnimationClip( '', - 1, tracks ); - function pushInterpolation( array, interpolation, index ) { + } - array.push( interpolation[ index + 0 ] / 127 ); // x1 - array.push( interpolation[ index + 8 ] / 127 ); // x2 - array.push( interpolation[ index + 4 ] / 127 ); // y1 - array.push( interpolation[ index + 12 ] / 127 ); // y2 + /** + * @param {Object} vmd - parsed VMD data + * @param {SkinnedMesh} mesh - tracks will be fitting to mesh + * @return {AnimationClip} + */ + buildSkeletalAnimation( vmd, mesh ) { - } + function pushInterpolation( array, interpolation, index ) { - var tracks = []; + array.push( interpolation[ index + 0 ] / 127 ); // x1 + array.push( interpolation[ index + 8 ] / 127 ); // x2 + array.push( interpolation[ index + 4 ] / 127 ); // y1 + array.push( interpolation[ index + 12 ] / 127 ); // y2 - var motions = {}; - var bones = mesh.skeleton.bones; - var boneNameDictionary = {}; + } - for ( var i = 0, il = bones.length; i < il; i ++ ) { + const tracks = []; - boneNameDictionary[ bones[ i ].name ] = true; + const motions = {}; + const bones = mesh.skeleton.bones; + const boneNameDictionary = {}; - } + for ( let i = 0, il = bones.length; i < il; i ++ ) { - for ( var i = 0; i < vmd.metadata.motionCount; i ++ ) { + boneNameDictionary[ bones[ i ].name ] = true; - var motion = vmd.motions[ i ]; - var boneName = motion.boneName; + } - if ( boneNameDictionary[ boneName ] === undefined ) continue; + for ( let i = 0; i < vmd.metadata.motionCount; i ++ ) { - motions[ boneName ] = motions[ boneName ] || []; - motions[ boneName ].push( motion ); + const motion = vmd.motions[ i ]; + const boneName = motion.boneName; - } + if ( boneNameDictionary[ boneName ] === undefined ) continue; - for ( var key in motions ) { + motions[ boneName ] = motions[ boneName ] || []; + motions[ boneName ].push( motion ); - var array = motions[ key ]; - - array.sort( function ( a, b ) { + } - return a.frameNum - b.frameNum; + for ( const key in motions ) { - } ); + const array = motions[ key ]; - var times = []; - var positions = []; - var rotations = []; - var pInterpolations = []; - var rInterpolations = []; + array.sort( function ( a, b ) { - var basePosition = mesh.skeleton.getBoneByName( key ).position.toArray(); + return a.frameNum - b.frameNum; - for ( var i = 0, il = array.length; i < il; i ++ ) { + } ); - var time = array[ i ].frameNum / 30; - var position = array[ i ].position; - var rotation = array[ i ].rotation; - var interpolation = array[ i ].interpolation; + const times = []; + const positions = []; + const rotations = []; + const pInterpolations = []; + const rInterpolations = []; - times.push( time ); + const basePosition = mesh.skeleton.getBoneByName( key ).position.toArray(); - for ( var j = 0; j < 3; j ++ ) positions.push( basePosition[ j ] + position[ j ] ); - for ( var j = 0; j < 4; j ++ ) rotations.push( rotation[ j ] ); - for ( var j = 0; j < 3; j ++ ) pushInterpolation( pInterpolations, interpolation, j ); + for ( let i = 0, il = array.length; i < il; i ++ ) { - pushInterpolation( rInterpolations, interpolation, 3 ); + const time = array[ i ].frameNum / 30; + const position = array[ i ].position; + const rotation = array[ i ].rotation; + const interpolation = array[ i ].interpolation; - } + times.push( time ); - var targetName = '.bones[' + key + ']'; + for ( let j = 0; j < 3; j ++ ) positions.push( basePosition[ j ] + position[ j ] ); + for ( let j = 0; j < 4; j ++ ) rotations.push( rotation[ j ] ); + for ( let j = 0; j < 3; j ++ ) pushInterpolation( pInterpolations, interpolation, j ); - tracks.push( this._createTrack( targetName + '.position', VectorKeyframeTrack, times, positions, pInterpolations ) ); - tracks.push( this._createTrack( targetName + '.quaternion', QuaternionKeyframeTrack, times, rotations, rInterpolations ) ); + pushInterpolation( rInterpolations, interpolation, 3 ); } - return new AnimationClip( '', - 1, tracks ); + const targetName = '.bones[' + key + ']'; - }, + tracks.push( this._createTrack( targetName + '.position', VectorKeyframeTrack, times, positions, pInterpolations ) ); + tracks.push( this._createTrack( targetName + '.quaternion', QuaternionKeyframeTrack, times, rotations, rInterpolations ) ); - /** - * @param {Object} vmd - parsed VMD data - * @param {SkinnedMesh} mesh - tracks will be fitting to mesh - * @return {AnimationClip} - */ - buildMorphAnimation: function ( vmd, mesh ) { + } - var tracks = []; + return new AnimationClip( '', - 1, tracks ); - var morphs = {}; - var morphTargetDictionary = mesh.morphTargetDictionary; + } + + /** + * @param {Object} vmd - parsed VMD data + * @param {SkinnedMesh} mesh - tracks will be fitting to mesh + * @return {AnimationClip} + */ + buildMorphAnimation( vmd, mesh ) { - for ( var i = 0; i < vmd.metadata.morphCount; i ++ ) { + const tracks = []; - var morph = vmd.morphs[ i ]; - var morphName = morph.morphName; + const morphs = {}; + const morphTargetDictionary = mesh.morphTargetDictionary; - if ( morphTargetDictionary[ morphName ] === undefined ) continue; + for ( let i = 0; i < vmd.metadata.morphCount; i ++ ) { - morphs[ morphName ] = morphs[ morphName ] || []; - morphs[ morphName ].push( morph ); + const morph = vmd.morphs[ i ]; + const morphName = morph.morphName; - } + if ( morphTargetDictionary[ morphName ] === undefined ) continue; - for ( var key in morphs ) { + morphs[ morphName ] = morphs[ morphName ] || []; + morphs[ morphName ].push( morph ); - var array = morphs[ key ]; + } - array.sort( function ( a, b ) { + for ( const key in morphs ) { - return a.frameNum - b.frameNum; + const array = morphs[ key ]; - } ); + array.sort( function ( a, b ) { - var times = []; - var values = []; + return a.frameNum - b.frameNum; - for ( var i = 0, il = array.length; i < il; i ++ ) { + } ); - times.push( array[ i ].frameNum / 30 ); - values.push( array[ i ].weight ); + const times = []; + const values = []; - } + for ( let i = 0, il = array.length; i < il; i ++ ) { - tracks.push( new NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetDictionary[ key ] + ']', times, values ) ); + times.push( array[ i ].frameNum / 30 ); + values.push( array[ i ].weight ); } - return new AnimationClip( '', - 1, tracks ); - - }, + tracks.push( new NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetDictionary[ key ] + ']', times, values ) ); - /** - * @param {Object} vmd - parsed VMD data - * @return {AnimationClip} - */ - buildCameraAnimation: function ( vmd ) { + } - function pushVector3( array, vec ) { + return new AnimationClip( '', - 1, tracks ); - array.push( vec.x ); - array.push( vec.y ); - array.push( vec.z ); + } - } + /** + * @param {Object} vmd - parsed VMD data + * @return {AnimationClip} + */ + buildCameraAnimation( vmd ) { - function pushQuaternion( array, q ) { + function pushVector3( array, vec ) { - array.push( q.x ); - array.push( q.y ); - array.push( q.z ); - array.push( q.w ); + array.push( vec.x ); + array.push( vec.y ); + array.push( vec.z ); - } + } - function pushInterpolation( array, interpolation, index ) { + function pushQuaternion( array, q ) { - array.push( interpolation[ index * 4 + 0 ] / 127 ); // x1 - array.push( interpolation[ index * 4 + 1 ] / 127 ); // x2 - array.push( interpolation[ index * 4 + 2 ] / 127 ); // y1 - array.push( interpolation[ index * 4 + 3 ] / 127 ); // y2 + array.push( q.x ); + array.push( q.y ); + array.push( q.z ); + array.push( q.w ); - } + } - var tracks = []; + function pushInterpolation( array, interpolation, index ) { - var cameras = vmd.cameras === undefined ? [] : vmd.cameras.slice(); + array.push( interpolation[ index * 4 + 0 ] / 127 ); // x1 + array.push( interpolation[ index * 4 + 1 ] / 127 ); // x2 + array.push( interpolation[ index * 4 + 2 ] / 127 ); // y1 + array.push( interpolation[ index * 4 + 3 ] / 127 ); // y2 - cameras.sort( function ( a, b ) { + } - return a.frameNum - b.frameNum; + const cameras = vmd.cameras === undefined ? [] : vmd.cameras.slice(); - } ); + cameras.sort( function ( a, b ) { - var times = []; - var centers = []; - var quaternions = []; - var positions = []; - var fovs = []; + return a.frameNum - b.frameNum; - var cInterpolations = []; - var qInterpolations = []; - var pInterpolations = []; - var fInterpolations = []; + } ); - var quaternion = new Quaternion(); - var euler = new Euler(); - var position = new Vector3(); - var center = new Vector3(); + const times = []; + const centers = []; + const quaternions = []; + const positions = []; + const fovs = []; - for ( var i = 0, il = cameras.length; i < il; i ++ ) { + const cInterpolations = []; + const qInterpolations = []; + const pInterpolations = []; + const fInterpolations = []; - var motion = cameras[ i ]; + const quaternion = new Quaternion(); + const euler = new Euler(); + const position = new Vector3(); + const center = new Vector3(); - var time = motion.frameNum / 30; - var pos = motion.position; - var rot = motion.rotation; - var distance = motion.distance; - var fov = motion.fov; - var interpolation = motion.interpolation; + for ( let i = 0, il = cameras.length; i < il; i ++ ) { - times.push( time ); + const motion = cameras[ i ]; - position.set( 0, 0, - distance ); - center.set( pos[ 0 ], pos[ 1 ], pos[ 2 ] ); + const time = motion.frameNum / 30; + const pos = motion.position; + const rot = motion.rotation; + const distance = motion.distance; + const fov = motion.fov; + const interpolation = motion.interpolation; - euler.set( - rot[ 0 ], - rot[ 1 ], - rot[ 2 ] ); - quaternion.setFromEuler( euler ); + times.push( time ); - position.add( center ); - position.applyQuaternion( quaternion ); + position.set( 0, 0, - distance ); + center.set( pos[ 0 ], pos[ 1 ], pos[ 2 ] ); - pushVector3( centers, center ); - pushQuaternion( quaternions, quaternion ); - pushVector3( positions, position ); + euler.set( - rot[ 0 ], - rot[ 1 ], - rot[ 2 ] ); + quaternion.setFromEuler( euler ); - fovs.push( fov ); + position.add( center ); + position.applyQuaternion( quaternion ); - for ( var j = 0; j < 3; j ++ ) { + pushVector3( centers, center ); + pushQuaternion( quaternions, quaternion ); + pushVector3( positions, position ); - pushInterpolation( cInterpolations, interpolation, j ); + fovs.push( fov ); - } + for ( let j = 0; j < 3; j ++ ) { - pushInterpolation( qInterpolations, interpolation, 3 ); + pushInterpolation( cInterpolations, interpolation, j ); - // use the same parameter for x, y, z axis. - for ( var j = 0; j < 3; j ++ ) { + } - pushInterpolation( pInterpolations, interpolation, 4 ); + pushInterpolation( qInterpolations, interpolation, 3 ); - } + // use the same parameter for x, y, z axis. + for ( let j = 0; j < 3; j ++ ) { - pushInterpolation( fInterpolations, interpolation, 5 ); + pushInterpolation( pInterpolations, interpolation, 4 ); } - var tracks = []; + pushInterpolation( fInterpolations, interpolation, 5 ); + + } - // I expect an object whose name 'target' exists under THREE.Camera - tracks.push( this._createTrack( 'target.position', VectorKeyframeTrack, times, centers, cInterpolations ) ); + const tracks = []; - tracks.push( this._createTrack( '.quaternion', QuaternionKeyframeTrack, times, quaternions, qInterpolations ) ); - tracks.push( this._createTrack( '.position', VectorKeyframeTrack, times, positions, pInterpolations ) ); - tracks.push( this._createTrack( '.fov', NumberKeyframeTrack, times, fovs, fInterpolations ) ); + // I expect an object whose name 'target' exists under THREE.Camera + tracks.push( this._createTrack( 'target.position', VectorKeyframeTrack, times, centers, cInterpolations ) ); - return new AnimationClip( '', - 1, tracks ); + tracks.push( this._createTrack( '.quaternion', QuaternionKeyframeTrack, times, quaternions, qInterpolations ) ); + tracks.push( this._createTrack( '.position', VectorKeyframeTrack, times, positions, pInterpolations ) ); + tracks.push( this._createTrack( '.fov', NumberKeyframeTrack, times, fovs, fInterpolations ) ); - }, + return new AnimationClip( '', - 1, tracks ); - // private method + } - _createTrack: function ( node, typedKeyframeTrack, times, values, interpolations ) { + // private method - /* + _createTrack( node, typedKeyframeTrack, times, values, interpolations ) { + + /* * optimizes here not to let KeyframeTrackPrototype optimize * because KeyframeTrackPrototype optimizes times and values but * doesn't optimize interpolations. */ - if ( times.length > 2 ) { + if ( times.length > 2 ) { - times = times.slice(); - values = values.slice(); - interpolations = interpolations.slice(); + times = times.slice(); + values = values.slice(); + interpolations = interpolations.slice(); - var stride = values.length / times.length; - var interpolateStride = interpolations.length / times.length; + const stride = values.length / times.length; + const interpolateStride = interpolations.length / times.length; - var index = 1; + let index = 1; - for ( var aheadIndex = 2, endIndex = times.length; aheadIndex < endIndex; aheadIndex ++ ) { + for ( let aheadIndex = 2, endIndex = times.length; aheadIndex < endIndex; aheadIndex ++ ) { - for ( var i = 0; i < stride; i ++ ) { + for ( let i = 0; i < stride; i ++ ) { - if ( values[ index * stride + i ] !== values[ ( index - 1 ) * stride + i ] || + if ( values[ index * stride + i ] !== values[ ( index - 1 ) * stride + i ] || values[ index * stride + i ] !== values[ aheadIndex * stride + i ] ) { - index ++; - break; - - } + index ++; + break; } - if ( aheadIndex > index ) { + } - times[ index ] = times[ aheadIndex ]; + if ( aheadIndex > index ) { - for ( var i = 0; i < stride; i ++ ) { + times[ index ] = times[ aheadIndex ]; - values[ index * stride + i ] = values[ aheadIndex * stride + i ]; + for ( let i = 0; i < stride; i ++ ) { - } + values[ index * stride + i ] = values[ aheadIndex * stride + i ]; - for ( var i = 0; i < interpolateStride; i ++ ) { + } - interpolations[ index * interpolateStride + i ] = interpolations[ aheadIndex * interpolateStride + i ]; + for ( let i = 0; i < interpolateStride; i ++ ) { - } + interpolations[ index * interpolateStride + i ] = interpolations[ aheadIndex * interpolateStride + i ]; } } - times.length = index + 1; - values.length = ( index + 1 ) * stride; - interpolations.length = ( index + 1 ) * interpolateStride; - } - var track = new typedKeyframeTrack( node, times, values ); + times.length = index + 1; + values.length = ( index + 1 ) * stride; + interpolations.length = ( index + 1 ) * interpolateStride; - track.createInterpolant = function InterpolantFactoryMethodCubicBezier( result ) { + } - return new CubicBezierInterpolation( this.times, this.values, this.getValueSize(), result, new Float32Array( interpolations ) ); + const track = new typedKeyframeTrack( node, times, values ); - }; + track.createInterpolant = function InterpolantFactoryMethodCubicBezier( result ) { - return track; + return new CubicBezierInterpolation( this.times, this.values, this.getValueSize(), result, new Float32Array( interpolations ) ); - } + }; - }; + return track; - // interpolation + } - function CubicBezierInterpolation( parameterPositions, sampleValues, sampleSize, resultBuffer, params ) { +} - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); +// interpolation - this.interpolationParams = params; +class CubicBezierInterpolation extends Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer, params ) { - CubicBezierInterpolation.prototype = Object.assign( Object.create( Interpolant.prototype ), { + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + + this.interpolationParams = params; - constructor: CubicBezierInterpolation, + } - interpolate_: function ( i1, t0, t, t1 ) { + interpolate_( i1, t0, t, t1 ) { - var result = this.resultBuffer; - var values = this.sampleValues; - var stride = this.valueSize; - var params = this.interpolationParams; + const result = this.resultBuffer; + const values = this.sampleValues; + const stride = this.valueSize; + const params = this.interpolationParams; - var offset1 = i1 * stride; - var offset0 = offset1 - stride; + const offset1 = i1 * stride; + const offset0 = offset1 - stride; - // No interpolation if next key frame is in one frame in 30fps. - // This is from MMD animation spec. - // '1.5' is for precision loss. times are Float32 in Three.js Animation system. - var weight1 = ( ( t1 - t0 ) < 1 / 30 * 1.5 ) ? 0.0 : ( t - t0 ) / ( t1 - t0 ); + // No interpolation if next key frame is in one frame in 30fps. + // This is from MMD animation spec. + // '1.5' is for precision loss. times are Float32 in Three.js Animation system. + const weight1 = ( ( t1 - t0 ) < 1 / 30 * 1.5 ) ? 0.0 : ( t - t0 ) / ( t1 - t0 ); - if ( stride === 4 ) { // Quaternion + if ( stride === 4 ) { // Quaternion - var x1 = params[ i1 * 4 + 0 ]; - var x2 = params[ i1 * 4 + 1 ]; - var y1 = params[ i1 * 4 + 2 ]; - var y2 = params[ i1 * 4 + 3 ]; + const x1 = params[ i1 * 4 + 0 ]; + const x2 = params[ i1 * 4 + 1 ]; + const y1 = params[ i1 * 4 + 2 ]; + const y2 = params[ i1 * 4 + 3 ]; - var ratio = this._calculate( x1, x2, y1, y2, weight1 ); + const ratio = this._calculate( x1, x2, y1, y2, weight1 ); - Quaternion.slerpFlat( result, 0, values, offset0, values, offset1, ratio ); + Quaternion.slerpFlat( result, 0, values, offset0, values, offset1, ratio ); - } else if ( stride === 3 ) { // Vector3 + } else if ( stride === 3 ) { // Vector3 - for ( var i = 0; i !== stride; ++ i ) { + for ( let i = 0; i !== stride; ++ i ) { - var x1 = params[ i1 * 12 + i * 4 + 0 ]; - var x2 = params[ i1 * 12 + i * 4 + 1 ]; - var y1 = params[ i1 * 12 + i * 4 + 2 ]; - var y2 = params[ i1 * 12 + i * 4 + 3 ]; + const x1 = params[ i1 * 12 + i * 4 + 0 ]; + const x2 = params[ i1 * 12 + i * 4 + 1 ]; + const y1 = params[ i1 * 12 + i * 4 + 2 ]; + const y2 = params[ i1 * 12 + i * 4 + 3 ]; - var ratio = this._calculate( x1, x2, y1, y2, weight1 ); + const ratio = this._calculate( x1, x2, y1, y2, weight1 ); - result[ i ] = values[ offset0 + i ] * ( 1 - ratio ) + values[ offset1 + i ] * ratio; + result[ i ] = values[ offset0 + i ] * ( 1 - ratio ) + values[ offset1 + i ] * ratio; - } + } - } else { // Number + } else { // Number - var x1 = params[ i1 * 4 + 0 ]; - var x2 = params[ i1 * 4 + 1 ]; - var y1 = params[ i1 * 4 + 2 ]; - var y2 = params[ i1 * 4 + 3 ]; + const x1 = params[ i1 * 4 + 0 ]; + const x2 = params[ i1 * 4 + 1 ]; + const y1 = params[ i1 * 4 + 2 ]; + const y2 = params[ i1 * 4 + 3 ]; - var ratio = this._calculate( x1, x2, y1, y2, weight1 ); + const ratio = this._calculate( x1, x2, y1, y2, weight1 ); - result[ 0 ] = values[ offset0 ] * ( 1 - ratio ) + values[ offset1 ] * ratio; + result[ 0 ] = values[ offset0 ] * ( 1 - ratio ) + values[ offset1 ] * ratio; - } + } - return result; + return result; - }, + } - _calculate: function ( x1, x2, y1, y2, x ) { + _calculate( x1, x2, y1, y2, x ) { - /* + /* * Cubic Bezier curves * https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves * @@ -2030,40 +2003,36 @@ var MMDLoader = ( function () { * https://en.wikipedia.org/wiki/Newton%27s_method) */ - var c = 0.5; - var t = c; - var s = 1.0 - t; - var loop = 15; - var eps = 1e-5; - var math = Math; - - var sst3, stt3, ttt; + let c = 0.5; + let t = c; + let s = 1.0 - t; + const loop = 15; + const eps = 1e-5; + const math = Math; - for ( var i = 0; i < loop; i ++ ) { + let sst3, stt3, ttt; - sst3 = 3.0 * s * s * t; - stt3 = 3.0 * s * t * t; - ttt = t * t * t; + for ( let i = 0; i < loop; i ++ ) { - var ft = ( sst3 * x1 ) + ( stt3 * x2 ) + ( ttt ) - x; + sst3 = 3.0 * s * s * t; + stt3 = 3.0 * s * t * t; + ttt = t * t * t; - if ( math.abs( ft ) < eps ) break; + const ft = ( sst3 * x1 ) + ( stt3 * x2 ) + ( ttt ) - x; - c /= 2.0; + if ( math.abs( ft ) < eps ) break; - t += ( ft < 0 ) ? c : - c; - s = 1.0 - t; + c /= 2.0; - } - - return ( sst3 * y1 ) + ( stt3 * y2 ) + ttt; + t += ( ft < 0 ) ? c : - c; + s = 1.0 - t; } - } ); + return ( sst3 * y1 ) + ( stt3 * y2 ) + ttt; - return MMDLoader; + } -} )(); +} export { MMDLoader }; diff --git a/examples/jsm/loaders/MTLLoader.js b/examples/jsm/loaders/MTLLoader.js index 51c8482e3162ae..fba96470d7dd5c 100644 --- a/examples/jsm/loaders/MTLLoader.js +++ b/examples/jsm/loaders/MTLLoader.js @@ -15,15 +15,13 @@ import { * Loads a Wavefront .mtl file specifying materials */ -var MTLLoader = function ( manager ) { +class MTLLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: MTLLoader, + } /** * Loads and parses a MTL asset from a URL. @@ -38,13 +36,13 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @note In order for relative texture references to resolve correctly * you must call setResourcePath() explicitly prior to load. */ - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setRequestHeader( this.requestHeader ); loader.setWithCredentials( this.withCredentials ); @@ -72,36 +70,36 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - setMaterialOptions: function ( value ) { + setMaterialOptions( value ) { this.materialOptions = value; return this; - }, + } /** * Parses a MTL file. * * @param {String} text - Content of MTL file - * @return {MTLLoader.MaterialCreator} + * @return {MaterialCreator} * * @see setPath setResourcePath * * @note In order for relative texture references to resolve correctly * you must call setResourcePath() explicitly prior to parse. */ - parse: function ( text, path ) { + parse( text, path ) { - var lines = text.split( '\n' ); - var info = {}; - var delimiter_pattern = /\s+/; - var materialsInfo = {}; + const lines = text.split( '\n' ); + let info = {}; + const delimiter_pattern = /\s+/; + const materialsInfo = {}; - for ( var i = 0; i < lines.length; i ++ ) { + for ( let i = 0; i < lines.length; i ++ ) { - var line = lines[ i ]; + let line = lines[ i ]; line = line.trim(); if ( line.length === 0 || line.charAt( 0 ) === '#' ) { @@ -111,12 +109,12 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var pos = line.indexOf( ' ' ); + const pos = line.indexOf( ' ' ); - var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; + let key = ( pos >= 0 ) ? line.substring( 0, pos ) : line; key = key.toLowerCase(); - var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; + let value = ( pos >= 0 ) ? line.substring( pos + 1 ) : ''; value = value.trim(); if ( key === 'newmtl' ) { @@ -130,7 +128,7 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) { - var ss = value.split( delimiter_pattern, 3 ); + const ss = value.split( delimiter_pattern, 3 ); info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ]; } else { @@ -143,7 +141,7 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var materialCreator = new MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions ); + const materialCreator = new MaterialCreator( this.resourcePath || path, this.materialOptions ); materialCreator.setCrossOrigin( this.crossOrigin ); materialCreator.setManager( this.manager ); materialCreator.setMaterials( materialsInfo ); @@ -151,7 +149,7 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} /** * Create a new MTLLoader.MaterialCreator @@ -168,69 +166,67 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @constructor */ -MTLLoader.MaterialCreator = function ( baseUrl, options ) { - - this.baseUrl = baseUrl || ''; - this.options = options; - this.materialsInfo = {}; - this.materials = {}; - this.materialsArray = []; - this.nameLookup = {}; +class MaterialCreator { - this.side = ( this.options && this.options.side ) ? this.options.side : FrontSide; - this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : RepeatWrapping; + constructor( baseUrl = '', options = {} ) { -}; + this.baseUrl = baseUrl; + this.options = options; + this.materialsInfo = {}; + this.materials = {}; + this.materialsArray = []; + this.nameLookup = {}; -MTLLoader.MaterialCreator.prototype = { + this.crossOrigin = 'anonymous'; - constructor: MTLLoader.MaterialCreator, + this.side = ( this.options.side !== undefined ) ? this.options.side : FrontSide; + this.wrap = ( this.options.wrap !== undefined ) ? this.options.wrap : RepeatWrapping; - crossOrigin: 'anonymous', + } - setCrossOrigin: function ( value ) { + setCrossOrigin( value ) { this.crossOrigin = value; return this; - }, + } - setManager: function ( value ) { + setManager( value ) { this.manager = value; - }, + } - setMaterials: function ( materialsInfo ) { + setMaterials( materialsInfo ) { this.materialsInfo = this.convert( materialsInfo ); this.materials = {}; this.materialsArray = []; this.nameLookup = {}; - }, + } - convert: function ( materialsInfo ) { + convert( materialsInfo ) { if ( ! this.options ) return materialsInfo; - var converted = {}; + const converted = {}; - for ( var mn in materialsInfo ) { + for ( const mn in materialsInfo ) { // Convert materials info into normalized form based on options - var mat = materialsInfo[ mn ]; + const mat = materialsInfo[ mn ]; - var covmat = {}; + const covmat = {}; converted[ mn ] = covmat; - for ( var prop in mat ) { + for ( const prop in mat ) { - var save = true; - var value = mat[ prop ]; - var lprop = prop.toLowerCase(); + let save = true; + let value = mat[ prop ]; + const lprop = prop.toLowerCase(); switch ( lprop ) { @@ -278,29 +274,29 @@ MTLLoader.MaterialCreator.prototype = { return converted; - }, + } - preload: function () { + preload() { - for ( var mn in this.materialsInfo ) { + for ( const mn in this.materialsInfo ) { this.create( mn ); } - }, + } - getIndex: function ( materialName ) { + getIndex( materialName ) { return this.nameLookup[ materialName ]; - }, + } - getAsArray: function () { + getAsArray() { - var index = 0; + let index = 0; - for ( var mn in this.materialsInfo ) { + for ( const mn in this.materialsInfo ) { this.materialsArray[ index ] = this.create( mn ); this.nameLookup[ mn ] = index; @@ -310,9 +306,9 @@ MTLLoader.MaterialCreator.prototype = { return this.materialsArray; - }, + } - create: function ( materialName ) { + create( materialName ) { if ( this.materials[ materialName ] === undefined ) { @@ -322,15 +318,15 @@ MTLLoader.MaterialCreator.prototype = { return this.materials[ materialName ]; - }, + } - createMaterial_: function ( materialName ) { + createMaterial_( materialName ) { // Create material - var scope = this; - var mat = this.materialsInfo[ materialName ]; - var params = { + const scope = this; + const mat = this.materialsInfo[ materialName ]; + const params = { name: materialName, side: this.side @@ -353,8 +349,8 @@ MTLLoader.MaterialCreator.prototype = { if ( params[ mapType ] ) return; // Keep the first encountered texture - var texParams = scope.getTextureParams( value, params ); - var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); + const texParams = scope.getTextureParams( value, params ); + const map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) ); map.repeat.copy( texParams.scale ); map.offset.copy( texParams.offset ); @@ -366,10 +362,10 @@ MTLLoader.MaterialCreator.prototype = { } - for ( var prop in mat ) { + for ( const prop in mat ) { - var value = mat[ prop ]; - var n; + const value = mat[ prop ]; + let n; if ( value === '' ) continue; @@ -492,19 +488,19 @@ MTLLoader.MaterialCreator.prototype = { this.materials[ materialName ] = new MeshPhongMaterial( params ); return this.materials[ materialName ]; - }, + } - getTextureParams: function ( value, matParams ) { + getTextureParams( value, matParams ) { - var texParams = { + const texParams = { scale: new Vector2( 1, 1 ), offset: new Vector2( 0, 0 ) }; - var items = value.split( /\s+/ ); - var pos; + const items = value.split( /\s+/ ); + let pos; pos = items.indexOf( '-bm' ); @@ -536,13 +532,12 @@ MTLLoader.MaterialCreator.prototype = { texParams.url = items.join( ' ' ).trim(); return texParams; - }, + } - loadTexture: function ( url, mapping, onLoad, onProgress, onError ) { + loadTexture( url, mapping, onLoad, onProgress, onError ) { - var texture; - var manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager; - var loader = manager.getHandler( url ); + const manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager; + let loader = manager.getHandler( url ); if ( loader === null ) { @@ -551,7 +546,8 @@ MTLLoader.MaterialCreator.prototype = { } if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin ); - texture = loader.load( url, onLoad, onProgress, onError ); + + const texture = loader.load( url, onLoad, onProgress, onError ); if ( mapping !== undefined ) texture.mapping = mapping; @@ -559,6 +555,6 @@ MTLLoader.MaterialCreator.prototype = { } -}; +} export { MTLLoader }; diff --git a/examples/jsm/loaders/NRRDLoader.js b/examples/jsm/loaders/NRRDLoader.js index 59aa50ca24ca0e..534dc31eca51ad 100644 --- a/examples/jsm/loaders/NRRDLoader.js +++ b/examples/jsm/loaders/NRRDLoader.js @@ -4,24 +4,22 @@ import { Matrix4, Vector3 } from '../../../build/three.module.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; import { Volume } from '../misc/Volume.js'; -var NRRDLoader = function ( manager ) { +class NRRDLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; - -NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + super( manager ); - constructor: NRRDLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -50,21 +48,21 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { // this parser is largely inspired from the XTK NRRD parser : https://github.com/xtk/X - var _data = data; + let _data = data; - var _dataPointer = 0; + let _dataPointer = 0; - var _nativeLittleEndian = new Int8Array( new Int16Array( [ 1 ] ).buffer )[ 0 ] > 0; + const _nativeLittleEndian = new Int8Array( new Int16Array( [ 1 ] ).buffer )[ 0 ] > 0; - var _littleEndian = true; + const _littleEndian = true; - var headerObject = {}; + const headerObject = {}; function scan( type, chunks ) { @@ -74,8 +72,8 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var _chunkSize = 1; - var _array_type = Uint8Array; + let _chunkSize = 1; + let _array_type = Uint8Array; switch ( type ) { @@ -119,7 +117,7 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } // increase the data pointer in-place - var _bytes = new _array_type( _data.slice( _dataPointer, + let _bytes = new _array_type( _data.slice( _dataPointer, _dataPointer += chunks * _chunkSize ) ); // if required, flip the endianness of the bytes @@ -146,12 +144,12 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function flipEndianness( array, chunkSize ) { - var u8 = new Uint8Array( array.buffer, array.byteOffset, array.byteLength ); - for ( var i = 0; i < array.byteLength; i += chunkSize ) { + const u8 = new Uint8Array( array.buffer, array.byteOffset, array.byteLength ); + for ( let i = 0; i < array.byteLength; i += chunkSize ) { - for ( var j = i + chunkSize - 1, k = i; j > k; j --, k ++ ) { + for ( let j = i + chunkSize - 1, k = i; j > k; j --, k ++ ) { - var tmp = u8[ k ]; + const tmp = u8[ k ]; u8[ k ] = u8[ j ]; u8[ j ] = tmp; @@ -166,8 +164,8 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { //parse the header function parseHeader( header ) { - var data, field, fn, i, l, lines, m, _i, _len; - lines = header.split( /\r?\n/ ); + let data, field, fn, i, l, m, _i, _len; + const lines = header.split( /\r?\n/ ); for ( _i = 0, _len = lines.length; _i < _len; _i ++ ) { l = lines[ _i ]; @@ -180,7 +178,7 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { field = m[ 1 ].trim(); data = m[ 2 ].trim(); - fn = NRRDLoader.prototype.fieldFunctions[ field ]; + fn = _fieldFunctions[ field ]; if ( fn ) { fn.call( headerObject, data ); @@ -233,34 +231,34 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { //parse the data when registred as one of this type : 'text', 'ascii', 'txt' function parseDataAsText( data, start, end ) { - var number = ''; + let number = ''; start = start || 0; end = end || data.length; - var value; + let value; //length of the result is the product of the sizes - var lengthOfTheResult = headerObject.sizes.reduce( function ( previous, current ) { + const lengthOfTheResult = headerObject.sizes.reduce( function ( previous, current ) { return previous * current; }, 1 ); - var base = 10; + let base = 10; if ( headerObject.encoding === 'hex' ) { base = 16; } - var result = new headerObject.__array( lengthOfTheResult ); - var resultIndex = 0; - var parsingFunction = parseInt; + const result = new headerObject.__array( lengthOfTheResult ); + let resultIndex = 0; + let parsingFunction = parseInt; if ( headerObject.__array === Float32Array || headerObject.__array === Float64Array ) { parsingFunction = parseFloat; } - for ( var i = start; i < end; i ++ ) { + for ( let i = start; i < end; i ++ ) { value = data[ i ]; //if value is not a space @@ -294,11 +292,11 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var _bytes = scan( 'uchar', data.byteLength ); - var _length = _bytes.length; - var _header = null; - var _data_start = 0; - var i; + const _bytes = scan( 'uchar', data.byteLength ); + const _length = _bytes.length; + let _header = null; + let _data_start = 0; + let i; for ( i = 1; i < _length; i ++ ) { if ( _bytes[ i - 1 ] == 10 && _bytes[ i ] == 10 ) { @@ -317,7 +315,7 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // parse the header parseHeader( _header ); - var _data = _bytes.subarray( _data_start ); // the data without header + _data = _bytes.subarray( _data_start ); // the data without header if ( headerObject.encoding.substring( 0, 2 ) === 'gz' ) { // we need to decompress the datastream @@ -331,9 +329,9 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( headerObject.encoding === 'raw' ) { //we need to copy the array to create a new array buffer, else we retrieve the original arraybuffer with the header - var _copy = new Uint8Array( _data.length ); + const _copy = new Uint8Array( _data.length ); - for ( var i = 0; i < _data.length; i ++ ) { + for ( let i = 0; i < _data.length; i ++ ) { _copy[ i ] = _data[ i ]; @@ -346,16 +344,16 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // .. let's use the underlying array buffer _data = _data.buffer; - var volume = new Volume(); + const volume = new Volume(); volume.header = headerObject; // // parse the (unzipped) data to a datastream of the correct type // volume.data = new headerObject.__array( _data ); // get the min and max intensities - var min_max = volume.computeMinMax(); - var min = min_max[ 0 ]; - var max = min_max[ 1 ]; + const min_max = volume.computeMinMax(); + const min = min_max[ 0 ]; + const max = min_max[ 1 ]; // attach the scalar range to the volume volume.windowLow = min; volume.windowHigh = max; @@ -366,11 +364,11 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { volume.yLength = volume.dimensions[ 1 ]; volume.zLength = volume.dimensions[ 2 ]; // spacing - var spacingX = ( new Vector3( headerObject.vectors[ 0 ][ 0 ], headerObject.vectors[ 0 ][ 1 ], + const spacingX = ( new Vector3( headerObject.vectors[ 0 ][ 0 ], headerObject.vectors[ 0 ][ 1 ], headerObject.vectors[ 0 ][ 2 ] ) ).length(); - var spacingY = ( new Vector3( headerObject.vectors[ 1 ][ 0 ], headerObject.vectors[ 1 ][ 1 ], + const spacingY = ( new Vector3( headerObject.vectors[ 1 ][ 0 ], headerObject.vectors[ 1 ][ 1 ], headerObject.vectors[ 1 ][ 2 ] ) ).length(); - var spacingZ = ( new Vector3( headerObject.vectors[ 2 ][ 0 ], headerObject.vectors[ 2 ][ 1 ], + const spacingZ = ( new Vector3( headerObject.vectors[ 2 ][ 0 ], headerObject.vectors[ 2 ][ 1 ], headerObject.vectors[ 2 ][ 2 ] ) ).length(); volume.spacing = [ spacingX, spacingY, spacingZ ]; @@ -378,9 +376,9 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // Create IJKtoRAS matrix volume.matrix = new Matrix4(); - var _spaceX = 1; - var _spaceY = 1; - var _spaceZ = 1; + let _spaceX = 1; + let _spaceY = 1; + const _spaceZ = 1; if ( headerObject.space == 'left-posterior-superior' ) { @@ -404,7 +402,7 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else { - var v = headerObject.vectors; + const v = headerObject.vectors; volume.matrix.set( _spaceX * v[ 0 ][ 0 ], _spaceX * v[ 1 ][ 0 ], _spaceX * v[ 2 ][ 0 ], 0, @@ -434,9 +432,9 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return volume; - }, + } - parseChars: function ( array, start, end ) { + parseChars( array, start, end ) { // without borders, use the whole array if ( start === undefined ) { @@ -451,9 +449,9 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var output = ''; + let output = ''; // create and append the chars - var i = 0; + let i = 0; for ( i = start; i < end; ++ i ) { output += String.fromCharCode( array[ i ] ); @@ -462,178 +460,176 @@ NRRDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return output; - }, + } - fieldFunctions: { +} - type: function ( data ) { +const _fieldFunctions = { - switch ( data ) { + type: function ( data ) { - case 'uchar': - case 'unsigned char': - case 'uint8': - case 'uint8_t': - this.__array = Uint8Array; - break; - case 'signed char': - case 'int8': - case 'int8_t': - this.__array = Int8Array; - break; - case 'short': - case 'short int': - case 'signed short': - case 'signed short int': - case 'int16': - case 'int16_t': - this.__array = Int16Array; - break; - case 'ushort': - case 'unsigned short': - case 'unsigned short int': - case 'uint16': - case 'uint16_t': - this.__array = Uint16Array; - break; - case 'int': - case 'signed int': - case 'int32': - case 'int32_t': - this.__array = Int32Array; - break; - case 'uint': - case 'unsigned int': - case 'uint32': - case 'uint32_t': - this.__array = Uint32Array; - break; - case 'float': - this.__array = Float32Array; - break; - case 'double': - this.__array = Float64Array; - break; - default: - throw new Error( 'Unsupported NRRD data type: ' + data ); + switch ( data ) { - } + case 'uchar': + case 'unsigned char': + case 'uint8': + case 'uint8_t': + this.__array = Uint8Array; + break; + case 'signed char': + case 'int8': + case 'int8_t': + this.__array = Int8Array; + break; + case 'short': + case 'short int': + case 'signed short': + case 'signed short int': + case 'int16': + case 'int16_t': + this.__array = Int16Array; + break; + case 'ushort': + case 'unsigned short': + case 'unsigned short int': + case 'uint16': + case 'uint16_t': + this.__array = Uint16Array; + break; + case 'int': + case 'signed int': + case 'int32': + case 'int32_t': + this.__array = Int32Array; + break; + case 'uint': + case 'unsigned int': + case 'uint32': + case 'uint32_t': + this.__array = Uint32Array; + break; + case 'float': + this.__array = Float32Array; + break; + case 'double': + this.__array = Float64Array; + break; + default: + throw new Error( 'Unsupported NRRD data type: ' + data ); - return this.type = data; + } - }, + return this.type = data; - endian: function ( data ) { + }, - return this.endian = data; + endian: function ( data ) { - }, + return this.endian = data; - encoding: function ( data ) { + }, - return this.encoding = data; + encoding: function ( data ) { - }, + return this.encoding = data; - dimension: function ( data ) { + }, - return this.dim = parseInt( data, 10 ); + dimension: function ( data ) { - }, + return this.dim = parseInt( data, 10 ); - sizes: function ( data ) { + }, - var i; - return this.sizes = ( function () { + sizes: function ( data ) { - var _i, _len, _ref, _results; - _ref = data.split( /\s+/ ); - _results = []; + let i; + return this.sizes = ( function () { - for ( _i = 0, _len = _ref.length; _i < _len; _i ++ ) { + const _ref = data.split( /\s+/ ); + const _results = []; - i = _ref[ _i ]; - _results.push( parseInt( i, 10 ) ); + for ( let _i = 0, _len = _ref.length; _i < _len; _i ++ ) { - } + i = _ref[ _i ]; + _results.push( parseInt( i, 10 ) ); - return _results; + } - } )(); + return _results; - }, + } )(); - space: function ( data ) { + }, - return this.space = data; + space: function ( data ) { - }, + return this.space = data; - 'space origin': function ( data ) { + }, - return this.space_origin = data.split( '(' )[ 1 ].split( ')' )[ 0 ].split( ',' ); + 'space origin': function ( data ) { - }, + return this.space_origin = data.split( '(' )[ 1 ].split( ')' )[ 0 ].split( ',' ); - 'space directions': function ( data ) { + }, - var f, parts, v; - parts = data.match( /\(.*?\)/g ); - return this.vectors = ( function () { + 'space directions': function ( data ) { - var _i, _len, _results; - _results = []; + let f, v; + const parts = data.match( /\(.*?\)/g ); + return this.vectors = ( function () { - for ( _i = 0, _len = parts.length; _i < _len; _i ++ ) { + const _results = []; - v = parts[ _i ]; - _results.push( ( function () { + for ( let _i = 0, _len = parts.length; _i < _len; _i ++ ) { - var _j, _len2, _ref, _results2; - _ref = v.slice( 1, - 1 ).split( /,/ ); - _results2 = []; + v = parts[ _i ]; + _results.push( ( function () { - for ( _j = 0, _len2 = _ref.length; _j < _len2; _j ++ ) { + const _ref = v.slice( 1, - 1 ).split( /,/ ); + const _results2 = []; - f = _ref[ _j ]; - _results2.push( parseFloat( f ) ); + for ( let _j = 0, _len2 = _ref.length; _j < _len2; _j ++ ) { - } + f = _ref[ _j ]; + _results2.push( parseFloat( f ) ); - return _results2; + } - } )() ); + return _results2; - } + } )() ); + + } - return _results; + return _results; - } )(); + } )(); - }, + }, - spacings: function ( data ) { + spacings: function ( data ) { - var f, parts; - parts = data.split( /\s+/ ); - return this.spacings = ( function () { + let f; + const parts = data.split( /\s+/ ); + return this.spacings = ( function () { - var _i, _len, _results = []; + const _results = []; - for ( _i = 0, _len = parts.length; _i < _len; _i ++ ) { + for ( let _i = 0, _len = parts.length; _i < _len; _i ++ ) { - f = parts[ _i ]; - _results.push( parseFloat( f ) ); + f = parts[ _i ]; + _results.push( parseFloat( f ) ); - } + } - return _results; + return _results; - } )(); + } )(); - } } -} ); +}; export { NRRDLoader }; diff --git a/examples/jsm/loaders/NodeMaterialLoader.js b/examples/jsm/loaders/NodeMaterialLoader.js index e03c29369f521a..8a64d60db6b3f3 100644 --- a/examples/jsm/loaders/NodeMaterialLoader.js +++ b/examples/jsm/loaders/NodeMaterialLoader.js @@ -1,81 +1,29 @@ import { - DefaultLoadingManager, + Loader, FileLoader } from '../../../build/three.module.js'; import * as Nodes from '../nodes/Nodes.js'; -var NodeMaterialLoader = function ( manager, library ) { +class NodeMaterialLoader extends Loader { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + constructor( manager, library = {} ) { - this.nodes = {}; - this.materials = {}; - this.passes = {}; - this.names = {}; - this.library = library || {}; + super( manager ); -}; - -var NodeMaterialLoaderUtils = { - - replaceUUIDObject: function ( object, uuid, value, recursive ) { - - recursive = recursive !== undefined ? recursive : true; - - if ( typeof uuid === 'object' ) uuid = uuid.uuid; - - if ( typeof object === 'object' ) { - - var keys = Object.keys( object ); - - for ( var i = 0; i < keys.length; i ++ ) { - - var key = keys[ i ]; - - if ( recursive ) { - - object[ key ] = this.replaceUUIDObject( object[ key ], uuid, value ); - - } - - if ( key === uuid ) { - - object[ uuid ] = object[ key ]; - - delete object[ key ]; - - } - - } - - } - - return object === uuid ? value : object; - - }, - - replaceUUID: function ( json, uuid, value ) { - - this.replaceUUIDObject( json, uuid, value, false ); - this.replaceUUIDObject( json.nodes, uuid, value ); - this.replaceUUIDObject( json.materials, uuid, value ); - this.replaceUUIDObject( json.passes, uuid, value ); - this.replaceUUIDObject( json.library, uuid, value, false ); - - return json; + this.nodes = {}; + this.materials = {}; + this.passes = {}; + this.names = {}; + this.library = library; } -}; - -Object.assign( NodeMaterialLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.load( url, function ( text ) { @@ -85,22 +33,15 @@ Object.assign( NodeMaterialLoader.prototype, { return this; - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - }, + } - getObjectByName: function ( uuid ) { + getObjectByName( uuid ) { return this.names[ uuid ]; - }, + } - getObjectById: function ( uuid ) { + getObjectById( uuid ) { return this.library[ uuid ] || this.nodes[ uuid ] || @@ -108,11 +49,11 @@ Object.assign( NodeMaterialLoader.prototype, { this.passes[ uuid ] || this.names[ uuid ]; - }, + } - getNode: function ( uuid ) { + getNode( uuid ) { - var object = this.getObjectById( uuid ); + const object = this.getObjectById( uuid ); if ( ! object ) { @@ -122,9 +63,9 @@ Object.assign( NodeMaterialLoader.prototype, { return object; - }, + } - resolve: function ( json ) { + resolve( json ) { switch ( typeof json ) { @@ -147,7 +88,7 @@ Object.assign( NodeMaterialLoader.prototype, { if ( Array.isArray( json ) ) { - for ( var i = 0; i < json.length; i ++ ) { + for ( let i = 0; i < json.length; i ++ ) { json[ i ] = this.resolve( json[ i ] ); @@ -155,7 +96,7 @@ Object.assign( NodeMaterialLoader.prototype, { } else { - for ( var prop in json ) { + for ( const prop in json ) { if ( prop === 'uuid' ) continue; @@ -169,11 +110,11 @@ Object.assign( NodeMaterialLoader.prototype, { return json; - }, + } - declare: function ( json ) { + declare( json ) { - var uuid, node, object; + let uuid, node, object; for ( uuid in json.nodes ) { @@ -235,11 +176,11 @@ Object.assign( NodeMaterialLoader.prototype, { return json; - }, + } - parse: function ( json ) { + parse( json ) { - var uuid; + let uuid; json = this.resolve( this.declare( json ) ); @@ -265,6 +206,58 @@ Object.assign( NodeMaterialLoader.prototype, { } -} ); +} + +class NodeMaterialLoaderUtils { + + static replaceUUIDObject( object, uuid, value, recursive ) { + + recursive = recursive !== undefined ? recursive : true; + + if ( typeof uuid === 'object' ) uuid = uuid.uuid; + + if ( typeof object === 'object' ) { + + const keys = Object.keys( object ); + + for ( let i = 0; i < keys.length; i ++ ) { + + const key = keys[ i ]; + + if ( recursive ) { + + object[ key ] = this.replaceUUIDObject( object[ key ], uuid, value ); + + } + + if ( key === uuid ) { + + object[ uuid ] = object[ key ]; + + delete object[ key ]; + + } + + } + + } + + return object === uuid ? value : object; + + } + + static replaceUUID( json, uuid, value ) { + + this.replaceUUIDObject( json, uuid, value, false ); + this.replaceUUIDObject( json.nodes, uuid, value ); + this.replaceUUIDObject( json.materials, uuid, value ); + this.replaceUUIDObject( json.passes, uuid, value ); + this.replaceUUIDObject( json.library, uuid, value, false ); + + return json; + + } + +} export { NodeMaterialLoader, NodeMaterialLoaderUtils }; diff --git a/examples/jsm/loaders/OBJLoader.js b/examples/jsm/loaders/OBJLoader.js index 6f2e4b50dec035..745ae0e315f114 100644 --- a/examples/jsm/loaders/OBJLoader.js +++ b/examples/jsm/loaders/OBJLoader.js @@ -14,678 +14,675 @@ import { Vector3 } from '../../../build/three.module.js'; -var OBJLoader = ( function () { +// o object_name | g group_name +const _object_pattern = /^[og]\s*(.+)?/; +// mtllib file_reference +const _material_library_pattern = /^mtllib /; +// usemtl material_name +const _material_use_pattern = /^usemtl /; +// usemap map_name +const _map_use_pattern = /^usemap /; - // o object_name | g group_name - var object_pattern = /^[og]\s*(.+)?/; - // mtllib file_reference - var material_library_pattern = /^mtllib /; - // usemtl material_name - var material_use_pattern = /^usemtl /; - // usemap map_name - var map_use_pattern = /^usemap /; +const _vA = new Vector3(); +const _vB = new Vector3(); +const _vC = new Vector3(); - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); +const _ab = new Vector3(); +const _cb = new Vector3(); - var ab = new Vector3(); - var cb = new Vector3(); +function ParserState() { - function ParserState() { + const state = { + objects: [], + object: {}, - var state = { - objects: [], - object: {}, + vertices: [], + normals: [], + colors: [], + uvs: [], - vertices: [], - normals: [], - colors: [], - uvs: [], + materials: {}, + materialLibraries: [], - materials: {}, - materialLibraries: [], + startObject: function ( name, fromDeclaration ) { - startObject: function ( name, fromDeclaration ) { + // If the current object (initial from reset) is not from a g/o declaration in the parsed + // file. We need to use it for the first parsed g/o to keep things in sync. + if ( this.object && this.object.fromDeclaration === false ) { - // If the current object (initial from reset) is not from a g/o declaration in the parsed - // file. We need to use it for the first parsed g/o to keep things in sync. - if ( this.object && this.object.fromDeclaration === false ) { + this.object.name = name; + this.object.fromDeclaration = ( fromDeclaration !== false ); + return; - this.object.name = name; - this.object.fromDeclaration = ( fromDeclaration !== false ); - return; - - } - - var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); + } - if ( this.object && typeof this.object._finalize === 'function' ) { + const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); - this.object._finalize( true ); + if ( this.object && typeof this.object._finalize === 'function' ) { - } + this.object._finalize( true ); - this.object = { - name: name || '', - fromDeclaration: ( fromDeclaration !== false ), + } - geometry: { - vertices: [], - normals: [], - colors: [], - uvs: [], - hasUVIndices: false - }, - materials: [], - smooth: true, + this.object = { + name: name || '', + fromDeclaration: ( fromDeclaration !== false ), - startMaterial: function ( name, libraries ) { + geometry: { + vertices: [], + normals: [], + colors: [], + uvs: [], + hasUVIndices: false + }, + materials: [], + smooth: true, - var previous = this._finalize( false ); + startMaterial: function ( name, libraries ) { - // New usemtl declaration overwrites an inherited material, except if faces were declared - // after the material, then it must be preserved for proper MultiMaterial continuation. - if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { + const previous = this._finalize( false ); - this.materials.splice( previous.index, 1 ); + // New usemtl declaration overwrites an inherited material, except if faces were declared + // after the material, then it must be preserved for proper MultiMaterial continuation. + if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { - } + this.materials.splice( previous.index, 1 ); - var material = { - index: this.materials.length, - name: name || '', - mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), - smooth: ( previous !== undefined ? previous.smooth : this.smooth ), - groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), - groupEnd: - 1, - groupCount: - 1, - inherited: false, - - clone: function ( index ) { - - var cloned = { - index: ( typeof index === 'number' ? index : this.index ), - name: this.name, - mtllib: this.mtllib, - smooth: this.smooth, - groupStart: 0, - groupEnd: - 1, - groupCount: - 1, - inherited: false - }; - cloned.clone = this.clone.bind( cloned ); - return cloned; + } - } - }; + const material = { + index: this.materials.length, + name: name || '', + mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), + smooth: ( previous !== undefined ? previous.smooth : this.smooth ), + groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), + groupEnd: - 1, + groupCount: - 1, + inherited: false, + + clone: function ( index ) { + + const cloned = { + index: ( typeof index === 'number' ? index : this.index ), + name: this.name, + mtllib: this.mtllib, + smooth: this.smooth, + groupStart: 0, + groupEnd: - 1, + groupCount: - 1, + inherited: false + }; + cloned.clone = this.clone.bind( cloned ); + return cloned; - this.materials.push( material ); + } + }; - return material; + this.materials.push( material ); - }, + return material; - currentMaterial: function () { + }, - if ( this.materials.length > 0 ) { + currentMaterial: function () { - return this.materials[ this.materials.length - 1 ]; + if ( this.materials.length > 0 ) { - } + return this.materials[ this.materials.length - 1 ]; - return undefined; + } - }, + return undefined; - _finalize: function ( end ) { + }, - var lastMultiMaterial = this.currentMaterial(); - if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { + _finalize: function ( end ) { - lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; - lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; - lastMultiMaterial.inherited = false; + const lastMultiMaterial = this.currentMaterial(); + if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { - } + lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; + lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; + lastMultiMaterial.inherited = false; - // Ignore objects tail materials if no face declarations followed them before a new o/g started. - if ( end && this.materials.length > 1 ) { + } - for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { + // Ignore objects tail materials if no face declarations followed them before a new o/g started. + if ( end && this.materials.length > 1 ) { - if ( this.materials[ mi ].groupCount <= 0 ) { + for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) { - this.materials.splice( mi, 1 ); + if ( this.materials[ mi ].groupCount <= 0 ) { - } + this.materials.splice( mi, 1 ); } } - // Guarantee at least one empty material, this makes the creation later more straight forward. - if ( end && this.materials.length === 0 ) { - - this.materials.push( { - name: '', - smooth: this.smooth - } ); + } - } + // Guarantee at least one empty material, this makes the creation later more straight forward. + if ( end && this.materials.length === 0 ) { - return lastMultiMaterial; + this.materials.push( { + name: '', + smooth: this.smooth + } ); } - }; - - // Inherit previous objects material. - // Spec tells us that a declared material must be set to all objects until a new material is declared. - // If a usemtl declaration is encountered while this new object is being parsed, it will - // overwrite the inherited material. Exception being that there was already face declarations - // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - - var declared = previousMaterial.clone( 0 ); - declared.inherited = true; - this.object.materials.push( declared ); + return lastMultiMaterial; } + }; - this.objects.push( this.object ); + // Inherit previous objects material. + // Spec tells us that a declared material must be set to all objects until a new material is declared. + // If a usemtl declaration is encountered while this new object is being parsed, it will + // overwrite the inherited material. Exception being that there was already face declarations + // to the inherited material, then it will be preserved for proper MultiMaterial continuation. - }, + if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { - finalize: function () { + const declared = previousMaterial.clone( 0 ); + declared.inherited = true; + this.object.materials.push( declared ); - if ( this.object && typeof this.object._finalize === 'function' ) { + } - this.object._finalize( true ); + this.objects.push( this.object ); - } + }, - }, + finalize: function () { - parseVertexIndex: function ( value, len ) { + if ( this.object && typeof this.object._finalize === 'function' ) { - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + this.object._finalize( true ); - }, + } - parseNormalIndex: function ( value, len ) { + }, - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; + parseVertexIndex: function ( value, len ) { - }, + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - parseUVIndex: function ( value, len ) { + }, - var index = parseInt( value, 10 ); - return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; + parseNormalIndex: function ( value, len ) { - }, + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; - addVertex: function ( a, b, c ) { + }, - var src = this.vertices; - var dst = this.object.geometry.vertices; + parseUVIndex: function ( value, len ) { - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + const index = parseInt( value, 10 ); + return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; - }, + }, - addVertexPoint: function ( a ) { + addVertex: function ( a, b, c ) { - var src = this.vertices; - var dst = this.object.geometry.vertices; + const src = this.vertices; + const dst = this.object.geometry.vertices; - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - }, + }, - addVertexLine: function ( a ) { + addVertexPoint: function ( a ) { - var src = this.vertices; - var dst = this.object.geometry.vertices; + const src = this.vertices; + const dst = this.object.geometry.vertices; - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - }, + }, - addNormal: function ( a, b, c ) { + addVertexLine: function ( a ) { - var src = this.normals; - var dst = this.object.geometry.normals; + const src = this.vertices; + const dst = this.object.geometry.vertices; - dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - }, + }, - addFaceNormal: function ( a, b, c ) { + addNormal: function ( a, b, c ) { - var src = this.vertices; - var dst = this.object.geometry.normals; + const src = this.normals; + const dst = this.object.geometry.normals; - vA.fromArray( src, a ); - vB.fromArray( src, b ); - vC.fromArray( src, c ); + dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + }, - cb.normalize(); + addFaceNormal: function ( a, b, c ) { - dst.push( cb.x, cb.y, cb.z ); - dst.push( cb.x, cb.y, cb.z ); - dst.push( cb.x, cb.y, cb.z ); + const src = this.vertices; + const dst = this.object.geometry.normals; - }, + _vA.fromArray( src, a ); + _vB.fromArray( src, b ); + _vC.fromArray( src, c ); - addColor: function ( a, b, c ) { + _cb.subVectors( _vC, _vB ); + _ab.subVectors( _vA, _vB ); + _cb.cross( _ab ); - var src = this.colors; - var dst = this.object.geometry.colors; + _cb.normalize(); - if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); - if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); - if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); + dst.push( _cb.x, _cb.y, _cb.z ); - }, + }, - addUV: function ( a, b, c ) { + addColor: function ( a, b, c ) { - var src = this.uvs; - var dst = this.object.geometry.uvs; + const src = this.colors; + const dst = this.object.geometry.colors; - dst.push( src[ a + 0 ], src[ a + 1 ] ); - dst.push( src[ b + 0 ], src[ b + 1 ] ); - dst.push( src[ c + 0 ], src[ c + 1 ] ); + if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); + if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); + if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); - }, + }, - addDefaultUV: function () { + addUV: function ( a, b, c ) { - var dst = this.object.geometry.uvs; + const src = this.uvs; + const dst = this.object.geometry.uvs; - dst.push( 0, 0 ); - dst.push( 0, 0 ); - dst.push( 0, 0 ); + dst.push( src[ a + 0 ], src[ a + 1 ] ); + dst.push( src[ b + 0 ], src[ b + 1 ] ); + dst.push( src[ c + 0 ], src[ c + 1 ] ); - }, + }, - addUVLine: function ( a ) { + addDefaultUV: function () { - var src = this.uvs; - var dst = this.object.geometry.uvs; + const dst = this.object.geometry.uvs; - dst.push( src[ a + 0 ], src[ a + 1 ] ); + dst.push( 0, 0 ); + dst.push( 0, 0 ); + dst.push( 0, 0 ); - }, + }, - addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { + addUVLine: function ( a ) { - var vLen = this.vertices.length; + const src = this.uvs; + const dst = this.object.geometry.uvs; - var ia = this.parseVertexIndex( a, vLen ); - var ib = this.parseVertexIndex( b, vLen ); - var ic = this.parseVertexIndex( c, vLen ); + dst.push( src[ a + 0 ], src[ a + 1 ] ); - this.addVertex( ia, ib, ic ); - this.addColor( ia, ib, ic ); + }, - // normals + addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { - if ( na !== undefined && na !== '' ) { + const vLen = this.vertices.length; - var nLen = this.normals.length; + let ia = this.parseVertexIndex( a, vLen ); + let ib = this.parseVertexIndex( b, vLen ); + let ic = this.parseVertexIndex( c, vLen ); - ia = this.parseNormalIndex( na, nLen ); - ib = this.parseNormalIndex( nb, nLen ); - ic = this.parseNormalIndex( nc, nLen ); + this.addVertex( ia, ib, ic ); + this.addColor( ia, ib, ic ); - this.addNormal( ia, ib, ic ); + // normals - } else { + if ( na !== undefined && na !== '' ) { - this.addFaceNormal( ia, ib, ic ); + const nLen = this.normals.length; - } + ia = this.parseNormalIndex( na, nLen ); + ib = this.parseNormalIndex( nb, nLen ); + ic = this.parseNormalIndex( nc, nLen ); - // uvs + this.addNormal( ia, ib, ic ); - if ( ua !== undefined && ua !== '' ) { + } else { - var uvLen = this.uvs.length; + this.addFaceNormal( ia, ib, ic ); - ia = this.parseUVIndex( ua, uvLen ); - ib = this.parseUVIndex( ub, uvLen ); - ic = this.parseUVIndex( uc, uvLen ); + } - this.addUV( ia, ib, ic ); + // uvs - this.object.geometry.hasUVIndices = true; + if ( ua !== undefined && ua !== '' ) { - } else { + const uvLen = this.uvs.length; - // add placeholder values (for inconsistent face definitions) + ia = this.parseUVIndex( ua, uvLen ); + ib = this.parseUVIndex( ub, uvLen ); + ic = this.parseUVIndex( uc, uvLen ); - this.addDefaultUV(); + this.addUV( ia, ib, ic ); - } + this.object.geometry.hasUVIndices = true; - }, + } else { - addPointGeometry: function ( vertices ) { + // add placeholder values (for inconsistent face definitions) - this.object.geometry.type = 'Points'; + this.addDefaultUV(); - var vLen = this.vertices.length; + } - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { + }, - var index = this.parseVertexIndex( vertices[ vi ], vLen ); + addPointGeometry: function ( vertices ) { - this.addVertexPoint( index ); - this.addColor( index ); + this.object.geometry.type = 'Points'; - } + const vLen = this.vertices.length; - }, + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - addLineGeometry: function ( vertices, uvs ) { + const index = this.parseVertexIndex( vertices[ vi ], vLen ); - this.object.geometry.type = 'Line'; + this.addVertexPoint( index ); + this.addColor( index ); - var vLen = this.vertices.length; - var uvLen = this.uvs.length; + } - for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { + }, - this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); + addLineGeometry: function ( vertices, uvs ) { - } + this.object.geometry.type = 'Line'; - for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { + const vLen = this.vertices.length; + const uvLen = this.uvs.length; - this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); + for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) { - } + this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); } - }; + for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { - state.startObject( '', false ); + this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); - return state; + } - } + } - // + }; - function OBJLoader( manager ) { + state.startObject( '', false ); - Loader.call( this, manager ); + return state; - this.materials = null; +} - } +// - OBJLoader.prototype = Object.assign( Object.create( Loader.prototype ), { +class OBJLoader extends Loader { - constructor: OBJLoader, + constructor( manager ) { - load: function ( url, onLoad, onProgress, onError ) { + super( manager ); - var scope = this; + this.materials = null; - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { + } - try { + load( url, onLoad, onProgress, onError ) { - onLoad( scope.parse( text ) ); + const scope = this; - } catch ( e ) { + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { - if ( onError ) { + try { - onError( e ); + onLoad( scope.parse( text ) ); - } else { + } catch ( e ) { - console.error( e ); + if ( onError ) { - } + onError( e ); - scope.manager.itemError( url ); + } else { + + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); - }, + } - setMaterials: function ( materials ) { + }, onProgress, onError ); - this.materials = materials; + } - return this; + setMaterials( materials ) { - }, + this.materials = materials; - parse: function ( text ) { + return this; - var state = new ParserState(); + } - if ( text.indexOf( '\r\n' ) !== - 1 ) { + parse( text ) { - // This is faster than String.split with regex that splits on both - text = text.replace( /\r\n/g, '\n' ); + const state = new ParserState(); - } + if ( text.indexOf( '\r\n' ) !== - 1 ) { - if ( text.indexOf( '\\\n' ) !== - 1 ) { + // This is faster than String.split with regex that splits on both + text = text.replace( /\r\n/g, '\n' ); - // join lines separated by a line continuation character (\) - text = text.replace( /\\\n/g, '' ); + } - } + if ( text.indexOf( '\\\n' ) !== - 1 ) { - var lines = text.split( '\n' ); - var line = '', lineFirstChar = ''; - var lineLength = 0; - var result = []; + // join lines separated by a line continuation character (\) + text = text.replace( /\\\n/g, '' ); - // Faster to just trim left side of the line. Use if available. - var trimLeft = ( typeof ''.trimLeft === 'function' ); + } - for ( var i = 0, l = lines.length; i < l; i ++ ) { + const lines = text.split( '\n' ); + let line = '', lineFirstChar = ''; + let lineLength = 0; + let result = []; - line = lines[ i ]; + // Faster to just trim left side of the line. Use if available. + const trimLeft = ( typeof ''.trimLeft === 'function' ); - line = trimLeft ? line.trimLeft() : line.trim(); + for ( let i = 0, l = lines.length; i < l; i ++ ) { - lineLength = line.length; + line = lines[ i ]; - if ( lineLength === 0 ) continue; + line = trimLeft ? line.trimLeft() : line.trim(); - lineFirstChar = line.charAt( 0 ); + lineLength = line.length; - // @todo invoke passed in handler if any - if ( lineFirstChar === '#' ) continue; + if ( lineLength === 0 ) continue; - if ( lineFirstChar === 'v' ) { + lineFirstChar = line.charAt( 0 ); - var data = line.split( /\s+/ ); + // @todo invoke passed in handler if any + if ( lineFirstChar === '#' ) continue; - switch ( data[ 0 ] ) { + if ( lineFirstChar === 'v' ) { - case 'v': - state.vertices.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - if ( data.length >= 7 ) { + const data = line.split( /\s+/ ); - state.colors.push( - parseFloat( data[ 4 ] ), - parseFloat( data[ 5 ] ), - parseFloat( data[ 6 ] ) + switch ( data[ 0 ] ) { - ); + case 'v': + state.vertices.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + if ( data.length >= 7 ) { - } else { + state.colors.push( + parseFloat( data[ 4 ] ), + parseFloat( data[ 5 ] ), + parseFloat( data[ 6 ] ) - // if no colors are defined, add placeholders so color and vertex indices match + ); - state.colors.push( undefined, undefined, undefined ); + } else { - } + // if no colors are defined, add placeholders so color and vertex indices match - break; - case 'vn': - state.normals.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ), - parseFloat( data[ 3 ] ) - ); - break; - case 'vt': - state.uvs.push( - parseFloat( data[ 1 ] ), - parseFloat( data[ 2 ] ) - ); - break; + state.colors.push( undefined, undefined, undefined ); - } + } + + break; + case 'vn': + state.normals.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ), + parseFloat( data[ 3 ] ) + ); + break; + case 'vt': + state.uvs.push( + parseFloat( data[ 1 ] ), + parseFloat( data[ 2 ] ) + ); + break; - } else if ( lineFirstChar === 'f' ) { + } - var lineData = line.substr( 1 ).trim(); - var vertexData = lineData.split( /\s+/ ); - var faceVertices = []; + } else if ( lineFirstChar === 'f' ) { - // Parse the face vertex data into an easy to work with format + const lineData = line.substr( 1 ).trim(); + const vertexData = lineData.split( /\s+/ ); + const faceVertices = []; - for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { + // Parse the face vertex data into an easy to work with format - var vertex = vertexData[ j ]; + for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) { - if ( vertex.length > 0 ) { + const vertex = vertexData[ j ]; - var vertexParts = vertex.split( '/' ); - faceVertices.push( vertexParts ); + if ( vertex.length > 0 ) { - } + const vertexParts = vertex.split( '/' ); + faceVertices.push( vertexParts ); } - // Draw an edge between the first vertex and all subsequent vertices to form an n-gon + } - var v1 = faceVertices[ 0 ]; + // Draw an edge between the first vertex and all subsequent vertices to form an n-gon - for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { + const v1 = faceVertices[ 0 ]; - var v2 = faceVertices[ j ]; - var v3 = faceVertices[ j + 1 ]; + for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { - state.addFace( - v1[ 0 ], v2[ 0 ], v3[ 0 ], - v1[ 1 ], v2[ 1 ], v3[ 1 ], - v1[ 2 ], v2[ 2 ], v3[ 2 ] - ); + const v2 = faceVertices[ j ]; + const v3 = faceVertices[ j + 1 ]; - } + state.addFace( + v1[ 0 ], v2[ 0 ], v3[ 0 ], + v1[ 1 ], v2[ 1 ], v3[ 1 ], + v1[ 2 ], v2[ 2 ], v3[ 2 ] + ); - } else if ( lineFirstChar === 'l' ) { + } - var lineParts = line.substring( 1 ).trim().split( ' ' ); - var lineVertices = [], lineUVs = []; + } else if ( lineFirstChar === 'l' ) { - if ( line.indexOf( '/' ) === - 1 ) { + const lineParts = line.substring( 1 ).trim().split( ' ' ); + let lineVertices = []; + const lineUVs = []; - lineVertices = lineParts; + if ( line.indexOf( '/' ) === - 1 ) { - } else { + lineVertices = lineParts; - for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { + } else { - var parts = lineParts[ li ].split( '/' ); + for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) { - if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] ); - if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] ); + const parts = lineParts[ li ].split( '/' ); - } + if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] ); + if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] ); } - state.addLineGeometry( lineVertices, lineUVs ); + } - } else if ( lineFirstChar === 'p' ) { + state.addLineGeometry( lineVertices, lineUVs ); - var lineData = line.substr( 1 ).trim(); - var pointData = lineData.split( ' ' ); + } else if ( lineFirstChar === 'p' ) { - state.addPointGeometry( pointData ); + const lineData = line.substr( 1 ).trim(); + const pointData = lineData.split( ' ' ); - } else if ( ( result = object_pattern.exec( line ) ) !== null ) { + state.addPointGeometry( pointData ); - // o object_name - // or - // g group_name + } else if ( ( result = _object_pattern.exec( line ) ) !== null ) { - // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 - // var name = result[ 0 ].substr( 1 ).trim(); - var name = ( ' ' + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); + // o object_name + // or + // g group_name - state.startObject( name ); + // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869 + // let name = result[ 0 ].substr( 1 ).trim(); + const name = ( ' ' + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); - } else if ( material_use_pattern.test( line ) ) { + state.startObject( name ); - // material + } else if ( _material_use_pattern.test( line ) ) { - state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); + // material - } else if ( material_library_pattern.test( line ) ) { + state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); - // mtl file + } else if ( _material_library_pattern.test( line ) ) { - state.materialLibraries.push( line.substring( 7 ).trim() ); + // mtl file - } else if ( map_use_pattern.test( line ) ) { + state.materialLibraries.push( line.substring( 7 ).trim() ); - // the line is parsed but ignored since the loader assumes textures are defined MTL files - // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) + } else if ( _map_use_pattern.test( line ) ) { - console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); + // the line is parsed but ignored since the loader assumes textures are defined MTL files + // (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method) - } else if ( lineFirstChar === 's' ) { + console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' ); - result = line.split( ' ' ); + } else if ( lineFirstChar === 's' ) { - // smooth shading + result = line.split( ' ' ); - // @todo Handle files that have varying smooth values for a set of faces inside one geometry, - // but does not define a usemtl for each face set. - // This should be detected and a dummy material created (later MultiMaterial and geometry groups). - // This requires some care to not create extra material on each smooth value for "normal" obj files. - // where explicit usemtl defines geometry groups. - // Example asset: examples/models/obj/cerberus/Cerberus.obj + // smooth shading - /* + // @todo Handle files that have varying smooth values for a set of faces inside one geometry, + // but does not define a usemtl for each face set. + // This should be detected and a dummy material created (later MultiMaterial and geometry groups). + // This requires some care to not create extra material on each smooth value for "normal" obj files. + // where explicit usemtl defines geometry groups. + // Example asset: examples/models/obj/cerberus/Cerberus.obj + + /* * http://paulbourke.net/dataformats/obj/ * or * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf @@ -696,223 +693,219 @@ var OBJLoader = ( function () { * surfaces, smoothing groups are either turned on or off; there is no difference between values greater * than 0." */ - if ( result.length > 1 ) { + if ( result.length > 1 ) { - var value = result[ 1 ].trim().toLowerCase(); - state.object.smooth = ( value !== '0' && value !== 'off' ); + const value = result[ 1 ].trim().toLowerCase(); + state.object.smooth = ( value !== '0' && value !== 'off' ); - } else { + } else { - // ZBrush can produce "s" lines #11707 - state.object.smooth = true; + // ZBrush can produce "s" lines #11707 + state.object.smooth = true; - } + } - var material = state.object.currentMaterial(); - if ( material ) material.smooth = state.object.smooth; + const material = state.object.currentMaterial(); + if ( material ) material.smooth = state.object.smooth; - } else { - - // Handle null terminated files without exception - if ( line === '\0' ) continue; + } else { - console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); + // Handle null terminated files without exception + if ( line === '\0' ) continue; - } + console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); } - state.finalize(); + } - var container = new Group(); - container.materialLibraries = [].concat( state.materialLibraries ); + state.finalize(); - var hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); + const container = new Group(); + container.materialLibraries = [].concat( state.materialLibraries ); - if ( hasPrimitives === true ) { + const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 ); - for ( var i = 0, l = state.objects.length; i < l; i ++ ) { + if ( hasPrimitives === true ) { - var object = state.objects[ i ]; - var geometry = object.geometry; - var materials = object.materials; - var isLine = ( geometry.type === 'Line' ); - var isPoints = ( geometry.type === 'Points' ); - var hasVertexColors = false; + for ( let i = 0, l = state.objects.length; i < l; i ++ ) { - // Skip o/g line declarations that did not follow with any faces - if ( geometry.vertices.length === 0 ) continue; + const object = state.objects[ i ]; + const geometry = object.geometry; + const materials = object.materials; + const isLine = ( geometry.type === 'Line' ); + const isPoints = ( geometry.type === 'Points' ); + let hasVertexColors = false; - var buffergeometry = new BufferGeometry(); + // Skip o/g line declarations that did not follow with any faces + if ( geometry.vertices.length === 0 ) continue; - buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) ); + const buffergeometry = new BufferGeometry(); - if ( geometry.normals.length > 0 ) { + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) ); - buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) ); + if ( geometry.normals.length > 0 ) { - } + buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) ); - if ( geometry.colors.length > 0 ) { + } - hasVertexColors = true; - buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) ); + if ( geometry.colors.length > 0 ) { - } + hasVertexColors = true; + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) ); - if ( geometry.hasUVIndices === true ) { + } - buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) ); + if ( geometry.hasUVIndices === true ) { - } + buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) ); - // Create materials + } - var createdMaterials = []; + // Create materials - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + const createdMaterials = []; - var sourceMaterial = materials[ mi ]; - var materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors; - var material = state.materials[ materialHash ]; + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - if ( this.materials !== null ) { + const sourceMaterial = materials[ mi ]; + const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors; + let material = state.materials[ materialHash ]; - material = this.materials.create( sourceMaterial.name ); + if ( this.materials !== null ) { - // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. - if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) { + material = this.materials.create( sourceMaterial.name ); - var materialLine = new LineBasicMaterial(); - Material.prototype.copy.call( materialLine, material ); - materialLine.color.copy( material.color ); - material = materialLine; + // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material. + if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) { - } else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) { + const materialLine = new LineBasicMaterial(); + Material.prototype.copy.call( materialLine, material ); + materialLine.color.copy( material.color ); + material = materialLine; - var materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } ); - Material.prototype.copy.call( materialPoints, material ); - materialPoints.color.copy( material.color ); - materialPoints.map = material.map; - material = materialPoints; + } else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) { - } + const materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } ); + Material.prototype.copy.call( materialPoints, material ); + materialPoints.color.copy( material.color ); + materialPoints.map = material.map; + material = materialPoints; } - if ( material === undefined ) { - - if ( isLine ) { - - material = new LineBasicMaterial(); + } - } else if ( isPoints ) { + if ( material === undefined ) { - material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); + if ( isLine ) { - } else { + material = new LineBasicMaterial(); - material = new MeshPhongMaterial(); + } else if ( isPoints ) { - } + material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - material.name = sourceMaterial.name; - material.flatShading = sourceMaterial.smooth ? false : true; - material.vertexColors = hasVertexColors; + } else { - state.materials[ materialHash ] = material; + material = new MeshPhongMaterial(); } - createdMaterials.push( material ); + material.name = sourceMaterial.name; + material.flatShading = sourceMaterial.smooth ? false : true; + material.vertexColors = hasVertexColors; + + state.materials[ materialHash ] = material; } - // Create mesh + createdMaterials.push( material ); - var mesh; + } - if ( createdMaterials.length > 1 ) { + // Create mesh - for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { + let mesh; - var sourceMaterial = materials[ mi ]; - buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); + if ( createdMaterials.length > 1 ) { - } + for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { - if ( isLine ) { + const sourceMaterial = materials[ mi ]; + buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); - mesh = new LineSegments( buffergeometry, createdMaterials ); + } - } else if ( isPoints ) { + if ( isLine ) { - mesh = new Points( buffergeometry, createdMaterials ); + mesh = new LineSegments( buffergeometry, createdMaterials ); - } else { + } else if ( isPoints ) { - mesh = new Mesh( buffergeometry, createdMaterials ); - - } + mesh = new Points( buffergeometry, createdMaterials ); } else { - if ( isLine ) { + mesh = new Mesh( buffergeometry, createdMaterials ); - mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] ); + } - } else if ( isPoints ) { + } else { - mesh = new Points( buffergeometry, createdMaterials[ 0 ] ); + if ( isLine ) { - } else { + mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] ); - mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] ); + } else if ( isPoints ) { - } + mesh = new Points( buffergeometry, createdMaterials[ 0 ] ); - } + } else { - mesh.name = object.name; + mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] ); - container.add( mesh ); + } } - } else { + mesh.name = object.name; - // if there is only the default parser state object with no geometry data, interpret data as point cloud + container.add( mesh ); - if ( state.vertices.length > 0 ) { + } - var material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); + } else { - var buffergeometry = new BufferGeometry(); + // if there is only the default parser state object with no geometry data, interpret data as point cloud - buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) ); + if ( state.vertices.length > 0 ) { - if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { + const material = new PointsMaterial( { size: 1, sizeAttenuation: false } ); - buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) ); - material.vertexColors = true; + const buffergeometry = new BufferGeometry(); - } + buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) ); - var points = new Points( buffergeometry, material ); - container.add( points ); + if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) { + + buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) ); + material.vertexColors = true; } - } + const points = new Points( buffergeometry, material ); + container.add( points ); - return container; + } } - } ); + return container; - return OBJLoader; + } -} )(); +} export { OBJLoader }; diff --git a/examples/jsm/loaders/PCDLoader.js b/examples/jsm/loaders/PCDLoader.js index 1fbb1265c2cbb1..dd48c091ddb549 100644 --- a/examples/jsm/loaders/PCDLoader.js +++ b/examples/jsm/loaders/PCDLoader.js @@ -8,24 +8,21 @@ import { PointsMaterial } from '../../../build/three.module.js'; -var PCDLoader = function ( manager ) { +class PCDLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.littleEndian = true; + super( manager ); -}; + this.littleEndian = true; + } -PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: PCDLoader, - - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -54,21 +51,21 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data, url ) { + parse( data, url ) { // from https://gitlab.com/taketwo/three-pcd-loader/blob/master/decompress-lzf.js function decompressLZF( inData, outLength ) { - var inLength = inData.length; - var outData = new Uint8Array( outLength ); - var inPtr = 0; - var outPtr = 0; - var ctrl; - var len; - var ref; + const inLength = inData.length; + const outData = new Uint8Array( outLength ); + let inPtr = 0; + let outPtr = 0; + let ctrl; + let len; + let ref; do { ctrl = inData[ inPtr ++ ]; @@ -115,9 +112,9 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseHeader( data ) { - var PCDheader = {}; - var result1 = data.search( /[\r\n]DATA\s(\S*)\s/i ); - var result2 = /[\r\n]DATA\s(\S*)\s/i.exec( data.substr( result1 - 1 ) ); + const PCDheader = {}; + const result1 = data.search( /[\r\n]DATA\s(\S*)\s/i ); + const result2 = /[\r\n]DATA\s(\S*)\s/i.exec( data.substr( result1 - 1 ) ); PCDheader.data = result2[ 1 ]; PCDheader.headerLen = result2[ 0 ].length + result1; @@ -187,7 +184,7 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { PCDheader.count = []; - for ( var i = 0, l = PCDheader.fields.length; i < l; i ++ ) { + for ( let i = 0, l = PCDheader.fields.length; i < l; i ++ ) { PCDheader.count.push( 1 ); @@ -197,9 +194,9 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { PCDheader.offset = {}; - var sizeSum = 0; + let sizeSum = 0; - for ( var i = 0, l = PCDheader.fields.length; i < l; i ++ ) { + for ( let i = 0, l = PCDheader.fields.length; i < l; i ++ ) { if ( PCDheader.data === 'ascii' ) { @@ -222,31 +219,31 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var textData = LoaderUtils.decodeText( new Uint8Array( data ) ); + const textData = LoaderUtils.decodeText( new Uint8Array( data ) ); // parse header (always ascii format) - var PCDheader = parseHeader( textData ); + const PCDheader = parseHeader( textData ); // parse data - var position = []; - var normal = []; - var color = []; + const position = []; + const normal = []; + const color = []; // ascii if ( PCDheader.data === 'ascii' ) { - var offset = PCDheader.offset; - var pcdData = textData.substr( PCDheader.headerLen ); - var lines = pcdData.split( '\n' ); + const offset = PCDheader.offset; + const pcdData = textData.substr( PCDheader.headerLen ); + const lines = pcdData.split( '\n' ); - for ( var i = 0, l = lines.length; i < l; i ++ ) { + for ( let i = 0, l = lines.length; i < l; i ++ ) { if ( lines[ i ] === '' ) continue; - var line = lines[ i ].split( ' ' ); + const line = lines[ i ].split( ' ' ); if ( offset.x !== undefined ) { @@ -258,10 +255,10 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( offset.rgb !== undefined ) { - var rgb = parseFloat( line[ offset.rgb ] ); - var r = ( rgb >> 16 ) & 0x0000ff; - var g = ( rgb >> 8 ) & 0x0000ff; - var b = ( rgb >> 0 ) & 0x0000ff; + const rgb = parseFloat( line[ offset.rgb ] ); + const r = ( rgb >> 16 ) & 0x0000ff; + const g = ( rgb >> 8 ) & 0x0000ff; + const b = ( rgb >> 0 ) & 0x0000ff; color.push( r / 255, g / 255, b / 255 ); } @@ -286,15 +283,15 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( PCDheader.data === 'binary_compressed' ) { - var sizes = new Uint32Array( data.slice( PCDheader.headerLen, PCDheader.headerLen + 8 ) ); - var compressedSize = sizes[ 0 ]; - var decompressedSize = sizes[ 1 ]; - var decompressed = decompressLZF( new Uint8Array( data, PCDheader.headerLen + 8, compressedSize ), decompressedSize ); - var dataview = new DataView( decompressed.buffer ); + const sizes = new Uint32Array( data.slice( PCDheader.headerLen, PCDheader.headerLen + 8 ) ); + const compressedSize = sizes[ 0 ]; + const decompressedSize = sizes[ 1 ]; + const decompressed = decompressLZF( new Uint8Array( data, PCDheader.headerLen + 8, compressedSize ), decompressedSize ); + const dataview = new DataView( decompressed.buffer ); - var offset = PCDheader.offset; + const offset = PCDheader.offset; - for ( var i = 0; i < PCDheader.points; i ++ ) { + for ( let i = 0; i < PCDheader.points; i ++ ) { if ( offset.x !== undefined ) { @@ -328,10 +325,10 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( PCDheader.data === 'binary' ) { - var dataview = new DataView( data, PCDheader.headerLen ); - var offset = PCDheader.offset; + const dataview = new DataView( data, PCDheader.headerLen ); + const offset = PCDheader.offset; - for ( var i = 0, row = 0; i < PCDheader.points; i ++, row += PCDheader.rowSize ) { + for ( let i = 0, row = 0; i < PCDheader.points; i ++, row += PCDheader.rowSize ) { if ( offset.x !== undefined ) { @@ -363,7 +360,7 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // build geometry - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); if ( position.length > 0 ) geometry.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); if ( normal.length > 0 ) geometry.setAttribute( 'normal', new Float32BufferAttribute( normal, 3 ) ); @@ -373,7 +370,7 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // build material - var material = new PointsMaterial( { size: 0.005 } ); + const material = new PointsMaterial( { size: 0.005 } ); if ( color.length > 0 ) { @@ -387,8 +384,8 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // build point cloud - var mesh = new Points( geometry, material ); - var name = url.split( '' ).reverse().join( '' ); + const mesh = new Points( geometry, material ); + let name = url.split( '' ).reverse().join( '' ); name = /([^\/]*)/.exec( name ); name = name[ 1 ].split( '' ).reverse().join( '' ); mesh.name = name; @@ -397,6 +394,6 @@ PCDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { PCDLoader }; diff --git a/examples/jsm/loaders/PDBLoader.js b/examples/jsm/loaders/PDBLoader.js index e92bd1e1247ebd..2477969e61f034 100644 --- a/examples/jsm/loaders/PDBLoader.js +++ b/examples/jsm/loaders/PDBLoader.js @@ -5,21 +5,19 @@ import { Loader } from '../../../build/three.module.js'; -var PDBLoader = function ( manager ) { +class PDBLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: PDBLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setRequestHeader( scope.requestHeader ); loader.setWithCredentials( scope.withCredentials ); @@ -47,11 +45,11 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } // Based on CanvasMol PDB parser - parse: function ( text ) { + parse( text ) { function trim( text ) { @@ -71,13 +69,13 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - function parseBond( start, length ) { + function parseBond( start, length, satom, i ) { - var eatom = parseInt( lines[ i ].substr( start, length ) ); + const eatom = parseInt( lines[ i ].substr( start, length ) ); if ( eatom ) { - var h = hash( satom, eatom ); + const h = hash( satom, eatom ); if ( _bhash[ h ] === undefined ) { @@ -99,7 +97,7 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function buildGeometry() { - var build = { + const build = { geometryAtoms: new BufferGeometry(), geometryBonds: new BufferGeometry(), json: { @@ -107,31 +105,28 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } }; - var geometryAtoms = build.geometryAtoms; - var geometryBonds = build.geometryBonds; + const geometryAtoms = build.geometryAtoms; + const geometryBonds = build.geometryBonds; - var i, l; - var x, y, z; - - var verticesAtoms = []; - var colorsAtoms = []; - var verticesBonds = []; + const verticesAtoms = []; + const colorsAtoms = []; + const verticesBonds = []; // atoms - for ( i = 0, l = atoms.length; i < l; i ++ ) { + for ( let i = 0, l = atoms.length; i < l; i ++ ) { - var atom = atoms[ i ]; + const atom = atoms[ i ]; - x = atom[ 0 ]; - y = atom[ 1 ]; - z = atom[ 2 ]; + const x = atom[ 0 ]; + const y = atom[ 1 ]; + const z = atom[ 2 ]; verticesAtoms.push( x, y, z ); - var r = atom[ 3 ][ 0 ] / 255; - var g = atom[ 3 ][ 1 ] / 255; - var b = atom[ 3 ][ 2 ] / 255; + const r = atom[ 3 ][ 0 ] / 255; + const g = atom[ 3 ][ 1 ] / 255; + const b = atom[ 3 ][ 2 ] / 255; colorsAtoms.push( r, g, b ); @@ -139,19 +134,19 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // bonds - for ( i = 0, l = _bonds.length; i < l; i ++ ) { + for ( let i = 0, l = _bonds.length; i < l; i ++ ) { - var bond = _bonds[ i ]; + const bond = _bonds[ i ]; - var start = bond[ 0 ]; - var end = bond[ 1 ]; + const start = bond[ 0 ]; + const end = bond[ 1 ]; - var startAtom = _atomMap[ start ]; - var endAtom = _atomMap[ end ]; + const startAtom = _atomMap[ start ]; + const endAtom = _atomMap[ end ]; - x = startAtom[ 0 ]; - y = startAtom[ 1 ]; - z = startAtom[ 2 ]; + let x = startAtom[ 0 ]; + let y = startAtom[ 1 ]; + let z = startAtom[ 2 ]; verticesBonds.push( x, y, z ); @@ -174,30 +169,28 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var CPK = { h: [ 255, 255, 255 ], he: [ 217, 255, 255 ], li: [ 204, 128, 255 ], be: [ 194, 255, 0 ], b: [ 255, 181, 181 ], c: [ 144, 144, 144 ], n: [ 48, 80, 248 ], o: [ 255, 13, 13 ], f: [ 144, 224, 80 ], ne: [ 179, 227, 245 ], na: [ 171, 92, 242 ], mg: [ 138, 255, 0 ], al: [ 191, 166, 166 ], si: [ 240, 200, 160 ], p: [ 255, 128, 0 ], s: [ 255, 255, 48 ], cl: [ 31, 240, 31 ], ar: [ 128, 209, 227 ], k: [ 143, 64, 212 ], ca: [ 61, 255, 0 ], sc: [ 230, 230, 230 ], ti: [ 191, 194, 199 ], v: [ 166, 166, 171 ], cr: [ 138, 153, 199 ], mn: [ 156, 122, 199 ], fe: [ 224, 102, 51 ], co: [ 240, 144, 160 ], ni: [ 80, 208, 80 ], cu: [ 200, 128, 51 ], zn: [ 125, 128, 176 ], ga: [ 194, 143, 143 ], ge: [ 102, 143, 143 ], as: [ 189, 128, 227 ], se: [ 255, 161, 0 ], br: [ 166, 41, 41 ], kr: [ 92, 184, 209 ], rb: [ 112, 46, 176 ], sr: [ 0, 255, 0 ], y: [ 148, 255, 255 ], zr: [ 148, 224, 224 ], nb: [ 115, 194, 201 ], mo: [ 84, 181, 181 ], tc: [ 59, 158, 158 ], ru: [ 36, 143, 143 ], rh: [ 10, 125, 140 ], pd: [ 0, 105, 133 ], ag: [ 192, 192, 192 ], cd: [ 255, 217, 143 ], in: [ 166, 117, 115 ], sn: [ 102, 128, 128 ], sb: [ 158, 99, 181 ], te: [ 212, 122, 0 ], i: [ 148, 0, 148 ], xe: [ 66, 158, 176 ], cs: [ 87, 23, 143 ], ba: [ 0, 201, 0 ], la: [ 112, 212, 255 ], ce: [ 255, 255, 199 ], pr: [ 217, 255, 199 ], nd: [ 199, 255, 199 ], pm: [ 163, 255, 199 ], sm: [ 143, 255, 199 ], eu: [ 97, 255, 199 ], gd: [ 69, 255, 199 ], tb: [ 48, 255, 199 ], dy: [ 31, 255, 199 ], ho: [ 0, 255, 156 ], er: [ 0, 230, 117 ], tm: [ 0, 212, 82 ], yb: [ 0, 191, 56 ], lu: [ 0, 171, 36 ], hf: [ 77, 194, 255 ], ta: [ 77, 166, 255 ], w: [ 33, 148, 214 ], re: [ 38, 125, 171 ], os: [ 38, 102, 150 ], ir: [ 23, 84, 135 ], pt: [ 208, 208, 224 ], au: [ 255, 209, 35 ], hg: [ 184, 184, 208 ], tl: [ 166, 84, 77 ], pb: [ 87, 89, 97 ], bi: [ 158, 79, 181 ], po: [ 171, 92, 0 ], at: [ 117, 79, 69 ], rn: [ 66, 130, 150 ], fr: [ 66, 0, 102 ], ra: [ 0, 125, 0 ], ac: [ 112, 171, 250 ], th: [ 0, 186, 255 ], pa: [ 0, 161, 255 ], u: [ 0, 143, 255 ], np: [ 0, 128, 255 ], pu: [ 0, 107, 255 ], am: [ 84, 92, 242 ], cm: [ 120, 92, 227 ], bk: [ 138, 79, 227 ], cf: [ 161, 54, 212 ], es: [ 179, 31, 212 ], fm: [ 179, 31, 186 ], md: [ 179, 13, 166 ], no: [ 189, 13, 135 ], lr: [ 199, 0, 102 ], rf: [ 204, 0, 89 ], db: [ 209, 0, 79 ], sg: [ 217, 0, 69 ], bh: [ 224, 0, 56 ], hs: [ 230, 0, 46 ], mt: [ 235, 0, 38 ], ds: [ 235, 0, 38 ], rg: [ 235, 0, 38 ], cn: [ 235, 0, 38 ], uut: [ 235, 0, 38 ], uuq: [ 235, 0, 38 ], uup: [ 235, 0, 38 ], uuh: [ 235, 0, 38 ], uus: [ 235, 0, 38 ], uuo: [ 235, 0, 38 ] }; - - var atoms = []; + const CPK = { h: [ 255, 255, 255 ], he: [ 217, 255, 255 ], li: [ 204, 128, 255 ], be: [ 194, 255, 0 ], b: [ 255, 181, 181 ], c: [ 144, 144, 144 ], n: [ 48, 80, 248 ], o: [ 255, 13, 13 ], f: [ 144, 224, 80 ], ne: [ 179, 227, 245 ], na: [ 171, 92, 242 ], mg: [ 138, 255, 0 ], al: [ 191, 166, 166 ], si: [ 240, 200, 160 ], p: [ 255, 128, 0 ], s: [ 255, 255, 48 ], cl: [ 31, 240, 31 ], ar: [ 128, 209, 227 ], k: [ 143, 64, 212 ], ca: [ 61, 255, 0 ], sc: [ 230, 230, 230 ], ti: [ 191, 194, 199 ], v: [ 166, 166, 171 ], cr: [ 138, 153, 199 ], mn: [ 156, 122, 199 ], fe: [ 224, 102, 51 ], co: [ 240, 144, 160 ], ni: [ 80, 208, 80 ], cu: [ 200, 128, 51 ], zn: [ 125, 128, 176 ], ga: [ 194, 143, 143 ], ge: [ 102, 143, 143 ], as: [ 189, 128, 227 ], se: [ 255, 161, 0 ], br: [ 166, 41, 41 ], kr: [ 92, 184, 209 ], rb: [ 112, 46, 176 ], sr: [ 0, 255, 0 ], y: [ 148, 255, 255 ], zr: [ 148, 224, 224 ], nb: [ 115, 194, 201 ], mo: [ 84, 181, 181 ], tc: [ 59, 158, 158 ], ru: [ 36, 143, 143 ], rh: [ 10, 125, 140 ], pd: [ 0, 105, 133 ], ag: [ 192, 192, 192 ], cd: [ 255, 217, 143 ], in: [ 166, 117, 115 ], sn: [ 102, 128, 128 ], sb: [ 158, 99, 181 ], te: [ 212, 122, 0 ], i: [ 148, 0, 148 ], xe: [ 66, 158, 176 ], cs: [ 87, 23, 143 ], ba: [ 0, 201, 0 ], la: [ 112, 212, 255 ], ce: [ 255, 255, 199 ], pr: [ 217, 255, 199 ], nd: [ 199, 255, 199 ], pm: [ 163, 255, 199 ], sm: [ 143, 255, 199 ], eu: [ 97, 255, 199 ], gd: [ 69, 255, 199 ], tb: [ 48, 255, 199 ], dy: [ 31, 255, 199 ], ho: [ 0, 255, 156 ], er: [ 0, 230, 117 ], tm: [ 0, 212, 82 ], yb: [ 0, 191, 56 ], lu: [ 0, 171, 36 ], hf: [ 77, 194, 255 ], ta: [ 77, 166, 255 ], w: [ 33, 148, 214 ], re: [ 38, 125, 171 ], os: [ 38, 102, 150 ], ir: [ 23, 84, 135 ], pt: [ 208, 208, 224 ], au: [ 255, 209, 35 ], hg: [ 184, 184, 208 ], tl: [ 166, 84, 77 ], pb: [ 87, 89, 97 ], bi: [ 158, 79, 181 ], po: [ 171, 92, 0 ], at: [ 117, 79, 69 ], rn: [ 66, 130, 150 ], fr: [ 66, 0, 102 ], ra: [ 0, 125, 0 ], ac: [ 112, 171, 250 ], th: [ 0, 186, 255 ], pa: [ 0, 161, 255 ], u: [ 0, 143, 255 ], np: [ 0, 128, 255 ], pu: [ 0, 107, 255 ], am: [ 84, 92, 242 ], cm: [ 120, 92, 227 ], bk: [ 138, 79, 227 ], cf: [ 161, 54, 212 ], es: [ 179, 31, 212 ], fm: [ 179, 31, 186 ], md: [ 179, 13, 166 ], no: [ 189, 13, 135 ], lr: [ 199, 0, 102 ], rf: [ 204, 0, 89 ], db: [ 209, 0, 79 ], sg: [ 217, 0, 69 ], bh: [ 224, 0, 56 ], hs: [ 230, 0, 46 ], mt: [ 235, 0, 38 ], ds: [ 235, 0, 38 ], rg: [ 235, 0, 38 ], cn: [ 235, 0, 38 ], uut: [ 235, 0, 38 ], uuq: [ 235, 0, 38 ], uup: [ 235, 0, 38 ], uuh: [ 235, 0, 38 ], uus: [ 235, 0, 38 ], uuo: [ 235, 0, 38 ] }; - var _bonds = []; - var _bhash = {}; - var _atomMap = {}; + const atoms = []; - var x, y, z, index, e; + const _bonds = []; + const _bhash = {}; + const _atomMap = {}; // parse - var lines = text.split( '\n' ); + const lines = text.split( '\n' ); - for ( var i = 0, l = lines.length; i < l; i ++ ) { + for ( let i = 0, l = lines.length; i < l; i ++ ) { if ( lines[ i ].substr( 0, 4 ) === 'ATOM' || lines[ i ].substr( 0, 6 ) === 'HETATM' ) { - x = parseFloat( lines[ i ].substr( 30, 7 ) ); - y = parseFloat( lines[ i ].substr( 38, 7 ) ); - z = parseFloat( lines[ i ].substr( 46, 7 ) ); - index = parseInt( lines[ i ].substr( 6, 5 ) ) - 1; + const x = parseFloat( lines[ i ].substr( 30, 7 ) ); + const y = parseFloat( lines[ i ].substr( 38, 7 ) ); + const z = parseFloat( lines[ i ].substr( 46, 7 ) ); + const index = parseInt( lines[ i ].substr( 6, 5 ) ) - 1; - e = trim( lines[ i ].substr( 76, 2 ) ).toLowerCase(); + let e = trim( lines[ i ].substr( 76, 2 ) ).toLowerCase(); if ( e === '' ) { @@ -205,19 +198,19 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var atomData = [ x, y, z, CPK[ e ], capitalize( e ) ]; + const atomData = [ x, y, z, CPK[ e ], capitalize( e ) ]; atoms.push( atomData ); _atomMap[ index ] = atomData; } else if ( lines[ i ].substr( 0, 6 ) === 'CONECT' ) { - var satom = parseInt( lines[ i ].substr( 6, 5 ) ); + const satom = parseInt( lines[ i ].substr( 6, 5 ) ); - parseBond( 11, 5 ); - parseBond( 16, 5 ); - parseBond( 21, 5 ); - parseBond( 26, 5 ); + parseBond( 11, 5, satom, i ); + parseBond( 16, 5, satom, i ); + parseBond( 21, 5, satom, i ); + parseBond( 26, 5, satom, i ); } @@ -229,6 +222,6 @@ PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { PDBLoader }; diff --git a/examples/jsm/loaders/PLYLoader.js b/examples/jsm/loaders/PLYLoader.js index ea51b74e920098..1c1e0283980499 100644 --- a/examples/jsm/loaders/PLYLoader.js +++ b/examples/jsm/loaders/PLYLoader.js @@ -13,7 +13,7 @@ import { * Limitations: ASCII decoding assumes file is UTF-8. * * Usage: - * var loader = new PLYLoader(); + * const loader = new PLYLoader(); * loader.load('./models/ply/ascii/dolphins.ply', function (geometry) { * * scene.add( new THREE.Mesh( geometry ) ); @@ -33,23 +33,21 @@ import { */ -var PLYLoader = function ( manager ) { +class PLYLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.propertyNameMapping = {}; + super( manager ); -}; + this.propertyNameMapping = {}; -PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: PLYLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( this.requestHeader ); @@ -78,22 +76,22 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - setPropertyNameMapping: function ( mapping ) { + setPropertyNameMapping( mapping ) { this.propertyNameMapping = mapping; - }, + } - parse: function ( data ) { + parse( data ) { function parseHeader( data ) { - var patternHeader = /ply([\s\S]*)end_header\r?\n/; - var headerText = ''; - var headerLength = 0; - var result = patternHeader.exec( data ); + const patternHeader = /ply([\s\S]*)end_header\r?\n/; + let headerText = ''; + let headerLength = 0; + const result = patternHeader.exec( data ); if ( result !== null ) { @@ -102,20 +100,19 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var header = { + const header = { comments: [], elements: [], headerLength: headerLength, objInfo: '' }; - var lines = headerText.split( '\n' ); - var currentElement; - var lineType, lineValues; + const lines = headerText.split( '\n' ); + let currentElement; function make_ply_element_property( propertValues, propertyNameMapping ) { - var property = { type: propertValues[ 0 ] }; + const property = { type: propertValues[ 0 ] }; if ( property.type === 'list' ) { @@ -139,15 +136,15 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - for ( var i = 0; i < lines.length; i ++ ) { + for ( let i = 0; i < lines.length; i ++ ) { - var line = lines[ i ]; + let line = lines[ i ]; line = line.trim(); if ( line === '' ) continue; - lineValues = line.split( /\s+/ ); - lineType = lineValues.shift(); + const lineValues = line.split( /\s+/ ); + const lineType = lineValues.shift(); line = lineValues.join( ' ' ); switch ( lineType ) { @@ -230,18 +227,18 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseASCIIElement( properties, line ) { - var values = line.split( /\s+/ ); + const values = line.split( /\s+/ ); - var element = {}; + const element = {}; - for ( var i = 0; i < properties.length; i ++ ) { + for ( let i = 0; i < properties.length; i ++ ) { if ( properties[ i ].type === 'list' ) { - var list = []; - var n = parseASCIINumber( values.shift(), properties[ i ].countType ); + const list = []; + const n = parseASCIINumber( values.shift(), properties[ i ].countType ); - for ( var j = 0; j < n; j ++ ) { + for ( let j = 0; j < n; j ++ ) { list.push( parseASCIINumber( values.shift(), properties[ i ].itemType ) ); @@ -265,7 +262,7 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format) - var buffer = { + const buffer = { indices: [], vertices: [], normals: [], @@ -274,23 +271,23 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { colors: [] }; - var result; + let result; - var patternBody = /end_header\s([\s\S]*)$/; - var body = ''; + const patternBody = /end_header\s([\s\S]*)$/; + let body = ''; if ( ( result = patternBody.exec( data ) ) !== null ) { body = result[ 1 ]; } - var lines = body.split( '\n' ); - var currentElement = 0; - var currentElementCount = 0; + const lines = body.split( '\n' ); + let currentElement = 0; + let currentElementCount = 0; - for ( var i = 0; i < lines.length; i ++ ) { + for ( let i = 0; i < lines.length; i ++ ) { - var line = lines[ i ]; + let line = lines[ i ]; line = line.trim(); if ( line === '' ) { @@ -305,7 +302,7 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var element = parseASCIIElement( header.elements[ currentElement ].properties, line ); + const element = parseASCIIElement( header.elements[ currentElement ].properties, line ); handleElement( buffer, header.elements[ currentElement ].name, element ); @@ -319,7 +316,7 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function postProcess( buffer ) { - var geometry = new BufferGeometry(); + let geometry = new BufferGeometry(); // mandatory buffer data @@ -390,8 +387,8 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( elementName === 'face' ) { - var vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338 - var texcoord = element.texcoord; + const vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338 + const texcoord = element.texcoord; if ( vertex_indices.length === 3 ) { @@ -436,20 +433,20 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function binaryReadElement( dataview, at, properties, little_endian ) { - var element = {}; - var result, read = 0; + const element = {}; + let result, read = 0; - for ( var i = 0; i < properties.length; i ++ ) { + for ( let i = 0; i < properties.length; i ++ ) { if ( properties[ i ].type === 'list' ) { - var list = []; + const list = []; result = binaryRead( dataview, at + read, properties[ i ].countType, little_endian ); - var n = result[ 0 ]; + const n = result[ 0 ]; read += result[ 1 ]; - for ( var j = 0; j < n; j ++ ) { + for ( let j = 0; j < n; j ++ ) { result = binaryRead( dataview, at + read, properties[ i ].itemType, little_endian ); list.push( result[ 0 ] ); @@ -475,7 +472,7 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseBinary( data, header ) { - var buffer = { + const buffer = { indices: [], vertices: [], normals: [], @@ -484,17 +481,17 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { colors: [] }; - var little_endian = ( header.format === 'binary_little_endian' ); - var body = new DataView( data, header.headerLength ); - var result, loc = 0; + const little_endian = ( header.format === 'binary_little_endian' ); + const body = new DataView( data, header.headerLength ); + let result, loc = 0; - for ( var currentElement = 0; currentElement < header.elements.length; currentElement ++ ) { + for ( let currentElement = 0; currentElement < header.elements.length; currentElement ++ ) { - for ( var currentElementCount = 0; currentElementCount < header.elements[ currentElement ].count; currentElementCount ++ ) { + for ( let currentElementCount = 0; currentElementCount < header.elements[ currentElement ].count; currentElementCount ++ ) { result = binaryReadElement( body, loc, header.elements[ currentElement ].properties, little_endian ); loc += result[ 1 ]; - var element = result[ 0 ]; + const element = result[ 0 ]; handleElement( buffer, header.elements[ currentElement ].name, element ); @@ -508,13 +505,13 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // - var geometry; - var scope = this; + let geometry; + const scope = this; if ( data instanceof ArrayBuffer ) { - var text = LoaderUtils.decodeText( new Uint8Array( data ) ); - var header = parseHeader( text ); + const text = LoaderUtils.decodeText( new Uint8Array( data ) ); + const header = parseHeader( text ); geometry = header.format === 'ascii' ? parseASCII( text, header ) : parseBinary( data, header ); @@ -528,6 +525,6 @@ PLYLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { PLYLoader }; diff --git a/examples/jsm/loaders/PRWMLoader.js b/examples/jsm/loaders/PRWMLoader.js index 9b8b9560f03a23..46ed2bfee114c1 100644 --- a/examples/jsm/loaders/PRWMLoader.js +++ b/examples/jsm/loaders/PRWMLoader.js @@ -9,308 +9,291 @@ import { * See https://github.com/kchapelier/PRWM for more informations about this file format */ -var PRWMLoader = ( function () { +let bigEndianPlatform = null; - var bigEndianPlatform = null; - - /** +/** * Check if the endianness of the platform is big-endian (most significant bit first) * @returns {boolean} True if big-endian, false if little-endian */ - function isBigEndianPlatform() { +function isBigEndianPlatform() { - if ( bigEndianPlatform === null ) { + if ( bigEndianPlatform === null ) { - var buffer = new ArrayBuffer( 2 ), - uint8Array = new Uint8Array( buffer ), - uint16Array = new Uint16Array( buffer ); + const buffer = new ArrayBuffer( 2 ), + uint8Array = new Uint8Array( buffer ), + uint16Array = new Uint16Array( buffer ); - uint8Array[ 0 ] = 0xAA; // set first byte - uint8Array[ 1 ] = 0xBB; // set second byte - bigEndianPlatform = ( uint16Array[ 0 ] === 0xAABB ); + uint8Array[ 0 ] = 0xAA; // set first byte + uint8Array[ 1 ] = 0xBB; // set second byte + bigEndianPlatform = ( uint16Array[ 0 ] === 0xAABB ); - } + } - return bigEndianPlatform; + return bigEndianPlatform; - } +} - // match the values defined in the spec to the TypedArray types - var InvertedEncodingTypes = [ - null, - Float32Array, - null, - Int8Array, - Int16Array, - null, - Int32Array, - Uint8Array, - Uint16Array, - null, - Uint32Array - ]; - - // define the method to use on a DataView, corresponding the TypedArray type - var getMethods = { - Uint16Array: 'getUint16', - Uint32Array: 'getUint32', - Int16Array: 'getInt16', - Int32Array: 'getInt32', - Float32Array: 'getFloat32', - Float64Array: 'getFloat64' - }; +// match the values defined in the spec to the TypedArray types +const InvertedEncodingTypes = [ + null, + Float32Array, + null, + Int8Array, + Int16Array, + null, + Int32Array, + Uint8Array, + Uint16Array, + null, + Uint32Array +]; +// define the method to use on a DataView, corresponding the TypedArray type +const getMethods = { + Uint16Array: 'getUint16', + Uint32Array: 'getUint32', + Int16Array: 'getInt16', + Int32Array: 'getInt32', + Float32Array: 'getFloat32', + Float64Array: 'getFloat64' +}; - function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) { - var bytesPerElement = viewType.BYTES_PER_ELEMENT, - result; +function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) { - if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) { + const bytesPerElement = viewType.BYTES_PER_ELEMENT; + let result; - result = new viewType( sourceArrayBuffer, position, length ); + if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) { - } else { + result = new viewType( sourceArrayBuffer, position, length ); - var readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ), - getMethod = getMethods[ viewType.name ], - littleEndian = ! fromBigEndian, - i = 0; + } else { - result = new viewType( length ); + const readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ), + getMethod = getMethods[ viewType.name ], + littleEndian = ! fromBigEndian; - for ( ; i < length; i ++ ) { + result = new viewType( length ); - result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian ); + for ( let i = 0; i < length; i ++ ) { - } + result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian ); } - return result; - } + return result; - function decodePrwm( buffer ) { +} - var array = new Uint8Array( buffer ), - version = array[ 0 ], - flags = array[ 1 ], - indexedGeometry = !! ( flags >> 7 & 0x01 ), - indicesType = flags >> 6 & 0x01, - bigEndian = ( flags >> 5 & 0x01 ) === 1, - attributesNumber = flags & 0x1F, - valuesNumber = 0, - indicesNumber = 0; - if ( bigEndian ) { +function decodePrwm( buffer ) { - valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ]; - indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ]; + const array = new Uint8Array( buffer ), + version = array[ 0 ]; - } else { + let flags = array[ 1 ]; - valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 ); - indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 ); + const indexedGeometry = !! ( flags >> 7 & 0x01 ), + indicesType = flags >> 6 & 0x01, + bigEndian = ( flags >> 5 & 0x01 ) === 1, + attributesNumber = flags & 0x1F; - } + let valuesNumber = 0, + indicesNumber = 0; - /** PRELIMINARY CHECKS **/ + if ( bigEndian ) { - if ( version === 0 ) { + valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ]; + indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ]; - throw new Error( 'PRWM decoder: Invalid format version: 0' ); + } else { - } else if ( version !== 1 ) { + valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 ); + indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 ); - throw new Error( 'PRWM decoder: Unsupported format version: ' + version ); + } - } + /** PRELIMINARY CHECKS **/ - if ( ! indexedGeometry ) { + if ( version === 0 ) { - if ( indicesType !== 0 ) { + throw new Error( 'PRWM decoder: Invalid format version: 0' ); - throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' ); + } else if ( version !== 1 ) { - } else if ( indicesNumber !== 0 ) { + throw new Error( 'PRWM decoder: Unsupported format version: ' + version ); - throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' ); + } - } + if ( ! indexedGeometry ) { - } + if ( indicesType !== 0 ) { - /** PARSING **/ + throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' ); - var pos = 8; + } else if ( indicesNumber !== 0 ) { - var attributes = {}, - attributeName, - char, - attributeType, - cardinality, - encodingType, - arrayType, - values, - indices, - i; + throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' ); - for ( i = 0; i < attributesNumber; i ++ ) { + } - attributeName = ''; + } - while ( pos < array.length ) { + /** PARSING **/ - char = array[ pos ]; - pos ++; + let pos = 8; - if ( char === 0 ) { + const attributes = {}; - break; + for ( let i = 0; i < attributesNumber; i ++ ) { - } else { + let attributeName = ''; - attributeName += String.fromCharCode( char ); + while ( pos < array.length ) { - } + const char = array[ pos ]; + pos ++; - } + if ( char === 0 ) { - flags = array[ pos ]; + break; - attributeType = flags >> 7 & 0x01; - cardinality = ( flags >> 4 & 0x03 ) + 1; - encodingType = flags & 0x0F; - arrayType = InvertedEncodingTypes[ encodingType ]; + } else { - pos ++; + attributeName += String.fromCharCode( char ); - // padding to next multiple of 4 - pos = Math.ceil( pos / 4 ) * 4; + } - values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian ); + } - pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber; + flags = array[ pos ]; - attributes[ attributeName ] = { - type: attributeType, - cardinality: cardinality, - values: values - }; + const attributeType = flags >> 7 & 0x01; + const cardinality = ( flags >> 4 & 0x03 ) + 1; + const encodingType = flags & 0x0F; + const arrayType = InvertedEncodingTypes[ encodingType ]; - } + pos ++; + // padding to next multiple of 4 pos = Math.ceil( pos / 4 ) * 4; - indices = null; - - if ( indexedGeometry ) { + const values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian ); - indices = copyFromBuffer( - buffer, - indicesType === 1 ? Uint32Array : Uint16Array, - pos, - indicesNumber, - bigEndian - ); + pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber; - } - - return { - version: version, - attributes: attributes, - indices: indices + attributes[ attributeName ] = { + type: attributeType, + cardinality: cardinality, + values: values }; } - // Define the public interface + pos = Math.ceil( pos / 4 ) * 4; + + let indices = null; - function PRWMLoader( manager ) { + if ( indexedGeometry ) { - Loader.call( this, manager ); + indices = copyFromBuffer( + buffer, + indicesType === 1 ? Uint32Array : Uint16Array, + pos, + indicesNumber, + bigEndian + ); } - PRWMLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + return { + version: version, + attributes: attributes, + indices: indices + }; + +} + +// Define the public interface - constructor: PRWMLoader, +class PRWMLoader extends Loader { - load: function ( url, onLoad, onProgress, onError ) { + constructor( manager ) { - var scope = this; + super( manager ); + + } - var loader = new FileLoader( scope.manager ); - loader.setPath( scope.path ); - loader.setResponseType( 'arraybuffer' ); - loader.setRequestHeader( scope.requestHeader ); - loader.setWithCredentials( scope.withCredentials ); + load( url, onLoad, onProgress, onError ) { - url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' ); + const scope = this; - loader.load( url, function ( arrayBuffer ) { + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); - try { + url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' ); - onLoad( scope.parse( arrayBuffer ) ); + loader.load( url, function ( arrayBuffer ) { - } catch ( e ) { + try { - if ( onError ) { + onLoad( scope.parse( arrayBuffer ) ); - onError( e ); + } catch ( e ) { - } else { + if ( onError ) { - console.error( e ); + onError( e ); - } + } else { - scope.manager.itemError( url ); + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); - }, + } - parse: function ( arrayBuffer ) { + }, onProgress, onError ); - var data = decodePrwm( arrayBuffer ), - attributesKey = Object.keys( data.attributes ), - bufferGeometry = new BufferGeometry(), - attribute, - i; + } - for ( i = 0; i < attributesKey.length; i ++ ) { + parse( arrayBuffer ) { - attribute = data.attributes[ attributesKey[ i ] ]; - bufferGeometry.setAttribute( attributesKey[ i ], new BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) ); + const data = decodePrwm( arrayBuffer ), + attributesKey = Object.keys( data.attributes ), + bufferGeometry = new BufferGeometry(); - } + for ( let i = 0; i < attributesKey.length; i ++ ) { - if ( data.indices !== null ) { + const attribute = data.attributes[ attributesKey[ i ] ]; + bufferGeometry.setAttribute( attributesKey[ i ], new BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) ); - bufferGeometry.setIndex( new BufferAttribute( data.indices, 1 ) ); + } - } + if ( data.indices !== null ) { - return bufferGeometry; + bufferGeometry.setIndex( new BufferAttribute( data.indices, 1 ) ); } - } ); + return bufferGeometry; - PRWMLoader.isBigEndianPlatform = function () { + } - return isBigEndianPlatform(); + static isBigEndianPlatform() { - }; + return isBigEndianPlatform(); - return PRWMLoader; + } -} )(); +} export { PRWMLoader }; diff --git a/examples/jsm/loaders/PVRLoader.js b/examples/jsm/loaders/PVRLoader.js index 662554fc42612e..553c1e5148a1e8 100644 --- a/examples/jsm/loaders/PVRLoader.js +++ b/examples/jsm/loaders/PVRLoader.js @@ -12,22 +12,20 @@ import { * TODO : implement loadMipmaps option */ -var PVRLoader = function ( manager ) { +class PVRLoader extends CompressedTextureLoader { - CompressedTextureLoader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -PVRLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), { - - constructor: PVRLoader, + } - parse: function ( buffer, loadMipmaps ) { + parse( buffer, loadMipmaps ) { - var headerLengthInt = 13; - var header = new Uint32Array( buffer, 0, headerLengthInt ); + const headerLengthInt = 13; + const header = new Uint32Array( buffer, 0, headerLengthInt ); - var pvrDatas = { + const pvrDatas = { buffer: buffer, header: header, loadMipmaps: loadMipmaps @@ -37,13 +35,13 @@ PVRLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot // PVR v3 - return PVRLoader._parseV3( pvrDatas ); + return _parseV3( pvrDatas ); } else if ( header[ 11 ] === 0x21525650 ) { // PVR v2 - return PVRLoader._parseV2( pvrDatas ); + return _parseV2( pvrDatas ); } else { @@ -53,15 +51,15 @@ PVRLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot } -} ); +} -PVRLoader._parseV3 = function ( pvrDatas ) { +function _parseV3( pvrDatas ) { - var header = pvrDatas.header; - var bpp, format; + const header = pvrDatas.header; + let bpp, format; - var metaLen = header[ 12 ], + const metaLen = header[ 12 ], pixelFormat = header[ 2 ], height = header[ 6 ], width = header[ 7 ], @@ -105,15 +103,15 @@ PVRLoader._parseV3 = function ( pvrDatas ) { pvrDatas.numMipmaps = numMipmaps; pvrDatas.isCubemap = ( numFaces === 6 ); - return PVRLoader._extract( pvrDatas ); + return _extract( pvrDatas ); -}; +} -PVRLoader._parseV2 = function ( pvrDatas ) { +function _parseV2( pvrDatas ) { - var header = pvrDatas.header; + const header = pvrDatas.header; - var headerLength = header[ 0 ], + const headerLength = header[ 0 ], height = header[ 1 ], width = header[ 2 ], numMipmaps = header[ 3 ], @@ -128,14 +126,14 @@ PVRLoader._parseV2 = function ( pvrDatas ) { numSurfs = header[ 12 ]; - var TYPE_MASK = 0xff; - var PVRTC_2 = 24, + const TYPE_MASK = 0xff; + const PVRTC_2 = 24, PVRTC_4 = 25; - var formatFlags = flags & TYPE_MASK; + const formatFlags = flags & TYPE_MASK; - var bpp, format; - var _hasAlpha = bitmaskAlpha > 0; + let bpp, format; + const _hasAlpha = bitmaskAlpha > 0; if ( formatFlags === PVRTC_4 ) { @@ -165,14 +163,14 @@ PVRLoader._parseV2 = function ( pvrDatas ) { // it juste a pvr containing 6 surface (no explicit cubemap type) pvrDatas.isCubemap = ( numSurfs === 6 ); - return PVRLoader._extract( pvrDatas ); + return _extract( pvrDatas ); -}; +} -PVRLoader._extract = function ( pvrDatas ) { +function _extract( pvrDatas ) { - var pvr = { + const pvr = { mipmaps: [], width: pvrDatas.width, height: pvrDatas.height, @@ -181,11 +179,9 @@ PVRLoader._extract = function ( pvrDatas ) { isCubemap: pvrDatas.isCubemap }; - var buffer = pvrDatas.buffer; + const buffer = pvrDatas.buffer; - var dataOffset = pvrDatas.dataPtr, - bpp = pvrDatas.bpp, - numSurfs = pvrDatas.numSurfaces, + let dataOffset = pvrDatas.dataPtr, dataSize = 0, blockSize = 0, blockWidth = 0, @@ -193,6 +189,9 @@ PVRLoader._extract = function ( pvrDatas ) { widthBlocks = 0, heightBlocks = 0; + const bpp = pvrDatas.bpp, + numSurfs = pvrDatas.numSurfaces; + if ( bpp === 2 ) { blockWidth = 8; @@ -209,11 +208,11 @@ PVRLoader._extract = function ( pvrDatas ) { pvr.mipmaps.length = pvrDatas.numMipmaps * numSurfs; - var mipLevel = 0; + let mipLevel = 0; while ( mipLevel < pvrDatas.numMipmaps ) { - var sWidth = pvrDatas.width >> mipLevel, + const sWidth = pvrDatas.width >> mipLevel, sHeight = pvrDatas.height >> mipLevel; widthBlocks = sWidth / blockWidth; @@ -225,11 +224,11 @@ PVRLoader._extract = function ( pvrDatas ) { dataSize = widthBlocks * heightBlocks * blockSize; - for ( var surfIndex = 0; surfIndex < numSurfs; surfIndex ++ ) { + for ( let surfIndex = 0; surfIndex < numSurfs; surfIndex ++ ) { - var byteArray = new Uint8Array( buffer, dataOffset, dataSize ); + const byteArray = new Uint8Array( buffer, dataOffset, dataSize ); - var mipmap = { + const mipmap = { data: byteArray, width: sWidth, height: sHeight @@ -247,6 +246,6 @@ PVRLoader._extract = function ( pvrDatas ) { return pvr; -}; +} export { PVRLoader }; diff --git a/examples/jsm/loaders/RGBELoader.js b/examples/jsm/loaders/RGBELoader.js index 9bfd6aa4ff3db9..0daadeff2aa2fa 100644 --- a/examples/jsm/loaders/RGBELoader.js +++ b/examples/jsm/loaders/RGBELoader.js @@ -15,23 +15,21 @@ import { // https://github.com/mrdoob/three.js/issues/5552 // http://en.wikipedia.org/wiki/RGBE_image_format -var RGBELoader = function ( manager ) { +class RGBELoader extends DataTextureLoader { - DataTextureLoader.call( this, manager ); + constructor( manager ) { - this.type = UnsignedByteType; + super( manager ); -}; + this.type = UnsignedByteType; -RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype ), { - - constructor: RGBELoader, + } // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html - parse: function ( buffer ) { + parse( buffer ) { - var + const /* return codes for rgbe routines */ //RGBE_RETURN_SUCCESS = 0, RGBE_RETURN_FAILURE = - 1, @@ -77,11 +75,13 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype fgets = function ( buffer, lineLimit, consume ) { + const chunkSize = 128; + lineLimit = ! lineLimit ? 1024 : lineLimit; - var p = buffer.pos, - i = - 1, len = 0, s = '', chunkSize = 128, - chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) ) - ; + let p = buffer.pos, + i = - 1, len = 0, s = '', + chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) ); + while ( ( 0 > ( i = chunk.indexOf( NEWLINE ) ) ) && ( len < lineLimit ) && ( p < buffer.byteLength ) ) { s += chunk; len += chunk.length; @@ -110,10 +110,9 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype /* minimal header reading. modify if you want to parse more information */ RGBE_ReadHeader = function ( buffer ) { - var line, match, - // regexes to parse header info fields - magic_token_re = /^#\?(\S+)/, + // regexes to parse header info fields + const magic_token_re = /^#\?(\S+)/, gamma_re = /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/, exposure_re = /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/, format_re = /^\s*FORMAT=(\S+)\s*$/, @@ -140,6 +139,8 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype }; + let line, match; + if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) { return rgbe_error( rgbe_read_error, 'no header found' ); @@ -219,10 +220,7 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype RGBE_ReadPixels_RLE = function ( buffer, w, h ) { - var data_rgba, offset, pos, count, byteValue, - scanline_buffer, ptr, ptr_end, i, l, off, isEncodedRun, - scanline_width = w, num_scanlines = h, rgbeStart - ; + const scanline_width = w; if ( // run length encoding is not allowed so read flat @@ -242,7 +240,7 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype } - data_rgba = new Uint8Array( 4 * w * h ); + const data_rgba = new Uint8Array( 4 * w * h ); if ( ! data_rgba.length ) { @@ -250,9 +248,12 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype } - offset = 0; pos = 0; ptr_end = 4 * scanline_width; - rgbeStart = new Uint8Array( 4 ); - scanline_buffer = new Uint8Array( ptr_end ); + let offset = 0, pos = 0; + + const ptr_end = 4 * scanline_width; + const rgbeStart = new Uint8Array( 4 ); + const scanline_buffer = new Uint8Array( ptr_end ); + let num_scanlines = h; // read in each successive scanline while ( ( num_scanlines > 0 ) && ( pos < buffer.byteLength ) ) { @@ -276,11 +277,12 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype // read each of the four channels for the scanline into the buffer // first red, then green, then blue, then exponent - ptr = 0; + let ptr = 0, count; + while ( ( ptr < ptr_end ) && ( pos < buffer.byteLength ) ) { count = buffer[ pos ++ ]; - isEncodedRun = count > 128; + const isEncodedRun = count > 128; if ( isEncodedRun ) count -= 128; if ( ( 0 === count ) || ( ptr + count > ptr_end ) ) { @@ -292,8 +294,8 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype if ( isEncodedRun ) { // a (encoded) run of the same value - byteValue = buffer[ pos ++ ]; - for ( i = 0; i < count; i ++ ) { + const byteValue = buffer[ pos ++ ]; + for ( let i = 0; i < count; i ++ ) { scanline_buffer[ ptr ++ ] = byteValue; @@ -313,10 +315,10 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype // now convert data from buffer into rgba // first red, then green, then blue, then exponent (alpha) - l = scanline_width; //scanline_buffer.byteLength; - for ( i = 0; i < l; i ++ ) { + const l = scanline_width; //scanline_buffer.byteLength; + for ( let i = 0; i < l; i ++ ) { - off = 0; + let off = 0; data_rgba[ offset ] = scanline_buffer[ i + off ]; off += scanline_width; //1; data_rgba[ offset + 1 ] = scanline_buffer[ i + off ]; @@ -336,10 +338,10 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype }; - var RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) { + const RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) { - var e = sourceArray[ sourceOffset + 3 ]; - var scale = Math.pow( 2.0, e - 128.0 ) / 255.0; + const e = sourceArray[ sourceOffset + 3 ]; + const scale = Math.pow( 2.0, e - 128.0 ) / 255.0; destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale; destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale; @@ -347,10 +349,10 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype }; - var RGBEByteToRGBHalf = function ( sourceArray, sourceOffset, destArray, destOffset ) { + const RGBEByteToRGBHalf = function ( sourceArray, sourceOffset, destArray, destOffset ) { - var e = sourceArray[ sourceOffset + 3 ]; - var scale = Math.pow( 2.0, e - 128.0 ) / 255.0; + const e = sourceArray[ sourceOffset + 3 ]; + const scale = Math.pow( 2.0, e - 128.0 ) / 255.0; destArray[ destOffset + 0 ] = DataUtils.toHalfFloat( sourceArray[ sourceOffset + 0 ] * scale ); destArray[ destOffset + 1 ] = DataUtils.toHalfFloat( sourceArray[ sourceOffset + 1 ] * scale ); @@ -358,57 +360,60 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype }; - var byteArray = new Uint8Array( buffer ); + const byteArray = new Uint8Array( buffer ); byteArray.pos = 0; - var rgbe_header_info = RGBE_ReadHeader( byteArray ); + const rgbe_header_info = RGBE_ReadHeader( byteArray ); if ( RGBE_RETURN_FAILURE !== rgbe_header_info ) { - var w = rgbe_header_info.width, + const w = rgbe_header_info.width, h = rgbe_header_info.height, image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h ); if ( RGBE_RETURN_FAILURE !== image_rgba_data ) { + let data, format, type; + let numElements; + switch ( this.type ) { case UnsignedByteType: - var data = image_rgba_data; - var format = RGBEFormat; // handled as THREE.RGBAFormat in shaders - var type = UnsignedByteType; + data = image_rgba_data; + format = RGBEFormat; // handled as THREE.RGBAFormat in shaders + type = UnsignedByteType; break; case FloatType: - var numElements = ( image_rgba_data.length / 4 ) * 3; - var floatArray = new Float32Array( numElements ); + numElements = ( image_rgba_data.length / 4 ) * 3; + const floatArray = new Float32Array( numElements ); - for ( var j = 0; j < numElements; j ++ ) { + for ( let j = 0; j < numElements; j ++ ) { RGBEByteToRGBFloat( image_rgba_data, j * 4, floatArray, j * 3 ); } - var data = floatArray; - var format = RGBFormat; - var type = FloatType; + data = floatArray; + format = RGBFormat; + type = FloatType; break; case HalfFloatType: - var numElements = ( image_rgba_data.length / 4 ) * 3; - var halfArray = new Uint16Array( numElements ); + numElements = ( image_rgba_data.length / 4 ) * 3; + const halfArray = new Uint16Array( numElements ); - for ( var j = 0; j < numElements; j ++ ) { + for ( let j = 0; j < numElements; j ++ ) { RGBEByteToRGBHalf( image_rgba_data, j * 4, halfArray, j * 3 ); } - var data = halfArray; - var format = RGBFormat; - var type = HalfFloatType; + data = halfArray; + format = RGBFormat; + type = HalfFloatType; break; default: @@ -434,16 +439,16 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype return null; - }, + } - setDataType: function ( value ) { + setDataType( value ) { this.type = value; return this; - }, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { function onLoadCallback( texture, texData ) { @@ -482,10 +487,10 @@ RGBELoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype } - return DataTextureLoader.prototype.load.call( this, url, onLoadCallback, onProgress, onError ); + return super.load( url, onLoadCallback, onProgress, onError ); } -} ); +} export { RGBELoader }; diff --git a/examples/jsm/loaders/STLLoader.js b/examples/jsm/loaders/STLLoader.js index e00c68bce524a6..00d91d313f3612 100644 --- a/examples/jsm/loaders/STLLoader.js +++ b/examples/jsm/loaders/STLLoader.js @@ -21,7 +21,7 @@ import { * ASCII decoding assumes file is UTF-8. * * Usage: - * var loader = new STLLoader(); + * const loader = new STLLoader(); * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { * scene.add( new THREE.Mesh( geometry ) ); * }); @@ -31,24 +31,24 @@ import { * if (geometry.hasColors) { * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true }); * } else { .... } - * var mesh = new THREE.Mesh( geometry, material ); + * const mesh = new THREE.Mesh( geometry, material ); * * For ASCII STLs containing multiple solids, each solid is assigned to a different group. * Groups can be used to assign a different color by defining an array of materials with the same length of * geometry.groups and passing it to the Mesh constructor: * - * var mesh = new THREE.Mesh( geometry, material ); + * const mesh = new THREE.Mesh( geometry, material ); * * For example: * - * var materials = []; - * var nGeometryGroups = geometry.groups.length; + * const materials = []; + * const nGeometryGroups = geometry.groups.length; * - * var colorMap = ...; // Some logic to index colors. + * const colorMap = ...; // Some logic to index colors. * - * for (var i = 0; i < nGeometryGroups; i++) { + * for (let i = 0; i < nGeometryGroups; i++) { * - * var material = new THREE.MeshPhongMaterial({ + * const material = new THREE.MeshPhongMaterial({ * color: colorMap[i], * wireframe: false * }); @@ -56,25 +56,23 @@ import { * } * * materials.push(material); - * var mesh = new THREE.Mesh(geometry, materials); + * const mesh = new THREE.Mesh(geometry, materials); */ -var STLLoader = function ( manager ) { +class STLLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: STLLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( this.requestHeader ); @@ -104,17 +102,16 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { function isBinary( data ) { - var expect, face_size, n_faces, reader; - reader = new DataView( data ); - face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 ); - n_faces = reader.getUint32( 80, true ); - expect = 80 + ( 32 / 8 ) + ( n_faces * face_size ); + const reader = new DataView( data ); + const face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 ); + const n_faces = reader.getUint32( 80, true ); + const expect = 80 + ( 32 / 8 ) + ( n_faces * face_size ); if ( expect === reader.byteLength ) { @@ -132,9 +129,9 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd' - var solid = [ 115, 111, 108, 105, 100 ]; + const solid = [ 115, 111, 108, 105, 100 ]; - for ( var off = 0; off < 5; off ++ ) { + for ( let off = 0; off < 5; off ++ ) { // If "solid" text is matched to the current offset, declare it to be an ASCII STL. @@ -152,7 +149,7 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // Check if each byte in query matches the corresponding byte from the current offset - for ( var i = 0, il = query.length; i < il; i ++ ) { + for ( let i = 0, il = query.length; i < il; i ++ ) { if ( query[ i ] !== reader.getUint8( offset + i, false ) ) return false; @@ -164,16 +161,16 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseBinary( data ) { - var reader = new DataView( data ); - var faces = reader.getUint32( 80, true ); + const reader = new DataView( data ); + const faces = reader.getUint32( 80, true ); - var r, g, b, hasColors = false, colors; - var defaultR, defaultG, defaultB, alpha; + let r, g, b, hasColors = false, colors; + let defaultR, defaultG, defaultB, alpha; // process STL header // check for default color in header ("COLOR=rgba" sequence). - for ( var index = 0; index < 80 - 10; index ++ ) { + for ( let index = 0; index < 80 - 10; index ++ ) { if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) && ( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) && @@ -191,24 +188,24 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var dataOffset = 84; - var faceLength = 12 * 4 + 2; + const dataOffset = 84; + const faceLength = 12 * 4 + 2; - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); - var vertices = new Float32Array( faces * 3 * 3 ); - var normals = new Float32Array( faces * 3 * 3 ); + const vertices = new Float32Array( faces * 3 * 3 ); + const normals = new Float32Array( faces * 3 * 3 ); - for ( var face = 0; face < faces; face ++ ) { + for ( let face = 0; face < faces; face ++ ) { - var start = dataOffset + face * faceLength; - var normalX = reader.getFloat32( start, true ); - var normalY = reader.getFloat32( start + 4, true ); - var normalZ = reader.getFloat32( start + 8, true ); + const start = dataOffset + face * faceLength; + const normalX = reader.getFloat32( start, true ); + const normalY = reader.getFloat32( start + 4, true ); + const normalZ = reader.getFloat32( start + 8, true ); if ( hasColors ) { - var packedColor = reader.getUint16( start + 48, true ); + const packedColor = reader.getUint16( start + 48, true ); if ( ( packedColor & 0x8000 ) === 0 ) { @@ -228,10 +225,10 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - for ( var i = 1; i <= 3; i ++ ) { + for ( let i = 1; i <= 3; i ++ ) { - var vertexstart = start + i * 12; - var componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 ); + const vertexstart = start + i * 12; + const componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 ); vertices[ componentIdx ] = reader.getFloat32( vertexstart, true ); vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true ); @@ -270,38 +267,38 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseASCII( data ) { - var geometry = new BufferGeometry(); - var patternSolid = /solid([\s\S]*?)endsolid/g; - var patternFace = /facet([\s\S]*?)endfacet/g; - var faceCounter = 0; + const geometry = new BufferGeometry(); + const patternSolid = /solid([\s\S]*?)endsolid/g; + const patternFace = /facet([\s\S]*?)endfacet/g; + let faceCounter = 0; - var patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source; - var patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' ); - var patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' ); + const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source; + const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' ); + const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' ); - var vertices = []; - var normals = []; + const vertices = []; + const normals = []; - var normal = new Vector3(); + const normal = new Vector3(); - var result; + let result; - var groupCount = 0; - var startVertex = 0; - var endVertex = 0; + let groupCount = 0; + let startVertex = 0; + let endVertex = 0; while ( ( result = patternSolid.exec( data ) ) !== null ) { startVertex = endVertex; - var solid = result[ 0 ]; + const solid = result[ 0 ]; while ( ( result = patternFace.exec( solid ) ) !== null ) { - var vertexCountPerFace = 0; - var normalCountPerFace = 0; + let vertexCountPerFace = 0; + let normalCountPerFace = 0; - var text = result[ 0 ]; + const text = result[ 0 ]; while ( ( result = patternNormal.exec( text ) ) !== null ) { @@ -341,8 +338,8 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var start = startVertex; - var count = endVertex - startVertex; + const start = startVertex; + const count = endVertex - startVertex; geometry.addGroup( start, count, groupCount ); groupCount ++; @@ -372,8 +369,8 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( typeof buffer === 'string' ) { - var array_buffer = new Uint8Array( buffer.length ); - for ( var i = 0; i < buffer.length; i ++ ) { + const array_buffer = new Uint8Array( buffer.length ); + for ( let i = 0; i < buffer.length; i ++ ) { array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian @@ -391,12 +388,12 @@ STLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // start - var binData = ensureBinary( data ); + const binData = ensureBinary( data ); return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) ); } -} ); +} export { STLLoader }; diff --git a/examples/jsm/loaders/SVGLoader.js b/examples/jsm/loaders/SVGLoader.js index 3cf0284e457a84..36748be7b7b738 100644 --- a/examples/jsm/loaders/SVGLoader.js +++ b/examples/jsm/loaders/SVGLoader.js @@ -13,27 +13,25 @@ import { Vector3 } from '../../../build/three.module.js'; -var SVGLoader = function ( manager ) { +class SVGLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - // Default dots per inch - this.defaultDPI = 90; + super( manager ); - // Accepted units: 'mm', 'cm', 'in', 'pt', 'pc', 'px' - this.defaultUnit = 'px'; + // Default dots per inch + this.defaultDPI = 90; -}; + // Accepted units: 'mm', 'cm', 'in', 'pt', 'pc', 'px' + this.defaultUnit = 'px'; -SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: SVGLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setRequestHeader( scope.requestHeader ); loader.setWithCredentials( scope.withCredentials ); @@ -61,21 +59,21 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( text ) { + parse( text ) { - var scope = this; + const scope = this; function parseNode( node, style ) { if ( node.nodeType !== 1 ) return; - var transform = getNodeTransform( node ); + const transform = getNodeTransform( node ); - var traverseChildNodes = true; + let traverseChildNodes = true; - var path = null; + let path = null; switch ( node.nodeName ) { @@ -131,8 +129,8 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { case 'use': style = parseStyle( node, style ); - var usedNodeId = node.href.baseVal.substring( 1 ); - var usedNode = node.viewportElement.getElementById( usedNodeId ); + const usedNodeId = node.href.baseVal.substring( 1 ); + const usedNode = node.viewportElement.getElementById( usedNodeId ); if ( usedNode ) { parseNode( usedNode, style ); @@ -168,9 +166,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( traverseChildNodes ) { - var nodes = node.childNodes; + const nodes = node.childNodes; - for ( var i = 0; i < nodes.length; i ++ ) { + for ( let i = 0; i < nodes.length; i ++ ) { parseNode( nodes[ i ], style ); @@ -198,27 +196,27 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parsePathNode( node ) { - var path = new ShapePath(); + const path = new ShapePath(); - var point = new Vector2(); - var control = new Vector2(); + const point = new Vector2(); + const control = new Vector2(); - var firstPoint = new Vector2(); - var isFirstPoint = true; - var doSetFirstPoint = false; + const firstPoint = new Vector2(); + let isFirstPoint = true; + let doSetFirstPoint = false; - var d = node.getAttribute( 'd' ); + const d = node.getAttribute( 'd' ); // console.log( d ); - var commands = d.match( /[a-df-z][^a-df-z]*/ig ); + const commands = d.match( /[a-df-z][^a-df-z]*/ig ); - for ( var i = 0, l = commands.length; i < l; i ++ ) { + for ( let i = 0, l = commands.length; i < l; i ++ ) { - var command = commands[ i ]; + const command = commands[ i ]; - var type = command.charAt( 0 ); - var data = command.substr( 1 ).trim(); + const type = command.charAt( 0 ); + const data = command.substr( 1 ).trim(); if ( isFirstPoint === true ) { @@ -227,11 +225,13 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } + let numbers; + switch ( type ) { case 'M': - var numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 2 ) { + numbers = parseFloats( data ); + for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) { point.x = numbers[ j + 0 ]; point.y = numbers[ j + 1 ]; @@ -255,9 +255,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'H': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j ++ ) { + for ( let j = 0, jl = numbers.length; j < jl; j ++ ) { point.x = numbers[ j ]; control.x = point.x; @@ -271,9 +271,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'V': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j ++ ) { + for ( let j = 0, jl = numbers.length; j < jl; j ++ ) { point.y = numbers[ j ]; control.x = point.x; @@ -287,9 +287,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'L': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 2 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) { point.x = numbers[ j + 0 ]; point.y = numbers[ j + 1 ]; @@ -304,9 +304,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'C': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 6 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 6 ) { path.bezierCurveTo( numbers[ j + 0 ], @@ -328,9 +328,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'S': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 4 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) { path.bezierCurveTo( getReflection( point.x, control.x ), @@ -352,9 +352,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'Q': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 4 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) { path.quadraticCurveTo( numbers[ j + 0 ], @@ -374,12 +374,12 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'T': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 2 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) { - var rx = getReflection( point.x, control.x ); - var ry = getReflection( point.y, control.y ); + const rx = getReflection( point.x, control.x ); + const ry = getReflection( point.y, control.y ); path.quadraticCurveTo( rx, ry, @@ -398,14 +398,14 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'A': - var numbers = parseFloats( data, [ 3, 4 ], 7 ); + numbers = parseFloats( data, [ 3, 4 ], 7 ); - for ( var j = 0, jl = numbers.length; j < jl; j += 7 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 7 ) { // skip command if start point == end point if ( numbers[ j + 5 ] == point.x && numbers[ j + 6 ] == point.y ) continue; - var start = point.clone(); + const start = point.clone(); point.x = numbers[ j + 5 ]; point.y = numbers[ j + 6 ]; control.x = point.x; @@ -421,9 +421,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'm': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 2 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) { point.x += numbers[ j + 0 ]; point.y += numbers[ j + 1 ]; @@ -447,9 +447,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'h': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j ++ ) { + for ( let j = 0, jl = numbers.length; j < jl; j ++ ) { point.x += numbers[ j ]; control.x = point.x; @@ -463,9 +463,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'v': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j ++ ) { + for ( let j = 0, jl = numbers.length; j < jl; j ++ ) { point.y += numbers[ j ]; control.x = point.x; @@ -479,9 +479,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'l': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 2 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) { point.x += numbers[ j + 0 ]; point.y += numbers[ j + 1 ]; @@ -496,9 +496,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'c': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 6 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 6 ) { path.bezierCurveTo( point.x + numbers[ j + 0 ], @@ -520,9 +520,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 's': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 4 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) { path.bezierCurveTo( getReflection( point.x, control.x ), @@ -544,9 +544,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'q': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 4 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) { path.quadraticCurveTo( point.x + numbers[ j + 0 ], @@ -566,12 +566,12 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 't': - var numbers = parseFloats( data ); + numbers = parseFloats( data ); - for ( var j = 0, jl = numbers.length; j < jl; j += 2 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) { - var rx = getReflection( point.x, control.x ); - var ry = getReflection( point.y, control.y ); + const rx = getReflection( point.x, control.x ); + const ry = getReflection( point.y, control.y ); path.quadraticCurveTo( rx, ry, @@ -590,14 +590,14 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { break; case 'a': - var numbers = parseFloats( data, [ 3, 4 ], 7 ); + numbers = parseFloats( data, [ 3, 4 ], 7 ); - for ( var j = 0, jl = numbers.length; j < jl; j += 7 ) { + for ( let j = 0, jl = numbers.length; j < jl; j += 7 ) { // skip command if no displacement if ( numbers[ j + 5 ] == 0 && numbers[ j + 6 ] == 0 ) continue; - var start = point.clone(); + const start = point.clone(); point.x += numbers[ j + 5 ]; point.y += numbers[ j + 6 ]; control.x = point.x; @@ -646,18 +646,18 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( ! node.sheet || ! node.sheet.cssRules || ! node.sheet.cssRules.length ) return; - for ( var i = 0; i < node.sheet.cssRules.length; i ++ ) { + for ( let i = 0; i < node.sheet.cssRules.length; i ++ ) { - var stylesheet = node.sheet.cssRules[ i ]; + const stylesheet = node.sheet.cssRules[ i ]; if ( stylesheet.type !== 1 ) continue; - var selectorList = stylesheet.selectorText + const selectorList = stylesheet.selectorText .split( /,/gm ) .filter( Boolean ) .map( i => i.trim() ); - for ( var j = 0; j < selectorList.length; j ++ ) { + for ( let j = 0; j < selectorList.length; j ++ ) { stylesheets[ selectorList[ j ] ] = Object.assign( stylesheets[ selectorList[ j ] ] || {}, @@ -696,24 +696,24 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { ry = Math.abs( ry ); // Compute (x1', y1') - var dx2 = ( start.x - end.x ) / 2.0; - var dy2 = ( start.y - end.y ) / 2.0; - var x1p = Math.cos( x_axis_rotation ) * dx2 + Math.sin( x_axis_rotation ) * dy2; - var y1p = - Math.sin( x_axis_rotation ) * dx2 + Math.cos( x_axis_rotation ) * dy2; + const dx2 = ( start.x - end.x ) / 2.0; + const dy2 = ( start.y - end.y ) / 2.0; + const x1p = Math.cos( x_axis_rotation ) * dx2 + Math.sin( x_axis_rotation ) * dy2; + const y1p = - Math.sin( x_axis_rotation ) * dx2 + Math.cos( x_axis_rotation ) * dy2; // Compute (cx', cy') - var rxs = rx * rx; - var rys = ry * ry; - var x1ps = x1p * x1p; - var y1ps = y1p * y1p; + let rxs = rx * rx; + let rys = ry * ry; + const x1ps = x1p * x1p; + const y1ps = y1p * y1p; // Ensure radii are large enough - var cr = x1ps / rxs + y1ps / rys; + const cr = x1ps / rxs + y1ps / rys; if ( cr > 1 ) { // scale up rx,ry equally so cr == 1 - var s = Math.sqrt( cr ); + const s = Math.sqrt( cr ); rx = s * rx; ry = s * ry; rxs = rx * rx; @@ -721,20 +721,20 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var dq = ( rxs * y1ps + rys * x1ps ); - var pq = ( rxs * rys - dq ) / dq; - var q = Math.sqrt( Math.max( 0, pq ) ); + const dq = ( rxs * y1ps + rys * x1ps ); + const pq = ( rxs * rys - dq ) / dq; + let q = Math.sqrt( Math.max( 0, pq ) ); if ( large_arc_flag === sweep_flag ) q = - q; - var cxp = q * rx * y1p / ry; - var cyp = - q * ry * x1p / rx; + const cxp = q * rx * y1p / ry; + const cyp = - q * ry * x1p / rx; // Step 3: Compute (cx, cy) from (cx', cy') - var cx = Math.cos( x_axis_rotation ) * cxp - Math.sin( x_axis_rotation ) * cyp + ( start.x + end.x ) / 2; - var cy = Math.sin( x_axis_rotation ) * cxp + Math.cos( x_axis_rotation ) * cyp + ( start.y + end.y ) / 2; + const cx = Math.cos( x_axis_rotation ) * cxp - Math.sin( x_axis_rotation ) * cyp + ( start.x + end.x ) / 2; + const cy = Math.sin( x_axis_rotation ) * cxp + Math.cos( x_axis_rotation ) * cyp + ( start.y + end.y ) / 2; // Step 4: Compute θ1 and Δθ - var theta = svgAngle( 1, 0, ( x1p - cxp ) / rx, ( y1p - cyp ) / ry ); - var delta = svgAngle( ( x1p - cxp ) / rx, ( y1p - cyp ) / ry, ( - x1p - cxp ) / rx, ( - y1p - cyp ) / ry ) % ( Math.PI * 2 ); + const theta = svgAngle( 1, 0, ( x1p - cxp ) / rx, ( y1p - cyp ) / ry ); + const delta = svgAngle( ( x1p - cxp ) / rx, ( y1p - cyp ) / ry, ( - x1p - cxp ) / rx, ( - y1p - cyp ) / ry ) % ( Math.PI * 2 ); path.currentPath.absellipse( cx, cy, rx, ry, theta, theta + delta, sweep_flag === 0, x_axis_rotation ); @@ -742,9 +742,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function svgAngle( ux, uy, vx, vy ) { - var dot = ux * vx + uy * vy; - var len = Math.sqrt( ux * ux + uy * uy ) * Math.sqrt( vx * vx + vy * vy ); - var ang = Math.acos( Math.max( - 1, Math.min( 1, dot / len ) ) ); // floating point precision, slightly over values appear + const dot = ux * vx + uy * vy; + const len = Math.sqrt( ux * ux + uy * uy ) * Math.sqrt( vx * vx + vy * vy ); + let ang = Math.acos( Math.max( - 1, Math.min( 1, dot / len ) ) ); // floating point precision, slightly over values appear if ( ( ux * vy - uy * vx ) < 0 ) ang = - ang; return ang; @@ -756,14 +756,14 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { */ function parseRectNode( node ) { - var x = parseFloatWithUnits( node.getAttribute( 'x' ) || 0 ); - var y = parseFloatWithUnits( node.getAttribute( 'y' ) || 0 ); - var rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || 0 ); - var ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || 0 ); - var w = parseFloatWithUnits( node.getAttribute( 'width' ) ); - var h = parseFloatWithUnits( node.getAttribute( 'height' ) ); + const x = parseFloatWithUnits( node.getAttribute( 'x' ) || 0 ); + const y = parseFloatWithUnits( node.getAttribute( 'y' ) || 0 ); + const rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || 0 ); + const ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || 0 ); + const w = parseFloatWithUnits( node.getAttribute( 'width' ) ); + const h = parseFloatWithUnits( node.getAttribute( 'height' ) ); - var path = new ShapePath(); + const path = new ShapePath(); path.moveTo( x + 2 * rx, y ); path.lineTo( x + w - 2 * rx, y ); if ( rx !== 0 || ry !== 0 ) path.bezierCurveTo( x + w, y, x + w, y, x + w, y + 2 * ry ); @@ -793,8 +793,8 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function iterator( match, a, b ) { - var x = parseFloatWithUnits( a ); - var y = parseFloatWithUnits( b ); + const x = parseFloatWithUnits( a ); + const y = parseFloatWithUnits( b ); if ( index === 0 ) { @@ -810,11 +810,11 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g; + const regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g; - var path = new ShapePath(); + const path = new ShapePath(); - var index = 0; + let index = 0; node.getAttribute( 'points' ).replace( regex, iterator ); @@ -828,8 +828,8 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function iterator( match, a, b ) { - var x = parseFloatWithUnits( a ); - var y = parseFloatWithUnits( b ); + const x = parseFloatWithUnits( a ); + const y = parseFloatWithUnits( b ); if ( index === 0 ) { @@ -845,11 +845,11 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g; + const regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g; - var path = new ShapePath(); + const path = new ShapePath(); - var index = 0; + let index = 0; node.getAttribute( 'points' ).replace( regex, iterator ); @@ -861,14 +861,14 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseCircleNode( node ) { - var x = parseFloatWithUnits( node.getAttribute( 'cx' ) || 0 ); - var y = parseFloatWithUnits( node.getAttribute( 'cy' ) || 0 ); - var r = parseFloatWithUnits( node.getAttribute( 'r' ) || 0 ); + const x = parseFloatWithUnits( node.getAttribute( 'cx' ) || 0 ); + const y = parseFloatWithUnits( node.getAttribute( 'cy' ) || 0 ); + const r = parseFloatWithUnits( node.getAttribute( 'r' ) || 0 ); - var subpath = new Path(); + const subpath = new Path(); subpath.absarc( x, y, r, 0, Math.PI * 2 ); - var path = new ShapePath(); + const path = new ShapePath(); path.subPaths.push( subpath ); return path; @@ -877,15 +877,15 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseEllipseNode( node ) { - var x = parseFloatWithUnits( node.getAttribute( 'cx' ) || 0 ); - var y = parseFloatWithUnits( node.getAttribute( 'cy' ) || 0 ); - var rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || 0 ); - var ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || 0 ); + const x = parseFloatWithUnits( node.getAttribute( 'cx' ) || 0 ); + const y = parseFloatWithUnits( node.getAttribute( 'cy' ) || 0 ); + const rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || 0 ); + const ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || 0 ); - var subpath = new Path(); + const subpath = new Path(); subpath.absellipse( x, y, rx, ry, 0, Math.PI * 2 ); - var path = new ShapePath(); + const path = new ShapePath(); path.subPaths.push( subpath ); return path; @@ -894,12 +894,12 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseLineNode( node ) { - var x1 = parseFloatWithUnits( node.getAttribute( 'x1' ) || 0 ); - var y1 = parseFloatWithUnits( node.getAttribute( 'y1' ) || 0 ); - var x2 = parseFloatWithUnits( node.getAttribute( 'x2' ) || 0 ); - var y2 = parseFloatWithUnits( node.getAttribute( 'y2' ) || 0 ); + const x1 = parseFloatWithUnits( node.getAttribute( 'x1' ) || 0 ); + const y1 = parseFloatWithUnits( node.getAttribute( 'y1' ) || 0 ); + const x2 = parseFloatWithUnits( node.getAttribute( 'x2' ) || 0 ); + const y2 = parseFloatWithUnits( node.getAttribute( 'y2' ) || 0 ); - var path = new ShapePath(); + const path = new ShapePath(); path.moveTo( x1, y1 ); path.lineTo( x2, y2 ); path.currentPath.autoClose = false; @@ -914,16 +914,16 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { style = Object.assign( {}, style ); // clone style - var stylesheetStyles = {}; + let stylesheetStyles = {}; if ( node.hasAttribute( 'class' ) ) { - var classSelectors = node.getAttribute( 'class' ) + const classSelectors = node.getAttribute( 'class' ) .split( /\s/ ) .filter( Boolean ) .map( i => i.trim() ); - for ( var i = 0; i < classSelectors.length; i ++ ) { + for ( let i = 0; i < classSelectors.length; i ++ ) { stylesheetStyles = Object.assign( stylesheetStyles, stylesheets[ '.' + classSelectors[ i ] ] ); @@ -999,7 +999,7 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } // Character groups - var RE = { + const RE = { SEPARATOR: /[ \t\r\n\,.\-+]/, WHITESPACE: /[ \t\r\n]/, DIGIT: /[\d]/, @@ -1011,18 +1011,19 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }; // States - var SEP = 0; - var INT = 1; - var FLOAT = 2; - var EXP = 3; + const SEP = 0; + const INT = 1; + const FLOAT = 2; + const EXP = 3; - var state = SEP; - var seenComma = true; - var result = [], number = '', exponent = ''; + let state = SEP; + let seenComma = true; + let number = '', exponent = ''; + const result = []; function throwSyntaxError( current, i, partial ) { - var error = new SyntaxError( 'Unexpected character "' + current + '" at index ' + i + '.' ); + const error = new SyntaxError( 'Unexpected character "' + current + '" at index ' + i + '.' ); error.partial = partial; throw error; @@ -1042,8 +1043,10 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var current, i = 0, length = input.length; - for ( i = 0; i < length; i ++ ) { + let current; + const length = input.length; + + for ( let i = 0; i < length; i ++ ) { current = input[ i ]; @@ -1233,10 +1236,10 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { // Units - var units = [ 'mm', 'cm', 'in', 'pt', 'pc', 'px' ]; + const units = [ 'mm', 'cm', 'in', 'pt', 'pc', 'px' ]; // Conversion: [ fromUnit ][ toUnit ] (-1 means dpi dependent) - var unitConversion = { + const unitConversion = { 'mm': { 'mm': 1, @@ -1286,13 +1289,13 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseFloatWithUnits( string ) { - var theUnit = 'px'; + let theUnit = 'px'; if ( typeof string === 'string' || string instanceof String ) { - for ( var i = 0, n = units.length; i < n; i ++ ) { + for ( let i = 0, n = units.length; i < n; i ++ ) { - var u = units[ i ]; + const u = units[ i ]; if ( string.endsWith( u ) ) { @@ -1306,7 +1309,7 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var scale = undefined; + let scale = undefined; if ( theUnit === 'px' && scope.defaultUnit !== 'px' ) { @@ -1342,7 +1345,7 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var transform = parseNodeTransform( node ); + const transform = parseNodeTransform( node ); if ( transformStack.length > 0 ) { @@ -1359,13 +1362,13 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function parseNodeTransform( node ) { - var transform = new Matrix3(); - var currentTransform = tempTransform0; + const transform = new Matrix3(); + const currentTransform = tempTransform0; if ( node.nodeName === 'use' && ( node.hasAttribute( 'x' ) || node.hasAttribute( 'y' ) ) ) { - var tx = parseFloatWithUnits( node.getAttribute( 'x' ) ); - var ty = parseFloatWithUnits( node.getAttribute( 'y' ) ); + const tx = parseFloatWithUnits( node.getAttribute( 'x' ) ); + const ty = parseFloatWithUnits( node.getAttribute( 'y' ) ); transform.translate( tx, ty ); @@ -1373,22 +1376,22 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( node.hasAttribute( 'transform' ) ) { - var transformsTexts = node.getAttribute( 'transform' ).split( ')' ); + const transformsTexts = node.getAttribute( 'transform' ).split( ')' ); - for ( var tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex -- ) { + for ( let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex -- ) { - var transformText = transformsTexts[ tIndex ].trim(); + const transformText = transformsTexts[ tIndex ].trim(); if ( transformText === '' ) continue; - var openParPos = transformText.indexOf( '(' ); - var closeParPos = transformText.length; + const openParPos = transformText.indexOf( '(' ); + const closeParPos = transformText.length; if ( openParPos > 0 && openParPos < closeParPos ) { - var transformType = transformText.substr( 0, openParPos ); + const transformType = transformText.substr( 0, openParPos ); - var array = parseFloats( transformText.substr( openParPos + 1, closeParPos - openParPos - 1 ) ); + const array = parseFloats( transformText.substr( openParPos + 1, closeParPos - openParPos - 1 ) ); currentTransform.identity(); @@ -1398,8 +1401,8 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( array.length >= 1 ) { - var tx = array[ 0 ]; - var ty = tx; + const tx = array[ 0 ]; + let ty = tx; if ( array.length >= 2 ) { @@ -1417,9 +1420,9 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( array.length >= 1 ) { - var angle = 0; - var cx = 0; - var cy = 0; + let angle = 0; + let cx = 0; + let cy = 0; // Angle angle = - array[ 0 ] * Math.PI / 180; @@ -1447,8 +1450,8 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { if ( array.length >= 1 ) { - var scaleX = array[ 0 ]; - var scaleY = scaleX; + const scaleX = array[ 0 ]; + let scaleY = scaleX; if ( array.length >= 2 ) { @@ -1528,18 +1531,18 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - var isRotated = isTransformRotated( m ); + const isRotated = isTransformRotated( m ); - var subPaths = path.subPaths; + const subPaths = path.subPaths; - for ( var i = 0, n = subPaths.length; i < n; i ++ ) { + for ( let i = 0, n = subPaths.length; i < n; i ++ ) { - var subPath = subPaths[ i ]; - var curves = subPath.curves; + const subPath = subPaths[ i ]; + const curves = subPath.curves; - for ( var j = 0; j < curves.length; j ++ ) { + for ( let j = 0; j < curves.length; j ++ ) { - var curve = curves[ j ]; + const curve = curves[ j ]; if ( curve.isLineCurve ) { @@ -1591,35 +1594,35 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function getTransformScaleX( m ) { - var te = m.elements; + const te = m.elements; return Math.sqrt( te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] ); } function getTransformScaleY( m ) { - var te = m.elements; + const te = m.elements; return Math.sqrt( te[ 3 ] * te[ 3 ] + te[ 4 ] * te[ 4 ] ); } // - var paths = []; - var stylesheets = {}; + const paths = []; + const stylesheets = {}; - var transformStack = []; + const transformStack = []; - var tempTransform0 = new Matrix3(); - var tempTransform1 = new Matrix3(); - var tempTransform2 = new Matrix3(); - var tempTransform3 = new Matrix3(); - var tempV2 = new Vector2(); - var tempV3 = new Vector3(); + const tempTransform0 = new Matrix3(); + const tempTransform1 = new Matrix3(); + const tempTransform2 = new Matrix3(); + const tempTransform3 = new Matrix3(); + const tempV2 = new Vector2(); + const tempV3 = new Vector3(); - var currentTransform = new Matrix3(); + const currentTransform = new Matrix3(); - var xml = new DOMParser().parseFromString( text, 'image/svg+xml' ); // application/xml + const xml = new DOMParser().parseFromString( text, 'image/svg+xml' ); // application/xml parseNode( xml.documentElement, { fill: '#000', @@ -1631,527 +1634,505 @@ SVGLoader.prototype = Object.assign( Object.create( Loader.prototype ), { strokeMiterLimit: 4 } ); - var data = { paths: paths, xml: xml.documentElement }; + const data = { paths: paths, xml: xml.documentElement }; // console.log( paths ); return data; } -} ); + static createShapes( shapePath ) { -SVGLoader.createShapes = function ( shapePath ) { + // Param shapePath: a shapepath as returned by the parse function of this class + // Returns Shape object - // Param shapePath: a shapepath as returned by the parse function of this class - // Returns Shape object + const BIGNUMBER = 999999999; - const BIGNUMBER = 999999999; + const IntersectionLocationType = { + ORIGIN: 0, + DESTINATION: 1, + BETWEEN: 2, + LEFT: 3, + RIGHT: 4, + BEHIND: 5, + BEYOND: 6 + }; - const IntersectionLocationType = { - ORIGIN: 0, - DESTINATION: 1, - BETWEEN: 2, - LEFT: 3, - RIGHT: 4, - BEHIND: 5, - BEYOND: 6 - }; + const classifyResult = { + loc: IntersectionLocationType.ORIGIN, + t: 0 + }; - const classifyResult = { - loc: IntersectionLocationType.ORIGIN, - t: 0 - }; + function findEdgeIntersection( a0, a1, b0, b1 ) { - function findEdgeIntersection( a0, a1, b0, b1 ) { + const x1 = a0.x; + const x2 = a1.x; + const x3 = b0.x; + const x4 = b1.x; + const y1 = a0.y; + const y2 = a1.y; + const y3 = b0.y; + const y4 = b1.y; + const nom1 = ( x4 - x3 ) * ( y1 - y3 ) - ( y4 - y3 ) * ( x1 - x3 ); + const nom2 = ( x2 - x1 ) * ( y1 - y3 ) - ( y2 - y1 ) * ( x1 - x3 ); + const denom = ( y4 - y3 ) * ( x2 - x1 ) - ( x4 - x3 ) * ( y2 - y1 ); + const t1 = nom1 / denom; + const t2 = nom2 / denom; - var x1 = a0.x; - var x2 = a1.x; - var x3 = b0.x; - var x4 = b1.x; - var y1 = a0.y; - var y2 = a1.y; - var y3 = b0.y; - var y4 = b1.y; - var nom1 = ( x4 - x3 ) * ( y1 - y3 ) - ( y4 - y3 ) * ( x1 - x3 ); - var nom2 = ( x2 - x1 ) * ( y1 - y3 ) - ( y2 - y1 ) * ( x1 - x3 ); - var denom = ( y4 - y3 ) * ( x2 - x1 ) - ( x4 - x3 ) * ( y2 - y1 ); - var t1 = nom1 / denom; - var t2 = nom2 / denom; + if ( ( ( denom === 0 ) && ( nom1 !== 0 ) ) || ( t1 <= 0 ) || ( t1 >= 1 ) || ( t2 < 0 ) || ( t2 > 1 ) ) { - if ( ( ( denom === 0 ) && ( nom1 !== 0 ) ) || ( t1 <= 0 ) || ( t1 >= 1 ) || ( t2 < 0 ) || ( t2 > 1 ) ) { + //1. lines are parallel or edges don't intersect - //1. lines are parallel or edges don't intersect + return null; - return null; + } else if ( ( nom1 === 0 ) && ( denom === 0 ) ) { - } else if ( ( nom1 === 0 ) && ( denom === 0 ) ) { + //2. lines are colinear - //2. lines are colinear + //check if endpoints of edge2 (b0-b1) lies on edge1 (a0-a1) + for ( let i = 0; i < 2; i ++ ) { - //check if endpoints of edge2 (b0-b1) lies on edge1 (a0-a1) - for ( var i = 0; i < 2; i ++ ) { + classifyPoint( i === 0 ? b0 : b1, a0, a1 ); + //find position of this endpoints relatively to edge1 + if ( classifyResult.loc == IntersectionLocationType.ORIGIN ) { - classifyPoint( i === 0 ? b0 : b1, a0, a1 ); - //find position of this endpoints relatively to edge1 - if ( classifyResult.loc == IntersectionLocationType.ORIGIN ) { + const point = ( i === 0 ? b0 : b1 ); + return { x: point.x, y: point.y, t: classifyResult.t }; - var point = ( i === 0 ? b0 : b1 ); - return { x: point.x, y: point.y, t: classifyResult.t }; + } else if ( classifyResult.loc == IntersectionLocationType.BETWEEN ) { - } else if ( classifyResult.loc == IntersectionLocationType.BETWEEN ) { + const x = + ( ( x1 + classifyResult.t * ( x2 - x1 ) ).toPrecision( 10 ) ); + const y = + ( ( y1 + classifyResult.t * ( y2 - y1 ) ).toPrecision( 10 ) ); + return { x: x, y: y, t: classifyResult.t, }; - var x = + ( ( x1 + classifyResult.t * ( x2 - x1 ) ).toPrecision( 10 ) ); - var y = + ( ( y1 + classifyResult.t * ( y2 - y1 ) ).toPrecision( 10 ) ); - return { x: x, y: y, t: classifyResult.t, }; + } } - } + return null; - return null; + } else { - } else { + //3. edges intersect - //3. edges intersect + for ( let i = 0; i < 2; i ++ ) { - for ( var i = 0; i < 2; i ++ ) { + classifyPoint( i === 0 ? b0 : b1, a0, a1 ); - classifyPoint( i === 0 ? b0 : b1, a0, a1 ); + if ( classifyResult.loc == IntersectionLocationType.ORIGIN ) { - if ( classifyResult.loc == IntersectionLocationType.ORIGIN ) { + const point = ( i === 0 ? b0 : b1 ); + return { x: point.x, y: point.y, t: classifyResult.t }; - var point = ( i === 0 ? b0 : b1 ); - return { x: point.x, y: point.y, t: classifyResult.t }; + } } - } + const x = + ( ( x1 + t1 * ( x2 - x1 ) ).toPrecision( 10 ) ); + const y = + ( ( y1 + t1 * ( y2 - y1 ) ).toPrecision( 10 ) ); + return { x: x, y: y, t: t1 }; - var x = + ( ( x1 + t1 * ( x2 - x1 ) ).toPrecision( 10 ) ); - var y = + ( ( y1 + t1 * ( y2 - y1 ) ).toPrecision( 10 ) ); - return { x: x, y: y, t: t1 }; + } } - } + function classifyPoint( p, edgeStart, edgeEnd ) { - function classifyPoint( p, edgeStart, edgeEnd ) { + const ax = edgeEnd.x - edgeStart.x; + const ay = edgeEnd.y - edgeStart.y; + const bx = p.x - edgeStart.x; + const by = p.y - edgeStart.y; + const sa = ax * by - bx * ay; - var ax = edgeEnd.x - edgeStart.x; - var ay = edgeEnd.y - edgeStart.y; - var bx = p.x - edgeStart.x; - var by = p.y - edgeStart.y; - var sa = ax * by - bx * ay; + if ( ( p.x === edgeStart.x ) && ( p.y === edgeStart.y ) ) { - if ( ( p.x === edgeStart.x ) && ( p.y === edgeStart.y ) ) { + classifyResult.loc = IntersectionLocationType.ORIGIN; + classifyResult.t = 0; + return; - classifyResult.loc = IntersectionLocationType.ORIGIN; - classifyResult.t = 0; - return; + } - } + if ( ( p.x === edgeEnd.x ) && ( p.y === edgeEnd.y ) ) { - if ( ( p.x === edgeEnd.x ) && ( p.y === edgeEnd.y ) ) { + classifyResult.loc = IntersectionLocationType.DESTINATION; + classifyResult.t = 1; + return; - classifyResult.loc = IntersectionLocationType.DESTINATION; - classifyResult.t = 1; - return; + } - } + if ( sa < - Number.EPSILON ) { - if ( sa < - Number.EPSILON ) { + classifyResult.loc = IntersectionLocationType.LEFT; + return; - classifyResult.loc = IntersectionLocationType.LEFT; - return; + } - } + if ( sa > Number.EPSILON ) { - if ( sa > Number.EPSILON ) { + classifyResult.loc = IntersectionLocationType.RIGHT; + return; - classifyResult.loc = IntersectionLocationType.RIGHT; - return; + } - } + if ( ( ( ax * bx ) < 0 ) || ( ( ay * by ) < 0 ) ) { - if ( ( ( ax * bx ) < 0 ) || ( ( ay * by ) < 0 ) ) { + classifyResult.loc = IntersectionLocationType.BEHIND; + return; - classifyResult.loc = IntersectionLocationType.BEHIND; - return; + } - } + if ( ( Math.sqrt( ax * ax + ay * ay ) ) < ( Math.sqrt( bx * bx + by * by ) ) ) { - if ( ( Math.sqrt( ax * ax + ay * ay ) ) < ( Math.sqrt( bx * bx + by * by ) ) ) { + classifyResult.loc = IntersectionLocationType.BEYOND; + return; - classifyResult.loc = IntersectionLocationType.BEYOND; - return; + } - } + let t; - var t; + if ( ax !== 0 ) { - if ( ax !== 0 ) { + t = bx / ax; - t = bx / ax; + } else { - } else { + t = by / ay; - t = by / ay; + } - } + classifyResult.loc = IntersectionLocationType.BETWEEN; + classifyResult.t = t; - classifyResult.loc = IntersectionLocationType.BETWEEN; - classifyResult.t = t; + } - } + function getIntersections( path1, path2 ) { - function getIntersections( path1, path2 ) { + const intersectionsRaw = []; + const intersections = []; - const intersectionsRaw = []; - const intersections = []; + for ( let index = 1; index < path1.length; index ++ ) { - for ( let index = 1; index < path1.length; index ++ ) { + const path1EdgeStart = path1[ index - 1 ]; + const path1EdgeEnd = path1[ index ]; - const path1EdgeStart = path1[ index - 1 ]; - const path1EdgeEnd = path1[ index ]; + for ( let index2 = 1; index2 < path2.length; index2 ++ ) { - for ( let index2 = 1; index2 < path2.length; index2 ++ ) { + const path2EdgeStart = path2[ index2 - 1 ]; + const path2EdgeEnd = path2[ index2 ]; - const path2EdgeStart = path2[ index2 - 1 ]; - const path2EdgeEnd = path2[ index2 ]; + const intersection = findEdgeIntersection( path1EdgeStart, path1EdgeEnd, path2EdgeStart, path2EdgeEnd ); - const intersection = findEdgeIntersection( path1EdgeStart, path1EdgeEnd, path2EdgeStart, path2EdgeEnd ); + if ( intersection !== null && intersectionsRaw.find( i => i.t <= intersection.t + Number.EPSILON && i.t >= intersection.t - Number.EPSILON ) === undefined ) { - if ( intersection !== null && intersectionsRaw.find( i => i.t <= intersection.t + Number.EPSILON && i.t >= intersection.t - Number.EPSILON ) === undefined ) { + intersectionsRaw.push( intersection ); + intersections.push( new Vector2( intersection.x, intersection.y ) ); - intersectionsRaw.push( intersection ); - intersections.push( new Vector2( intersection.x, intersection.y ) ); + } } } + return intersections; + } - return intersections; + function getScanlineIntersections( scanline, boundingBox, paths ) { - } + const center = new Vector2(); + boundingBox.getCenter( center ); - function getScanlineIntersections( scanline, boundingBox, paths ) { + const allIntersections = []; - const center = new Vector2(); - boundingBox.getCenter( center ); + paths.forEach( path => { - const allIntersections = []; + // check if the center of the bounding box is in the bounding box of the paths. + // this is a pruning method to limit the search of intersections in paths that can't envelop of the current path. + // if a path envelops another path. The center of that oter path, has to be inside the bounding box of the enveloping path. + if ( path.boundingBox.containsPoint( center ) ) { - paths.forEach( path => { + const intersections = getIntersections( scanline, path.points ); - // check if the center of the bounding box is in the bounding box of the paths. - // this is a pruning method to limit the search of intersections in paths that can't envelop of the current path. - // if a path envelops another path. The center of that oter path, has to be inside the bounding box of the enveloping path. - if ( path.boundingBox.containsPoint( center ) ) { + intersections.forEach( p => { - const intersections = getIntersections( scanline, path.points ); + allIntersections.push( { identifier: path.identifier, isCW: path.isCW, point: p } ); - intersections.forEach( p => { + } ); - allIntersections.push( { identifier: path.identifier, isCW: path.isCW, point: p } ); + } - } ); + } ); - } + allIntersections.sort( ( i1, i2 ) => { - } ); + return i1.point.x - i2.point.x; - allIntersections.sort( ( i1, i2 ) => { + } ); - return i1.point.x - i2.point.x; + return allIntersections; - } ); + } - return allIntersections; + function isHoleTo( simplePath, allPaths, scanlineMinX, scanlineMaxX, _fillRule ) { - } + if ( _fillRule === null || _fillRule === undefined || _fillRule === '' ) { - function isHoleTo( simplePath, allPaths, scanlineMinX, scanlineMaxX, _fillRule ) { + _fillRule = 'nonzero'; - if ( _fillRule === null || _fillRule === undefined || _fillRule === '' ) { + } - _fillRule = 'nonzero'; + const centerBoundingBox = new Vector2(); + simplePath.boundingBox.getCenter( centerBoundingBox ); - } + const scanline = [ new Vector2( scanlineMinX, centerBoundingBox.y ), new Vector2( scanlineMaxX, centerBoundingBox.y ) ]; - const centerBoundingBox = new Vector2(); - simplePath.boundingBox.getCenter( centerBoundingBox ); + const scanlineIntersections = getScanlineIntersections( scanline, simplePath.boundingBox, allPaths ); - const scanline = [ new Vector2( scanlineMinX, centerBoundingBox.y ), new Vector2( scanlineMaxX, centerBoundingBox.y ) ]; + scanlineIntersections.sort( ( i1, i2 ) => { - const scanlineIntersections = getScanlineIntersections( scanline, simplePath.boundingBox, allPaths ); + return i1.point.x - i2.point.x; - scanlineIntersections.sort( ( i1, i2 ) => { + } ); - return i1.point.x - i2.point.x; + const baseIntersections = []; + const otherIntersections = []; - } ); + scanlineIntersections.forEach( i => { - const baseIntersections = []; - const otherIntersections = []; + if ( i.identifier === simplePath.identifier ) { - scanlineIntersections.forEach( i => { + baseIntersections.push( i ); - if ( i.identifier === simplePath.identifier ) { + } else { - baseIntersections.push( i ); + otherIntersections.push( i ); - } else { + } - otherIntersections.push( i ); + } ); - } + const firstXOfPath = baseIntersections[ 0 ].point.x; - } ); + // build up the path hierarchy + const stack = []; + let i = 0; - const firstXOfPath = baseIntersections[ 0 ].point.x; + while ( i < otherIntersections.length && otherIntersections[ i ].point.x < firstXOfPath ) { - // build up the path hierarchy - const stack = []; - let i = 0; + if ( stack.length > 0 && stack[ stack.length - 1 ] === otherIntersections[ i ].identifier ) { - while ( i < otherIntersections.length && otherIntersections[ i ].point.x < firstXOfPath ) { + stack.pop(); - if ( stack.length > 0 && stack[ stack.length - 1 ] === otherIntersections[ i ].identifier ) { + } else { - stack.pop(); + stack.push( otherIntersections[ i ].identifier ); - } else { + } - stack.push( otherIntersections[ i ].identifier ); + i ++; } - i ++; - - } + stack.push( simplePath.identifier ); - stack.push( simplePath.identifier ); + if ( _fillRule === 'evenodd' ) { - if ( _fillRule === 'evenodd' ) { + const isHole = stack.length % 2 === 0 ? true : false; + const isHoleFor = stack[ stack.length - 2 ]; - const isHole = stack.length % 2 === 0 ? true : false; - const isHoleFor = stack[ stack.length - 2 ]; + return { identifier: simplePath.identifier, isHole: isHole, for: isHoleFor }; - return { identifier: simplePath.identifier, isHole: isHole, for: isHoleFor }; + } else if ( _fillRule === 'nonzero' ) { - } else if ( _fillRule === 'nonzero' ) { + // check if path is a hole by counting the amount of paths with alternating rotations it has to cross. + let isHole = true; + let isHoleFor = null; + let lastCWValue = null; - // check if path is a hole by counting the amount of paths with alternating rotations it has to cross. - let isHole = true; - let isHoleFor = null; - let lastCWValue = null; + for ( let i = 0; i < stack.length; i ++ ) { - for ( let i = 0; i < stack.length; i ++ ) { + const identifier = stack[ i ]; + if ( isHole ) { - const identifier = stack[ i ]; - if ( isHole ) { + lastCWValue = allPaths[ identifier ].isCW; + isHole = false; + isHoleFor = identifier; - lastCWValue = allPaths[ identifier ].isCW; - isHole = false; - isHoleFor = identifier; + } else if ( lastCWValue !== allPaths[ identifier ].isCW ) { - } else if ( lastCWValue !== allPaths[ identifier ].isCW ) { + lastCWValue = allPaths[ identifier ].isCW; + isHole = true; - lastCWValue = allPaths[ identifier ].isCW; - isHole = true; + } } - } + return { identifier: simplePath.identifier, isHole: isHole, for: isHoleFor }; - return { identifier: simplePath.identifier, isHole: isHole, for: isHoleFor }; + } else { - } else { + console.warn( 'fill-rule: "' + _fillRule + '" is currently not implemented.' ); - console.warn( 'fill-rule: "' + _fillRule + '" is currently not implemented.' ); + } } - } + // check for self intersecting paths + // TODO - // check for self intersecting paths - // TODO + // check intersecting paths + // TODO - // check intersecting paths - // TODO + // prepare paths for hole detection + let identifier = 0; - // prepare paths for hole detection - let identifier = 0; + let scanlineMinX = BIGNUMBER; + let scanlineMaxX = - BIGNUMBER; - let scanlineMinX = BIGNUMBER; - let scanlineMaxX = - BIGNUMBER; + let simplePaths = shapePath.subPaths.map( p => { - let simplePaths = shapePath.subPaths.map( p => { + const points = p.getPoints(); + let maxY = - BIGNUMBER; + let minY = BIGNUMBER; + let maxX = - BIGNUMBER; + let minX = BIGNUMBER; - const points = p.getPoints(); - let maxY = - BIGNUMBER; - let minY = BIGNUMBER; - let maxX = - BIGNUMBER; - let minX = BIGNUMBER; + //points.forEach(p => p.y *= -1); - //points.forEach(p => p.y *= -1); + for ( let i = 0; i < points.length; i ++ ) { - for ( let i = 0; i < points.length; i ++ ) { + const p = points[ i ]; - const p = points[ i ]; + if ( p.y > maxY ) { - if ( p.y > maxY ) { + maxY = p.y; - maxY = p.y; + } - } + if ( p.y < minY ) { - if ( p.y < minY ) { + minY = p.y; - minY = p.y; + } - } + if ( p.x > maxX ) { - if ( p.x > maxX ) { + maxX = p.x; - maxX = p.x; + } - } + if ( p.x < minX ) { - if ( p.x < minX ) { + minX = p.x; - minX = p.x; + } } - } - - // - if ( scanlineMaxX <= maxX ) { + // + if ( scanlineMaxX <= maxX ) { - scanlineMaxX = maxX + 1; + scanlineMaxX = maxX + 1; - } + } - if ( scanlineMinX >= minX ) { + if ( scanlineMinX >= minX ) { - scanlineMinX = minX - 1; + scanlineMinX = minX - 1; - } + } - return { points: points, isCW: ShapeUtils.isClockWise( points ), identifier: identifier ++, boundingBox: new Box2( new Vector2( minX, minY ), new Vector2( maxX, maxY ) ) }; + return { points: points, isCW: ShapeUtils.isClockWise( points ), identifier: identifier ++, boundingBox: new Box2( new Vector2( minX, minY ), new Vector2( maxX, maxY ) ) }; - } ); + } ); - simplePaths = simplePaths.filter( sp => sp.points.length > 0 ); + simplePaths = simplePaths.filter( sp => sp.points.length > 0 ); - // check if path is solid or a hole - const isAHole = simplePaths.map( p => isHoleTo( p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData.style.fillRule ) ); + // check if path is solid or a hole + const isAHole = simplePaths.map( p => isHoleTo( p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData.style.fillRule ) ); - const shapesToReturn = []; - simplePaths.forEach( p => { + const shapesToReturn = []; + simplePaths.forEach( p => { - const amIAHole = isAHole[ p.identifier ]; + const amIAHole = isAHole[ p.identifier ]; - if ( ! amIAHole.isHole ) { + if ( ! amIAHole.isHole ) { - const shape = new Shape( p.points ); - const holes = isAHole.filter( h => h.isHole && h.for === p.identifier ); - holes.forEach( h => { + const shape = new Shape( p.points ); + const holes = isAHole.filter( h => h.isHole && h.for === p.identifier ); + holes.forEach( h => { - const path = simplePaths[ h.identifier ]; - shape.holes.push( new Path( path.points ) ); + const path = simplePaths[ h.identifier ]; + shape.holes.push( new Path( path.points ) ); - } ); - shapesToReturn.push( shape ); + } ); + shapesToReturn.push( shape ); - } + } - } ); + } ); - return shapesToReturn; + return shapesToReturn; -}; + } -SVGLoader.getStrokeStyle = function ( width, color, lineJoin, lineCap, miterLimit ) { + static getStrokeStyle( width, color, lineJoin, lineCap, miterLimit ) { + + // Param width: Stroke width + // Param color: As returned by THREE.Color.getStyle() + // Param lineJoin: One of "round", "bevel", "miter" or "miter-limit" + // Param lineCap: One of "round", "square" or "butt" + // Param miterLimit: Maximum join length, in multiples of the "width" parameter (join is truncated if it exceeds that distance) + // Returns style object + + width = width !== undefined ? width : 1; + color = color !== undefined ? color : '#000'; + lineJoin = lineJoin !== undefined ? lineJoin : 'miter'; + lineCap = lineCap !== undefined ? lineCap : 'butt'; + miterLimit = miterLimit !== undefined ? miterLimit : 4; + + return { + strokeColor: color, + strokeWidth: width, + strokeLineJoin: lineJoin, + strokeLineCap: lineCap, + strokeMiterLimit: miterLimit + }; - // Param width: Stroke width - // Param color: As returned by THREE.Color.getStyle() - // Param lineJoin: One of "round", "bevel", "miter" or "miter-limit" - // Param lineCap: One of "round", "square" or "butt" - // Param miterLimit: Maximum join length, in multiples of the "width" parameter (join is truncated if it exceeds that distance) - // Returns style object + } - width = width !== undefined ? width : 1; - color = color !== undefined ? color : '#000'; - lineJoin = lineJoin !== undefined ? lineJoin : 'miter'; - lineCap = lineCap !== undefined ? lineCap : 'butt'; - miterLimit = miterLimit !== undefined ? miterLimit : 4; + static pointsToStroke( points, style, arcDivisions, minDistance ) { - return { - strokeColor: color, - strokeWidth: width, - strokeLineJoin: lineJoin, - strokeLineCap: lineCap, - strokeMiterLimit: miterLimit - }; + // Generates a stroke with some witdh around the given path. + // The path can be open or closed (last point equals to first point) + // Param points: Array of Vector2D (the path). Minimum 2 points. + // Param style: Object with SVG properties as returned by SVGLoader.getStrokeStyle(), or SVGLoader.parse() in the path.userData.style object + // Params arcDivisions: Arc divisions for round joins and endcaps. (Optional) + // Param minDistance: Points closer to this distance will be merged. (Optional) + // Returns BufferGeometry with stroke triangles (In plane z = 0). UV coordinates are generated ('u' along path. 'v' across it, from left to right) -}; + const vertices = []; + const normals = []; + const uvs = []; -SVGLoader.pointsToStroke = function ( points, style, arcDivisions, minDistance ) { + if ( SVGLoader.pointsToStrokeWithBuffers( points, style, arcDivisions, minDistance, vertices, normals, uvs ) === 0 ) { - // Generates a stroke with some witdh around the given path. - // The path can be open or closed (last point equals to first point) - // Param points: Array of Vector2D (the path). Minimum 2 points. - // Param style: Object with SVG properties as returned by SVGLoader.getStrokeStyle(), or SVGLoader.parse() in the path.userData.style object - // Params arcDivisions: Arc divisions for round joins and endcaps. (Optional) - // Param minDistance: Points closer to this distance will be merged. (Optional) - // Returns BufferGeometry with stroke triangles (In plane z = 0). UV coordinates are generated ('u' along path. 'v' across it, from left to right) + return null; - var vertices = []; - var normals = []; - var uvs = []; + } - if ( SVGLoader.pointsToStrokeWithBuffers( points, style, arcDivisions, minDistance, vertices, normals, uvs ) === 0 ) { + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - return null; + return geometry; } - var geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - return geometry; - -}; - -SVGLoader.pointsToStrokeWithBuffers = function () { - - var tempV2_1 = new Vector2(); - var tempV2_2 = new Vector2(); - var tempV2_3 = new Vector2(); - var tempV2_4 = new Vector2(); - var tempV2_5 = new Vector2(); - var tempV2_6 = new Vector2(); - var tempV2_7 = new Vector2(); - var lastPointL = new Vector2(); - var lastPointR = new Vector2(); - var point0L = new Vector2(); - var point0R = new Vector2(); - var currentPointL = new Vector2(); - var currentPointR = new Vector2(); - var nextPointL = new Vector2(); - var nextPointR = new Vector2(); - var innerPoint = new Vector2(); - var outerPoint = new Vector2(); - - return function ( points, style, arcDivisions, minDistance, vertices, normals, uvs, vertexOffset ) { + static pointsToStrokeWithBuffers( points, style, arcDivisions, minDistance, vertices, normals, uvs, vertexOffset ) { // This function can be called to update existing arrays or buffers. // Accepts same parameters as pointsToStroke, plus the buffers and optional offset. @@ -2160,6 +2141,24 @@ SVGLoader.pointsToStrokeWithBuffers = function () { // if 'vertices' parameter is undefined no triangles will be generated, but the returned vertices count will still be valid (useful to preallocate the buffers) // 'normals' and 'uvs' buffers are optional + const tempV2_1 = new Vector2(); + const tempV2_2 = new Vector2(); + const tempV2_3 = new Vector2(); + const tempV2_4 = new Vector2(); + const tempV2_5 = new Vector2(); + const tempV2_6 = new Vector2(); + const tempV2_7 = new Vector2(); + const lastPointL = new Vector2(); + const lastPointR = new Vector2(); + const point0L = new Vector2(); + const point0R = new Vector2(); + const currentPointL = new Vector2(); + const currentPointR = new Vector2(); + const nextPointL = new Vector2(); + const nextPointR = new Vector2(); + const innerPoint = new Vector2(); + const outerPoint = new Vector2(); + arcDivisions = arcDivisions !== undefined ? arcDivisions : 12; minDistance = minDistance !== undefined ? minDistance : 0.001; vertexOffset = vertexOffset !== undefined ? vertexOffset : 0; @@ -2167,29 +2166,29 @@ SVGLoader.pointsToStrokeWithBuffers = function () { // First ensure there are no duplicated points points = removeDuplicatedPoints( points ); - var numPoints = points.length; + const numPoints = points.length; if ( numPoints < 2 ) return 0; - var isClosed = points[ 0 ].equals( points[ numPoints - 1 ] ); + const isClosed = points[ 0 ].equals( points[ numPoints - 1 ] ); - var currentPoint; - var previousPoint = points[ 0 ]; - var nextPoint; + let currentPoint; + let previousPoint = points[ 0 ]; + let nextPoint; - var strokeWidth2 = style.strokeWidth / 2; + const strokeWidth2 = style.strokeWidth / 2; - var deltaU = 1 / ( numPoints - 1 ); - var u0 = 0; + const deltaU = 1 / ( numPoints - 1 ); + let u0 = 0, u1; - var innerSideModified; - var joinIsOnLeftSide; - var isMiter; - var initialJoinIsOnLeftSide = false; + let innerSideModified; + let joinIsOnLeftSide; + let isMiter; + let initialJoinIsOnLeftSide = false; - var numVertices = 0; - var currentCoordinate = vertexOffset * 3; - var currentCoordinateUV = vertexOffset * 2; + let numVertices = 0; + let currentCoordinate = vertexOffset * 3; + let currentCoordinateUV = vertexOffset * 2; // Get initial left and right stroke points getNormal( points[ 0 ], points[ 1 ], tempV2_1 ).multiplyScalar( strokeWidth2 ); @@ -2198,7 +2197,7 @@ SVGLoader.pointsToStrokeWithBuffers = function () { point0L.copy( lastPointL ); point0R.copy( lastPointR ); - for ( var iPoint = 1; iPoint < numPoints; iPoint ++ ) { + for ( let iPoint = 1; iPoint < numPoints; iPoint ++ ) { currentPoint = points[ iPoint ]; @@ -2219,14 +2218,14 @@ SVGLoader.pointsToStrokeWithBuffers = function () { } // Normal of previous segment in tempV2_1 - var normal1 = tempV2_1; + const normal1 = tempV2_1; getNormal( previousPoint, currentPoint, normal1 ); tempV2_3.copy( normal1 ).multiplyScalar( strokeWidth2 ); currentPointL.copy( currentPoint ).sub( tempV2_3 ); currentPointR.copy( currentPoint ).add( tempV2_3 ); - var u1 = u0 + deltaU; + u1 = u0 + deltaU; innerSideModified = false; @@ -2251,22 +2250,22 @@ SVGLoader.pointsToStrokeWithBuffers = function () { tempV2_3.subVectors( nextPoint, currentPoint ); tempV2_3.normalize(); - var dot = Math.abs( normal1.dot( tempV2_3 ) ); + const dot = Math.abs( normal1.dot( tempV2_3 ) ); // If path is straight, don't create join if ( dot !== 0 ) { // Compute inner and outer segment intersections - var miterSide = strokeWidth2 / dot; + const miterSide = strokeWidth2 / dot; tempV2_3.multiplyScalar( - miterSide ); tempV2_4.subVectors( currentPoint, previousPoint ); tempV2_5.copy( tempV2_4 ).setLength( miterSide ).add( tempV2_3 ); innerPoint.copy( tempV2_5 ).negate(); - var miterLength2 = tempV2_5.length(); - var segmentLengthPrev = tempV2_4.length(); + const miterLength2 = tempV2_5.length(); + const segmentLengthPrev = tempV2_4.length(); tempV2_4.divideScalar( segmentLengthPrev ); tempV2_6.subVectors( nextPoint, currentPoint ); - var segmentLengthNext = tempV2_6.length(); + const segmentLengthNext = tempV2_6.length(); tempV2_6.divideScalar( segmentLengthNext ); // Check that previous and next segments doesn't overlap with the innerPoint of intersection if ( tempV2_4.dot( innerPoint ) < segmentLengthPrev && tempV2_6.dot( innerPoint ) < segmentLengthNext ) { @@ -2334,7 +2333,7 @@ SVGLoader.pointsToStrokeWithBuffers = function () { case 'miter-clip': default: - var miterFraction = ( strokeWidth2 * style.strokeMiterLimit ) / miterLength2; + const miterFraction = ( strokeWidth2 * style.strokeMiterLimit ) / miterLength2; if ( miterFraction < 1 ) { @@ -2512,8 +2511,8 @@ SVGLoader.pointsToStrokeWithBuffers = function () { // Modify path first segment vertices to adjust to the segments inner and outer intersections - var lastOuter = outerPoint; - var lastInner = innerPoint; + let lastOuter = outerPoint; + let lastInner = innerPoint; if ( initialJoinIsOnLeftSide !== joinIsOnLeftSide ) { @@ -2610,15 +2609,15 @@ SVGLoader.pointsToStrokeWithBuffers = function () { tempV2_1.copy( p1 ).sub( center ).normalize(); tempV2_2.copy( p2 ).sub( center ).normalize(); - var angle = Math.PI; - var dot = tempV2_1.dot( tempV2_2 ); + let angle = Math.PI; + const dot = tempV2_1.dot( tempV2_2 ); if ( Math.abs( dot ) < 1 ) angle = Math.abs( Math.acos( dot ) ); angle /= arcDivisions; tempV2_3.copy( p1 ); - for ( var i = 0, il = arcDivisions - 1; i < il; i ++ ) { + for ( let i = 0, il = arcDivisions - 1; i < il; i ++ ) { tempV2_4.copy( tempV2_3 ).rotateAround( center, angle ); @@ -2814,7 +2813,7 @@ SVGLoader.pointsToStrokeWithBuffers = function () { tempV2_3.addVectors( tempV2_1, tempV2_2 ).add( center ); tempV2_4.subVectors( tempV2_2, tempV2_1 ).add( center ); - var vl = vertices.length; + const vl = vertices.length; // Modify already existing vertices if ( joinIsOnLeftSide ) { @@ -2850,8 +2849,8 @@ SVGLoader.pointsToStrokeWithBuffers = function () { // Creates a new array if necessary with duplicated points removed. // This does not remove duplicated initial and ending points of a closed path. - var dupPoints = false; - for ( var i = 1, n = points.length - 1; i < n; i ++ ) { + let dupPoints = false; + for ( let i = 1, n = points.length - 1; i < n; i ++ ) { if ( points[ i ].distanceTo( points[ i + 1 ] ) < minDistance ) { @@ -2864,10 +2863,10 @@ SVGLoader.pointsToStrokeWithBuffers = function () { if ( ! dupPoints ) return points; - var newPoints = []; + const newPoints = []; newPoints.push( points[ 0 ] ); - for ( var i = 1, n = points.length - 1; i < n; i ++ ) { + for ( let i = 1, n = points.length - 1; i < n; i ++ ) { if ( points[ i ].distanceTo( points[ i + 1 ] ) >= minDistance ) { @@ -2883,8 +2882,9 @@ SVGLoader.pointsToStrokeWithBuffers = function () { } - }; + } + -}(); +} export { SVGLoader }; diff --git a/examples/jsm/loaders/TDSLoader.js b/examples/jsm/loaders/TDSLoader.js index 1d75df4be011a5..65eb3515e11d57 100644 --- a/examples/jsm/loaders/TDSLoader.js +++ b/examples/jsm/loaders/TDSLoader.js @@ -23,23 +23,21 @@ import { * @constructor */ -var TDSLoader = function ( manager ) { +class TDSLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.debug = false; + super( manager ); - this.group = null; - this.position = 0; + this.debug = false; - this.materials = []; - this.meshes = []; - -}; + this.group = null; + this.position = 0; -TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + this.materials = []; + this.meshes = []; - constructor: TDSLoader, + } /** * Load 3ds file from url. @@ -50,13 +48,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Function} onProgress onProgress callback. * @param {Function} onError onError callback. */ - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( this.requestHeader ); @@ -86,7 +84,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } /** * Parse arraybuffer data and load 3ds file. @@ -96,7 +94,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {String} path Path for external resources. * @return {Group} Group loaded from 3ds file. */ - parse: function ( arraybuffer, path ) { + parse( arraybuffer, path ) { this.group = new Group(); this.position = 0; @@ -105,7 +103,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.readFile( arraybuffer, path ); - for ( var i = 0; i < this.meshes.length; i ++ ) { + for ( let i = 0; i < this.meshes.length; i ++ ) { this.group.add( this.meshes[ i ] ); @@ -113,7 +111,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return this.group; - }, + } /** * Decode file content to read 3ds data. @@ -122,20 +120,20 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {ArrayBuffer} arraybuffer Arraybuffer data to be loaded. * @param {String} path Path for external resources. */ - readFile: function ( arraybuffer, path ) { + readFile( arraybuffer, path ) { - var data = new DataView( arraybuffer ); - var chunk = this.readChunk( data ); + const data = new DataView( arraybuffer ); + const chunk = this.readChunk( data ); if ( chunk.id === MLIBMAGIC || chunk.id === CMAGIC || chunk.id === M3DMAGIC ) { - var next = this.nextChunk( data, chunk ); + let next = this.nextChunk( data, chunk ); while ( next !== 0 ) { if ( next === M3D_VERSION ) { - var version = this.readDWord( data ); + const version = this.readDWord( data ); this.debugMessage( '3DS file version: ' + version ); } else if ( next === MDATA ) { @@ -157,7 +155,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.debugMessage( 'Parsed ' + this.meshes.length + ' meshes' ); - }, + } /** * Read mesh data chunk. @@ -166,21 +164,21 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Dataview} data Dataview in use. * @param {String} path Path for external resources. */ - readMeshData: function ( data, path ) { + readMeshData( data, path ) { - var chunk = this.readChunk( data ); - var next = this.nextChunk( data, chunk ); + const chunk = this.readChunk( data ); + let next = this.nextChunk( data, chunk ); while ( next !== 0 ) { if ( next === MESH_VERSION ) { - var version = + this.readDWord( data ); + const version = + this.readDWord( data ); this.debugMessage( 'Mesh Version: ' + version ); } else if ( next === MASTER_SCALE ) { - var scale = this.readFloat( data ); + const scale = this.readFloat( data ); this.debugMessage( 'Master scale: ' + scale ); this.group.scale.set( scale, scale, scale ); @@ -206,7 +204,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - }, + } /** * Read named object chunk. @@ -214,19 +212,19 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @method readNamedObject * @param {Dataview} data Dataview in use. */ - readNamedObject: function ( data ) { + readNamedObject( data ) { - var chunk = this.readChunk( data ); - var name = this.readString( data, 64 ); + const chunk = this.readChunk( data ); + const name = this.readString( data, 64 ); chunk.cur = this.position; - var next = this.nextChunk( data, chunk ); + let next = this.nextChunk( data, chunk ); while ( next !== 0 ) { if ( next === N_TRI_OBJECT ) { this.resetPosition( data ); - var mesh = this.readMesh( data ); + const mesh = this.readMesh( data ); mesh.name = name; this.meshes.push( mesh ); @@ -242,7 +240,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.endChunk( chunk ); - }, + } /** * Read material data chunk and add it to the material list. @@ -251,11 +249,11 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Dataview} data Dataview in use. * @param {String} path Path for external resources. */ - readMaterialEntry: function ( data, path ) { + readMaterialEntry( data, path ) { - var chunk = this.readChunk( data ); - var next = this.nextChunk( data, chunk ); - var material = new MeshPhongMaterial(); + const chunk = this.readChunk( data ); + let next = this.nextChunk( data, chunk ); + const material = new MeshPhongMaterial(); while ( next !== 0 ) { @@ -271,7 +269,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( next === MAT_WIRE_SIZE ) { - var value = this.readByte( data ); + const value = this.readByte( data ); material.wireframeLinewidth = value; this.debugMessage( ' Wireframe Thickness: ' + value ); @@ -302,13 +300,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( next === MAT_SHININESS ) { - var shininess = this.readPercentage( data ); + const shininess = this.readPercentage( data ); material.shininess = shininess * 100; this.debugMessage( ' Shininess : ' + shininess ); } else if ( next === MAT_TRANSPARENCY ) { - var transparency = this.readPercentage( data ); + const transparency = this.readPercentage( data ); material.opacity = 1 - transparency; this.debugMessage( ' Transparency : ' + transparency ); material.transparent = material.opacity < 1 ? true : false; @@ -351,7 +349,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.materials[ material.name ] = material; - }, + } /** * Read mesh data chunk. @@ -360,31 +358,30 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Dataview} data Dataview in use. * @return {Mesh} The parsed mesh. */ - readMesh: function ( data ) { + readMesh( data ) { - var chunk = this.readChunk( data ); - var next = this.nextChunk( data, chunk ); + const chunk = this.readChunk( data ); + let next = this.nextChunk( data, chunk ); - var geometry = new BufferGeometry(); - var uvs = []; + const geometry = new BufferGeometry(); - var material = new MeshPhongMaterial(); - var mesh = new Mesh( geometry, material ); + const material = new MeshPhongMaterial(); + const mesh = new Mesh( geometry, material ); mesh.name = 'mesh'; while ( next !== 0 ) { if ( next === POINT_ARRAY ) { - var points = this.readWord( data ); + const points = this.readWord( data ); this.debugMessage( ' Vertex: ' + points ); //BufferGeometry - var vertices = []; + const vertices = []; - for ( var i = 0; i < points; i ++ ) { + for ( let i = 0; i < points; i ++ ) { vertices.push( this.readFloat( data ) ); vertices.push( this.readFloat( data ) ); @@ -401,15 +398,15 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( next === TEX_VERTS ) { - var texels = this.readWord( data ); + const texels = this.readWord( data ); this.debugMessage( ' UV: ' + texels ); //BufferGeometry - var uvs = []; + const uvs = []; - for ( var i = 0; i < texels; i ++ ) { + for ( let i = 0; i < texels; i ++ ) { uvs.push( this.readFloat( data ) ); uvs.push( this.readFloat( data ) ); @@ -423,14 +420,14 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.debugMessage( ' Tranformation Matrix (TODO)' ); - var values = []; - for ( var i = 0; i < 12; i ++ ) { + const values = []; + for ( let i = 0; i < 12; i ++ ) { values[ i ] = this.readFloat( data ); } - var matrix = new Matrix4(); + const matrix = new Matrix4(); //X Line matrix.elements[ 0 ] = values[ 0 ]; @@ -458,7 +455,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { matrix.transpose(); - var inverse = new Matrix4(); + const inverse = new Matrix4(); inverse.copy( matrix ).invert(); geometry.applyMatrix4( inverse ); @@ -480,7 +477,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return mesh; - }, + } /** * Read face array data chunk. @@ -489,16 +486,16 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Dataview} data Dataview in use. * @param {Mesh} mesh Mesh to be filled with the data read. */ - readFaceArray: function ( data, mesh ) { + readFaceArray( data, mesh ) { - var chunk = this.readChunk( data ); - var faces = this.readWord( data ); + const chunk = this.readChunk( data ); + const faces = this.readWord( data ); this.debugMessage( ' Faces: ' + faces ); - var index = []; + const index = []; - for ( var i = 0; i < faces; ++ i ) { + for ( let i = 0; i < faces; ++ i ) { index.push( this.readWord( data ), this.readWord( data ), this.readWord( data ) ); @@ -510,12 +507,12 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { //The rest of the FACE_ARRAY chunk is subchunks - var materialIndex = 0; - var start = 0; + let materialIndex = 0; + let start = 0; while ( this.position < chunk.end ) { - var subchunk = this.readChunk( data ); + const subchunk = this.readChunk( data ); if ( subchunk.id === MSH_MAT_GROUP ) { @@ -523,15 +520,15 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.resetPosition( data ); - var group = this.readMaterialGroup( data ); - var count = group.index.length * 3; // assuming successive indices + const group = this.readMaterialGroup( data ); + const count = group.index.length * 3; // assuming successive indices mesh.geometry.addGroup( start, count, materialIndex ); start += count; materialIndex ++; - var material = this.materials[ group.name ]; + const material = this.materials[ group.name ]; if ( Array.isArray( mesh.material ) === false ) mesh.material = []; @@ -555,7 +552,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.endChunk( chunk ); - }, + } /** * Read texture map data chunk. @@ -565,20 +562,20 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {String} path Path for external resources. * @return {Texture} Texture read from this data chunk. */ - readMap: function ( data, path ) { + readMap( data, path ) { - var chunk = this.readChunk( data ); - var next = this.nextChunk( data, chunk ); - var texture = {}; + const chunk = this.readChunk( data ); + let next = this.nextChunk( data, chunk ); + let texture = {}; - var loader = new TextureLoader( this.manager ); + const loader = new TextureLoader( this.manager ); loader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); while ( next !== 0 ) { if ( next === MAT_MAPNAME ) { - var name = this.readString( data, 128 ); + const name = this.readString( data, 128 ); texture = loader.load( name ); this.debugMessage( ' File: ' + path + name ); @@ -617,7 +614,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return texture; - }, + } /** * Read material group data chunk. @@ -626,17 +623,17 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Dataview} data Dataview in use. * @return {Object} Object with name and index of the object. */ - readMaterialGroup: function ( data ) { + readMaterialGroup( data ) { this.readChunk( data ); - var name = this.readString( data, 64 ); - var numFaces = this.readWord( data ); + const name = this.readString( data, 64 ); + const numFaces = this.readWord( data ); this.debugMessage( ' Name: ' + name ); this.debugMessage( ' Faces: ' + numFaces ); - var index = []; - for ( var i = 0; i < numFaces; ++ i ) { + const index = []; + for ( let i = 0; i < numFaces; ++ i ) { index.push( this.readWord( data ) ); @@ -644,7 +641,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return { name: name, index: index }; - }, + } /** * Read a color value. @@ -653,16 +650,16 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview. * @return {Color} Color value read.. */ - readColor: function ( data ) { + readColor( data ) { - var chunk = this.readChunk( data ); - var color = new Color(); + const chunk = this.readChunk( data ); + const color = new Color(); if ( chunk.id === COLOR_24 || chunk.id === LIN_COLOR_24 ) { - var r = this.readByte( data ); - var g = this.readByte( data ); - var b = this.readByte( data ); + const r = this.readByte( data ); + const g = this.readByte( data ); + const b = this.readByte( data ); color.setRGB( r / 255, g / 255, b / 255 ); @@ -670,9 +667,9 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } else if ( chunk.id === COLOR_F || chunk.id === LIN_COLOR_F ) { - var r = this.readFloat( data ); - var g = this.readFloat( data ); - var b = this.readFloat( data ); + const r = this.readFloat( data ); + const g = this.readFloat( data ); + const b = this.readFloat( data ); color.setRGB( r, g, b ); @@ -687,7 +684,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { this.endChunk( chunk ); return color; - }, + } /** * Read next chunk of data. @@ -696,9 +693,9 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview. * @return {Object} Chunk of data read. */ - readChunk: function ( data ) { + readChunk( data ) { - var chunk = {}; + const chunk = {}; chunk.cur = this.position; chunk.id = this.readWord( data ); @@ -708,7 +705,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return chunk; - }, + } /** * Set position to the end of the current chunk of data. @@ -716,11 +713,11 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @method endChunk * @param {Object} chunk Data chunk. */ - endChunk: function ( chunk ) { + endChunk( chunk ) { this.position = chunk.end; - }, + } /** * Move to the next data chunk. @@ -729,7 +726,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview. * @param {Object} chunk Data chunk. */ - nextChunk: function ( data, chunk ) { + nextChunk( data, chunk ) { if ( chunk.cur >= chunk.end ) { @@ -741,7 +738,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { try { - var next = this.readChunk( data ); + const next = this.readChunk( data ); chunk.cur += next.size; return next.id; @@ -752,18 +749,18 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - }, + } /** * Reset dataview position. * * @method resetPosition */ - resetPosition: function () { + resetPosition() { this.position -= 6; - }, + } /** * Read byte value. @@ -772,13 +769,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readByte: function ( data ) { + readByte( data ) { - var v = data.getUint8( this.position, true ); + const v = data.getUint8( this.position, true ); this.position += 1; return v; - }, + } /** * Read 32 bit float value. @@ -787,11 +784,11 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readFloat: function ( data ) { + readFloat( data ) { try { - var v = data.getFloat32( this.position, true ); + const v = data.getFloat32( this.position, true ); this.position += 4; return v; @@ -801,7 +798,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } - }, + } /** * Read 32 bit signed integer value. @@ -810,13 +807,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readInt: function ( data ) { + readInt( data ) { - var v = data.getInt32( this.position, true ); + const v = data.getInt32( this.position, true ); this.position += 4; return v; - }, + } /** * Read 16 bit signed integer value. @@ -825,13 +822,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readShort: function ( data ) { + readShort( data ) { - var v = data.getInt16( this.position, true ); + const v = data.getInt16( this.position, true ); this.position += 2; return v; - }, + } /** * Read 64 bit unsigned integer value. @@ -840,13 +837,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readDWord: function ( data ) { + readDWord( data ) { - var v = data.getUint32( this.position, true ); + const v = data.getUint32( this.position, true ); this.position += 4; return v; - }, + } /** * Read 32 bit unsigned integer value. @@ -855,13 +852,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readWord: function ( data ) { + readWord( data ) { - var v = data.getUint16( this.position, true ); + const v = data.getUint16( this.position, true ); this.position += 2; return v; - }, + } /** * Read string value. @@ -871,13 +868,13 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {Number} maxLength Max size of the string to be read. * @return {String} Data read from the dataview. */ - readString: function ( data, maxLength ) { + readString( data, maxLength ) { - var s = ''; + let s = ''; - for ( var i = 0; i < maxLength; i ++ ) { + for ( let i = 0; i < maxLength; i ++ ) { - var c = this.readByte( data ); + const c = this.readByte( data ); if ( ! c ) { break; @@ -890,7 +887,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return s; - }, + } /** * Read percentage value. @@ -899,10 +896,10 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @param {DataView} data Dataview to read data from. * @return {Number} Data read from the dataview. */ - readPercentage: function ( data ) { + readPercentage( data ) { - var chunk = this.readChunk( data ); - var value; + const chunk = this.readChunk( data ); + let value; switch ( chunk.id ) { @@ -923,7 +920,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { return value; - }, + } /** * Print debug message to the console. @@ -933,7 +930,7 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { * @method debugMessage * @param {Object} message Debug message to print to the console. */ - debugMessage: function ( message ) { + debugMessage( message ) { if ( this.debug ) { @@ -943,224 +940,224 @@ TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); - -// var NULL_CHUNK = 0x0000; -var M3DMAGIC = 0x4D4D; -// var SMAGIC = 0x2D2D; -// var LMAGIC = 0x2D3D; -var MLIBMAGIC = 0x3DAA; -// var MATMAGIC = 0x3DFF; -var CMAGIC = 0xC23D; -var M3D_VERSION = 0x0002; -// var M3D_KFVERSION = 0x0005; -var COLOR_F = 0x0010; -var COLOR_24 = 0x0011; -var LIN_COLOR_24 = 0x0012; -var LIN_COLOR_F = 0x0013; -var INT_PERCENTAGE = 0x0030; -var FLOAT_PERCENTAGE = 0x0031; -var MDATA = 0x3D3D; -var MESH_VERSION = 0x3D3E; -var MASTER_SCALE = 0x0100; -// var LO_SHADOW_BIAS = 0x1400; -// var HI_SHADOW_BIAS = 0x1410; -// var SHADOW_MAP_SIZE = 0x1420; -// var SHADOW_SAMPLES = 0x1430; -// var SHADOW_RANGE = 0x1440; -// var SHADOW_FILTER = 0x1450; -// var RAY_BIAS = 0x1460; -// var O_CONSTS = 0x1500; -// var AMBIENT_LIGHT = 0x2100; -// var BIT_MAP = 0x1100; -// var SOLID_BGND = 0x1200; -// var V_GRADIENT = 0x1300; -// var USE_BIT_MAP = 0x1101; -// var USE_SOLID_BGND = 0x1201; -// var USE_V_GRADIENT = 0x1301; -// var FOG = 0x2200; -// var FOG_BGND = 0x2210; -// var LAYER_FOG = 0x2302; -// var DISTANCE_CUE = 0x2300; -// var DCUE_BGND = 0x2310; -// var USE_FOG = 0x2201; -// var USE_LAYER_FOG = 0x2303; -// var USE_DISTANCE_CUE = 0x2301; -var MAT_ENTRY = 0xAFFF; -var MAT_NAME = 0xA000; -var MAT_AMBIENT = 0xA010; -var MAT_DIFFUSE = 0xA020; -var MAT_SPECULAR = 0xA030; -var MAT_SHININESS = 0xA040; -// var MAT_SHIN2PCT = 0xA041; -var MAT_TRANSPARENCY = 0xA050; -// var MAT_XPFALL = 0xA052; -// var MAT_USE_XPFALL = 0xA240; -// var MAT_REFBLUR = 0xA053; -// var MAT_SHADING = 0xA100; -// var MAT_USE_REFBLUR = 0xA250; -// var MAT_SELF_ILLUM = 0xA084; -var MAT_TWO_SIDE = 0xA081; -// var MAT_DECAL = 0xA082; -var MAT_ADDITIVE = 0xA083; -var MAT_WIRE = 0xA085; -// var MAT_FACEMAP = 0xA088; -// var MAT_TRANSFALLOFF_IN = 0xA08A; -// var MAT_PHONGSOFT = 0xA08C; -// var MAT_WIREABS = 0xA08E; -var MAT_WIRE_SIZE = 0xA087; -var MAT_TEXMAP = 0xA200; -// var MAT_SXP_TEXT_DATA = 0xA320; -// var MAT_TEXMASK = 0xA33E; -// var MAT_SXP_TEXTMASK_DATA = 0xA32A; -// var MAT_TEX2MAP = 0xA33A; -// var MAT_SXP_TEXT2_DATA = 0xA321; -// var MAT_TEX2MASK = 0xA340; -// var MAT_SXP_TEXT2MASK_DATA = 0xA32C; -var MAT_OPACMAP = 0xA210; -// var MAT_SXP_OPAC_DATA = 0xA322; -// var MAT_OPACMASK = 0xA342; -// var MAT_SXP_OPACMASK_DATA = 0xA32E; -var MAT_BUMPMAP = 0xA230; -// var MAT_SXP_BUMP_DATA = 0xA324; -// var MAT_BUMPMASK = 0xA344; -// var MAT_SXP_BUMPMASK_DATA = 0xA330; -var MAT_SPECMAP = 0xA204; -// var MAT_SXP_SPEC_DATA = 0xA325; -// var MAT_SPECMASK = 0xA348; -// var MAT_SXP_SPECMASK_DATA = 0xA332; -// var MAT_SHINMAP = 0xA33C; -// var MAT_SXP_SHIN_DATA = 0xA326; -// var MAT_SHINMASK = 0xA346; -// var MAT_SXP_SHINMASK_DATA = 0xA334; -// var MAT_SELFIMAP = 0xA33D; -// var MAT_SXP_SELFI_DATA = 0xA328; -// var MAT_SELFIMASK = 0xA34A; -// var MAT_SXP_SELFIMASK_DATA = 0xA336; -// var MAT_REFLMAP = 0xA220; -// var MAT_REFLMASK = 0xA34C; -// var MAT_SXP_REFLMASK_DATA = 0xA338; -// var MAT_ACUBIC = 0xA310; -var MAT_MAPNAME = 0xA300; -// var MAT_MAP_TILING = 0xA351; -// var MAT_MAP_TEXBLUR = 0xA353; -var MAT_MAP_USCALE = 0xA354; -var MAT_MAP_VSCALE = 0xA356; -var MAT_MAP_UOFFSET = 0xA358; -var MAT_MAP_VOFFSET = 0xA35A; -// var MAT_MAP_ANG = 0xA35C; -// var MAT_MAP_COL1 = 0xA360; -// var MAT_MAP_COL2 = 0xA362; -// var MAT_MAP_RCOL = 0xA364; -// var MAT_MAP_GCOL = 0xA366; -// var MAT_MAP_BCOL = 0xA368; -var NAMED_OBJECT = 0x4000; -// var N_DIRECT_LIGHT = 0x4600; -// var DL_OFF = 0x4620; -// var DL_OUTER_RANGE = 0x465A; -// var DL_INNER_RANGE = 0x4659; -// var DL_MULTIPLIER = 0x465B; -// var DL_EXCLUDE = 0x4654; -// var DL_ATTENUATE = 0x4625; -// var DL_SPOTLIGHT = 0x4610; -// var DL_SPOT_ROLL = 0x4656; -// var DL_SHADOWED = 0x4630; -// var DL_LOCAL_SHADOW2 = 0x4641; -// var DL_SEE_CONE = 0x4650; -// var DL_SPOT_RECTANGULAR = 0x4651; -// var DL_SPOT_ASPECT = 0x4657; -// var DL_SPOT_PROJECTOR = 0x4653; -// var DL_SPOT_OVERSHOOT = 0x4652; -// var DL_RAY_BIAS = 0x4658; -// var DL_RAYSHAD = 0x4627; -// var N_CAMERA = 0x4700; -// var CAM_SEE_CONE = 0x4710; -// var CAM_RANGES = 0x4720; -// var OBJ_HIDDEN = 0x4010; -// var OBJ_VIS_LOFTER = 0x4011; -// var OBJ_DOESNT_CAST = 0x4012; -// var OBJ_DONT_RECVSHADOW = 0x4017; -// var OBJ_MATTE = 0x4013; -// var OBJ_FAST = 0x4014; -// var OBJ_PROCEDURAL = 0x4015; -// var OBJ_FROZEN = 0x4016; -var N_TRI_OBJECT = 0x4100; -var POINT_ARRAY = 0x4110; -// var POINT_FLAG_ARRAY = 0x4111; -var FACE_ARRAY = 0x4120; -var MSH_MAT_GROUP = 0x4130; -// var SMOOTH_GROUP = 0x4150; -// var MSH_BOXMAP = 0x4190; -var TEX_VERTS = 0x4140; -var MESH_MATRIX = 0x4160; -// var MESH_COLOR = 0x4165; -// var MESH_TEXTURE_INFO = 0x4170; -// var KFDATA = 0xB000; -// var KFHDR = 0xB00A; -// var KFSEG = 0xB008; -// var KFCURTIME = 0xB009; -// var AMBIENT_NODE_TAG = 0xB001; -// var OBJECT_NODE_TAG = 0xB002; -// var CAMERA_NODE_TAG = 0xB003; -// var TARGET_NODE_TAG = 0xB004; -// var LIGHT_NODE_TAG = 0xB005; -// var L_TARGET_NODE_TAG = 0xB006; -// var SPOTLIGHT_NODE_TAG = 0xB007; -// var NODE_ID = 0xB030; -// var NODE_HDR = 0xB010; -// var PIVOT = 0xB013; -// var INSTANCE_NAME = 0xB011; -// var MORPH_SMOOTH = 0xB015; -// var BOUNDBOX = 0xB014; -// var POS_TRACK_TAG = 0xB020; -// var COL_TRACK_TAG = 0xB025; -// var ROT_TRACK_TAG = 0xB021; -// var SCL_TRACK_TAG = 0xB022; -// var MORPH_TRACK_TAG = 0xB026; -// var FOV_TRACK_TAG = 0xB023; -// var ROLL_TRACK_TAG = 0xB024; -// var HOT_TRACK_TAG = 0xB027; -// var FALL_TRACK_TAG = 0xB028; -// var HIDE_TRACK_TAG = 0xB029; -// var POLY_2D = 0x5000; -// var SHAPE_OK = 0x5010; -// var SHAPE_NOT_OK = 0x5011; -// var SHAPE_HOOK = 0x5020; -// var PATH_3D = 0x6000; -// var PATH_MATRIX = 0x6005; -// var SHAPE_2D = 0x6010; -// var M_SCALE = 0x6020; -// var M_TWIST = 0x6030; -// var M_TEETER = 0x6040; -// var M_FIT = 0x6050; -// var M_BEVEL = 0x6060; -// var XZ_CURVE = 0x6070; -// var YZ_CURVE = 0x6080; -// var INTERPCT = 0x6090; -// var DEFORM_LIMIT = 0x60A0; -// var USE_CONTOUR = 0x6100; -// var USE_TWEEN = 0x6110; -// var USE_SCALE = 0x6120; -// var USE_TWIST = 0x6130; -// var USE_TEETER = 0x6140; -// var USE_FIT = 0x6150; -// var USE_BEVEL = 0x6160; -// var DEFAULT_VIEW = 0x3000; -// var VIEW_TOP = 0x3010; -// var VIEW_BOTTOM = 0x3020; -// var VIEW_LEFT = 0x3030; -// var VIEW_RIGHT = 0x3040; -// var VIEW_FRONT = 0x3050; -// var VIEW_BACK = 0x3060; -// var VIEW_USER = 0x3070; -// var VIEW_CAMERA = 0x3080; -// var VIEW_WINDOW = 0x3090; -// var VIEWPORT_LAYOUT_OLD = 0x7000; -// var VIEWPORT_DATA_OLD = 0x7010; -// var VIEWPORT_LAYOUT = 0x7001; -// var VIEWPORT_DATA = 0x7011; -// var VIEWPORT_DATA_3 = 0x7012; -// var VIEWPORT_SIZE = 0x7020; -// var NETWORK_VIEW = 0x7030; +} + +// const NULL_CHUNK = 0x0000; +const M3DMAGIC = 0x4D4D; +// const SMAGIC = 0x2D2D; +// const LMAGIC = 0x2D3D; +const MLIBMAGIC = 0x3DAA; +// const MATMAGIC = 0x3DFF; +const CMAGIC = 0xC23D; +const M3D_VERSION = 0x0002; +// const M3D_KFVERSION = 0x0005; +const COLOR_F = 0x0010; +const COLOR_24 = 0x0011; +const LIN_COLOR_24 = 0x0012; +const LIN_COLOR_F = 0x0013; +const INT_PERCENTAGE = 0x0030; +const FLOAT_PERCENTAGE = 0x0031; +const MDATA = 0x3D3D; +const MESH_VERSION = 0x3D3E; +const MASTER_SCALE = 0x0100; +// const LO_SHADOW_BIAS = 0x1400; +// const HI_SHADOW_BIAS = 0x1410; +// const SHADOW_MAP_SIZE = 0x1420; +// const SHADOW_SAMPLES = 0x1430; +// const SHADOW_RANGE = 0x1440; +// const SHADOW_FILTER = 0x1450; +// const RAY_BIAS = 0x1460; +// const O_CONSTS = 0x1500; +// const AMBIENT_LIGHT = 0x2100; +// const BIT_MAP = 0x1100; +// const SOLID_BGND = 0x1200; +// const V_GRADIENT = 0x1300; +// const USE_BIT_MAP = 0x1101; +// const USE_SOLID_BGND = 0x1201; +// const USE_V_GRADIENT = 0x1301; +// const FOG = 0x2200; +// const FOG_BGND = 0x2210; +// const LAYER_FOG = 0x2302; +// const DISTANCE_CUE = 0x2300; +// const DCUE_BGND = 0x2310; +// const USE_FOG = 0x2201; +// const USE_LAYER_FOG = 0x2303; +// const USE_DISTANCE_CUE = 0x2301; +const MAT_ENTRY = 0xAFFF; +const MAT_NAME = 0xA000; +const MAT_AMBIENT = 0xA010; +const MAT_DIFFUSE = 0xA020; +const MAT_SPECULAR = 0xA030; +const MAT_SHININESS = 0xA040; +// const MAT_SHIN2PCT = 0xA041; +const MAT_TRANSPARENCY = 0xA050; +// const MAT_XPFALL = 0xA052; +// const MAT_USE_XPFALL = 0xA240; +// const MAT_REFBLUR = 0xA053; +// const MAT_SHADING = 0xA100; +// const MAT_USE_REFBLUR = 0xA250; +// const MAT_SELF_ILLUM = 0xA084; +const MAT_TWO_SIDE = 0xA081; +// const MAT_DECAL = 0xA082; +const MAT_ADDITIVE = 0xA083; +const MAT_WIRE = 0xA085; +// const MAT_FACEMAP = 0xA088; +// const MAT_TRANSFALLOFF_IN = 0xA08A; +// const MAT_PHONGSOFT = 0xA08C; +// const MAT_WIREABS = 0xA08E; +const MAT_WIRE_SIZE = 0xA087; +const MAT_TEXMAP = 0xA200; +// const MAT_SXP_TEXT_DATA = 0xA320; +// const MAT_TEXMASK = 0xA33E; +// const MAT_SXP_TEXTMASK_DATA = 0xA32A; +// const MAT_TEX2MAP = 0xA33A; +// const MAT_SXP_TEXT2_DATA = 0xA321; +// const MAT_TEX2MASK = 0xA340; +// const MAT_SXP_TEXT2MASK_DATA = 0xA32C; +const MAT_OPACMAP = 0xA210; +// const MAT_SXP_OPAC_DATA = 0xA322; +// const MAT_OPACMASK = 0xA342; +// const MAT_SXP_OPACMASK_DATA = 0xA32E; +const MAT_BUMPMAP = 0xA230; +// const MAT_SXP_BUMP_DATA = 0xA324; +// const MAT_BUMPMASK = 0xA344; +// const MAT_SXP_BUMPMASK_DATA = 0xA330; +const MAT_SPECMAP = 0xA204; +// const MAT_SXP_SPEC_DATA = 0xA325; +// const MAT_SPECMASK = 0xA348; +// const MAT_SXP_SPECMASK_DATA = 0xA332; +// const MAT_SHINMAP = 0xA33C; +// const MAT_SXP_SHIN_DATA = 0xA326; +// const MAT_SHINMASK = 0xA346; +// const MAT_SXP_SHINMASK_DATA = 0xA334; +// const MAT_SELFIMAP = 0xA33D; +// const MAT_SXP_SELFI_DATA = 0xA328; +// const MAT_SELFIMASK = 0xA34A; +// const MAT_SXP_SELFIMASK_DATA = 0xA336; +// const MAT_REFLMAP = 0xA220; +// const MAT_REFLMASK = 0xA34C; +// const MAT_SXP_REFLMASK_DATA = 0xA338; +// const MAT_ACUBIC = 0xA310; +const MAT_MAPNAME = 0xA300; +// const MAT_MAP_TILING = 0xA351; +// const MAT_MAP_TEXBLUR = 0xA353; +const MAT_MAP_USCALE = 0xA354; +const MAT_MAP_VSCALE = 0xA356; +const MAT_MAP_UOFFSET = 0xA358; +const MAT_MAP_VOFFSET = 0xA35A; +// const MAT_MAP_ANG = 0xA35C; +// const MAT_MAP_COL1 = 0xA360; +// const MAT_MAP_COL2 = 0xA362; +// const MAT_MAP_RCOL = 0xA364; +// const MAT_MAP_GCOL = 0xA366; +// const MAT_MAP_BCOL = 0xA368; +const NAMED_OBJECT = 0x4000; +// const N_DIRECT_LIGHT = 0x4600; +// const DL_OFF = 0x4620; +// const DL_OUTER_RANGE = 0x465A; +// const DL_INNER_RANGE = 0x4659; +// const DL_MULTIPLIER = 0x465B; +// const DL_EXCLUDE = 0x4654; +// const DL_ATTENUATE = 0x4625; +// const DL_SPOTLIGHT = 0x4610; +// const DL_SPOT_ROLL = 0x4656; +// const DL_SHADOWED = 0x4630; +// const DL_LOCAL_SHADOW2 = 0x4641; +// const DL_SEE_CONE = 0x4650; +// const DL_SPOT_RECTANGULAR = 0x4651; +// const DL_SPOT_ASPECT = 0x4657; +// const DL_SPOT_PROJECTOR = 0x4653; +// const DL_SPOT_OVERSHOOT = 0x4652; +// const DL_RAY_BIAS = 0x4658; +// const DL_RAYSHAD = 0x4627; +// const N_CAMERA = 0x4700; +// const CAM_SEE_CONE = 0x4710; +// const CAM_RANGES = 0x4720; +// const OBJ_HIDDEN = 0x4010; +// const OBJ_VIS_LOFTER = 0x4011; +// const OBJ_DOESNT_CAST = 0x4012; +// const OBJ_DONT_RECVSHADOW = 0x4017; +// const OBJ_MATTE = 0x4013; +// const OBJ_FAST = 0x4014; +// const OBJ_PROCEDURAL = 0x4015; +// const OBJ_FROZEN = 0x4016; +const N_TRI_OBJECT = 0x4100; +const POINT_ARRAY = 0x4110; +// const POINT_FLAG_ARRAY = 0x4111; +const FACE_ARRAY = 0x4120; +const MSH_MAT_GROUP = 0x4130; +// const SMOOTH_GROUP = 0x4150; +// const MSH_BOXMAP = 0x4190; +const TEX_VERTS = 0x4140; +const MESH_MATRIX = 0x4160; +// const MESH_COLOR = 0x4165; +// const MESH_TEXTURE_INFO = 0x4170; +// const KFDATA = 0xB000; +// const KFHDR = 0xB00A; +// const KFSEG = 0xB008; +// const KFCURTIME = 0xB009; +// const AMBIENT_NODE_TAG = 0xB001; +// const OBJECT_NODE_TAG = 0xB002; +// const CAMERA_NODE_TAG = 0xB003; +// const TARGET_NODE_TAG = 0xB004; +// const LIGHT_NODE_TAG = 0xB005; +// const L_TARGET_NODE_TAG = 0xB006; +// const SPOTLIGHT_NODE_TAG = 0xB007; +// const NODE_ID = 0xB030; +// const NODE_HDR = 0xB010; +// const PIVOT = 0xB013; +// const INSTANCE_NAME = 0xB011; +// const MORPH_SMOOTH = 0xB015; +// const BOUNDBOX = 0xB014; +// const POS_TRACK_TAG = 0xB020; +// const COL_TRACK_TAG = 0xB025; +// const ROT_TRACK_TAG = 0xB021; +// const SCL_TRACK_TAG = 0xB022; +// const MORPH_TRACK_TAG = 0xB026; +// const FOV_TRACK_TAG = 0xB023; +// const ROLL_TRACK_TAG = 0xB024; +// const HOT_TRACK_TAG = 0xB027; +// const FALL_TRACK_TAG = 0xB028; +// const HIDE_TRACK_TAG = 0xB029; +// const POLY_2D = 0x5000; +// const SHAPE_OK = 0x5010; +// const SHAPE_NOT_OK = 0x5011; +// const SHAPE_HOOK = 0x5020; +// const PATH_3D = 0x6000; +// const PATH_MATRIX = 0x6005; +// const SHAPE_2D = 0x6010; +// const M_SCALE = 0x6020; +// const M_TWIST = 0x6030; +// const M_TEETER = 0x6040; +// const M_FIT = 0x6050; +// const M_BEVEL = 0x6060; +// const XZ_CURVE = 0x6070; +// const YZ_CURVE = 0x6080; +// const INTERPCT = 0x6090; +// const DEFORM_LIMIT = 0x60A0; +// const USE_CONTOUR = 0x6100; +// const USE_TWEEN = 0x6110; +// const USE_SCALE = 0x6120; +// const USE_TWIST = 0x6130; +// const USE_TEETER = 0x6140; +// const USE_FIT = 0x6150; +// const USE_BEVEL = 0x6160; +// const DEFAULT_VIEW = 0x3000; +// const VIEW_TOP = 0x3010; +// const VIEW_BOTTOM = 0x3020; +// const VIEW_LEFT = 0x3030; +// const VIEW_RIGHT = 0x3040; +// const VIEW_FRONT = 0x3050; +// const VIEW_BACK = 0x3060; +// const VIEW_USER = 0x3070; +// const VIEW_CAMERA = 0x3080; +// const VIEW_WINDOW = 0x3090; +// const VIEWPORT_LAYOUT_OLD = 0x7000; +// const VIEWPORT_DATA_OLD = 0x7010; +// const VIEWPORT_LAYOUT = 0x7001; +// const VIEWPORT_DATA = 0x7011; +// const VIEWPORT_DATA_3 = 0x7012; +// const VIEWPORT_SIZE = 0x7020; +// const NETWORK_VIEW = 0x7030; export { TDSLoader }; diff --git a/examples/jsm/loaders/TGALoader.js b/examples/jsm/loaders/TGALoader.js index 3b96a4223b2fc4..99066fc6fe4687 100644 --- a/examples/jsm/loaders/TGALoader.js +++ b/examples/jsm/loaders/TGALoader.js @@ -3,17 +3,15 @@ import { LinearMipmapLinearFilter } from '../../../build/three.module.js'; -var TGALoader = function ( manager ) { +class TGALoader extends DataTextureLoader { - DataTextureLoader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype ), { - - constructor: TGALoader, + } - parse: function ( buffer ) { + parse( buffer ) { // reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js @@ -82,13 +80,11 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaParse( use_rle, use_pal, header, offset, data ) { - var pixel_data, - pixel_size, - pixel_total, + let pixel_data, palettes; - pixel_size = header.pixel_size >> 3; - pixel_total = header.width * header.height * pixel_size; + const pixel_size = header.pixel_size >> 3; + const pixel_total = header.width * header.height * pixel_size; // read palettes @@ -104,9 +100,9 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype pixel_data = new Uint8Array( pixel_total ); - var c, count, i; - var shift = 0; - var pixels = new Uint8Array( pixel_size ); + let c, count, i; + let shift = 0; + const pixels = new Uint8Array( pixel_size ); while ( shift < pixel_total ) { @@ -172,9 +168,9 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaGetImageData8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes ) { - var colormap = palettes; - var color, i = 0, x, y; - var width = header.width; + const colormap = palettes; + let color, i = 0, x, y; + const width = header.width; for ( y = y_start; y !== y_end; y += y_step ) { @@ -196,8 +192,8 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaGetImageData16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - var color, i = 0, x, y; - var width = header.width; + let color, i = 0, x, y; + const width = header.width; for ( y = y_start; y !== y_end; y += y_step ) { @@ -219,8 +215,8 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaGetImageData24bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - var i = 0, x, y; - var width = header.width; + let i = 0, x, y; + const width = header.width; for ( y = y_start; y !== y_end; y += y_step ) { @@ -241,8 +237,8 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaGetImageData32bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - var i = 0, x, y; - var width = header.width; + let i = 0, x, y; + const width = header.width; for ( y = y_start; y !== y_end; y += y_step ) { @@ -263,8 +259,8 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - var color, i = 0, x, y; - var width = header.width; + let color, i = 0, x, y; + const width = header.width; for ( y = y_start; y !== y_end; y += y_step ) { @@ -286,8 +282,8 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function tgaGetImageDataGrey16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) { - var i = 0, x, y; - var width = header.width; + let i = 0, x, y; + const width = header.width; for ( y = y_start; y !== y_end; y += y_step ) { @@ -308,7 +304,7 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype function getTgaRGBA( data, width, height, image, palette ) { - var x_start, + let x_start, y_start, x_step, y_step, @@ -403,7 +399,7 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype } // Load image data according to specific method - // var func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits'; + // let func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits'; // func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette ); return data; @@ -411,7 +407,7 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype // TGA constants - var TGA_TYPE_NO_DATA = 0, + const TGA_TYPE_NO_DATA = 0, TGA_TYPE_INDEXED = 1, TGA_TYPE_RGB = 2, TGA_TYPE_GREY = 3, @@ -428,8 +424,9 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype if ( buffer.length < 19 ) console.error( 'THREE.TGALoader: Not enough data to contain header.' ); - var content = new Uint8Array( buffer ), - offset = 0, + let offset = 0; + + const content = new Uint8Array( buffer ), header = { id_length: content[ offset ++ ], colormap_type: content[ offset ++ ], @@ -463,7 +460,7 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype // get targa information about RLE compression and palette - var use_rle = false, + let use_rle = false, use_pal = false, use_grey = false; @@ -498,8 +495,8 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype // - var imageData = new Uint8Array( header.width * header.height * 4 ); - var result = tgaParse( use_rle, use_pal, header, offset, content ); + const imageData = new Uint8Array( header.width * header.height * 4 ); + const result = tgaParse( use_rle, use_pal, header, offset, content ); getTgaRGBA( imageData, header.width, header.height, result.pixel_data, result.palettes ); return { @@ -515,6 +512,6 @@ TGALoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype } -} ); +} export { TGALoader }; diff --git a/examples/jsm/loaders/TTFLoader.js b/examples/jsm/loaders/TTFLoader.js index c720018a334eeb..42d33ab64b8eec 100644 --- a/examples/jsm/loaders/TTFLoader.js +++ b/examples/jsm/loaders/TTFLoader.js @@ -10,24 +10,21 @@ import { opentype } from '../libs/opentype.module.min.js'; * to create THREE.Font objects. */ -var TTFLoader = function ( manager ) { +class TTFLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { - this.reversed = false; + super( manager ); -}; + this.reversed = false; + } -TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: TTFLoader, - - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( this.manager ); + const loader = new FileLoader( this.manager ); loader.setPath( this.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( this.requestHeader ); @@ -56,28 +53,28 @@ TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( arraybuffer ) { + parse( arraybuffer ) { function convert( font, reversed ) { - var round = Math.round; + const round = Math.round; - var glyphs = {}; - var scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 ); + const glyphs = {}; + const scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 ); - var glyphIndexMap = font.encoding.cmap.glyphIndexMap; - var unicodes = Object.keys( glyphIndexMap ); + const glyphIndexMap = font.encoding.cmap.glyphIndexMap; + const unicodes = Object.keys( glyphIndexMap ); - for ( var i = 0; i < unicodes.length; i ++ ) { + for ( let i = 0; i < unicodes.length; i ++ ) { - var unicode = unicodes[ i ]; - var glyph = font.glyphs.glyphs[ glyphIndexMap[ unicode ] ]; + const unicode = unicodes[ i ]; + const glyph = font.glyphs.glyphs[ glyphIndexMap[ unicode ] ]; if ( unicode !== undefined ) { - var token = { + const token = { ha: round( glyph.advanceWidth * scale ), x_min: round( glyph.xMin * scale ), x_max: round( glyph.xMax * scale ), @@ -147,8 +144,8 @@ TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function reverseCommands( commands ) { - var paths = []; - var path; + const paths = []; + let path; commands.forEach( function ( c ) { @@ -165,11 +162,11 @@ TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } ); - var reversed = []; + const reversed = []; paths.forEach( function ( p ) { - var result = { + const result = { type: 'm', x: p[ p.length - 1 ].x, y: p[ p.length - 1 ].y @@ -177,10 +174,10 @@ TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { reversed.push( result ); - for ( var i = p.length - 1; i > 0; i -- ) { + for ( let i = p.length - 1; i > 0; i -- ) { - var command = p[ i ]; - var result = { type: command.type }; + const command = p[ i ]; + const result = { type: command.type }; if ( command.x2 !== undefined && command.y2 !== undefined ) { @@ -219,6 +216,6 @@ TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { TTFLoader }; diff --git a/examples/jsm/loaders/TiltLoader.js b/examples/jsm/loaders/TiltLoader.js index 27625fe08f07fb..4e6b922724e783 100644 --- a/examples/jsm/loaders/TiltLoader.js +++ b/examples/jsm/loaders/TiltLoader.js @@ -12,7 +12,7 @@ import { Quaternion, Vector3 } from '../../../build/three.module.js'; -import { unzipSync, strFromU8 } from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; class TiltLoader extends Loader { @@ -56,7 +56,7 @@ class TiltLoader extends Loader { const group = new Group(); // https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/edit# - const zip = unzipSync( new Uint8Array( buffer.slice( 16 ) ) ); + const zip = fflate.unzipSync( new Uint8Array( buffer.slice( 16 ) ) ); /* const thumbnail = zip[ 'thumbnail.png' ].buffer; @@ -65,7 +65,7 @@ class TiltLoader extends Loader { document.body.appendChild( img ); */ - const metadata = JSON.parse( strFromU8( zip[ 'metadata.json' ] ) ); + const metadata = JSON.parse( fflate.strFromU8( zip[ 'metadata.json' ] ) ); /* const blob = new Blob( [ zip[ 'data.sketch' ].buffer ], { type: 'application/octet-stream' } ); diff --git a/examples/jsm/loaders/VRMLLoader.js b/examples/jsm/loaders/VRMLLoader.js index 44ea131bfb2b98..10bc263b95f57c 100644 --- a/examples/jsm/loaders/VRMLLoader.js +++ b/examples/jsm/loaders/VRMLLoader.js @@ -34,2647 +34,2640 @@ import { Vector2, Vector3 } from '../../../build/three.module.js'; -import { chevrotain } from '../libs/chevrotain.module.min.js'; +import chevrotain from '../libs/chevrotain.module.min.js'; -var VRMLLoader = ( function () { - // dependency check +class VRMLLoader extends Loader { - if ( typeof chevrotain === 'undefined' ) { // eslint-disable-line no-undef + constructor( manager ) { - throw Error( 'THREE.VRMLLoader: External library chevrotain.min.js required.' ); + super( manager ); - } + // dependency check - // class definitions + if ( typeof chevrotain === 'undefined' ) { // eslint-disable-line no-undef - function VRMLLoader( manager ) { + throw Error( 'THREE.VRMLLoader: External library chevrotain.min.js required.' ); - Loader.call( this, manager ); + } } - VRMLLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + load( url, onLoad, onProgress, onError ) { - constructor: VRMLLoader, + const scope = this; - load: function ( url, onLoad, onProgress, onError ) { + const path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; - var scope = this; + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( text ) { - var path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; + try { - var loader = new FileLoader( scope.manager ); - loader.setPath( scope.path ); - loader.setRequestHeader( scope.requestHeader ); - loader.setWithCredentials( scope.withCredentials ); - loader.load( url, function ( text ) { + onLoad( scope.parse( text, path ) ); - try { + } catch ( e ) { - onLoad( scope.parse( text, path ) ); + if ( onError ) { - } catch ( e ) { + onError( e ); - if ( onError ) { + } else { - onError( e ); + console.error( e ); - } else { + } - console.error( e ); + scope.manager.itemError( url ); - } + } - scope.manager.itemError( url ); + }, onProgress, onError ); - } + } - }, onProgress, onError ); + parse( data, path ) { - }, + const nodeMap = {}; - parse: function ( data, path ) { + function generateVRMLTree( data ) { - var nodeMap = {}; + // create lexer, parser and visitor - function generateVRMLTree( data ) { + const tokenData = createTokens(); - // create lexer, parser and visitor + const lexer = new VRMLLexer( tokenData.tokens ); + const parser = new VRMLParser( tokenData.tokenVocabulary ); + const visitor = createVisitor( parser.getBaseCstVisitorConstructor() ); - var tokenData = createTokens(); + // lexing - var lexer = new VRMLLexer( tokenData.tokens ); - var parser = new VRMLParser( tokenData.tokenVocabulary ); - var visitor = createVisitor( parser.getBaseCstVisitorConstructor() ); + const lexingResult = lexer.lex( data ); + parser.input = lexingResult.tokens; - // lexing + // parsing - var lexingResult = lexer.lex( data ); - parser.input = lexingResult.tokens; + const cstOutput = parser.vrml(); - // parsing + if ( parser.errors.length > 0 ) { - var cstOutput = parser.vrml(); + console.error( parser.errors ); - if ( parser.errors.length > 0 ) { + throw Error( 'THREE.VRMLLoader: Parsing errors detected.' ); - console.error( parser.errors ); + } - throw Error( 'THREE.VRMLLoader: Parsing errors detected.' ); + // actions - } + const ast = visitor.visit( cstOutput ); - // actions - - var ast = visitor.visit( cstOutput ); - - return ast; - - } - - function createTokens() { - - var createToken = chevrotain.createToken; // eslint-disable-line no-undef - - // from http://gun.teipir.gr/VRML-amgem/spec/part1/concepts.html#SyntaxBasics - - var RouteIdentifier = createToken( { name: 'RouteIdentifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*[\.][^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/ } ); - var Identifier = createToken( { name: 'Identifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/, longer_alt: RouteIdentifier } ); - - // from http://gun.teipir.gr/VRML-amgem/spec/part1/nodesRef.html - - var nodeTypes = [ - 'Anchor', 'Billboard', 'Collision', 'Group', 'Transform', // grouping nodes - 'Inline', 'LOD', 'Switch', // special groups - 'AudioClip', 'DirectionalLight', 'PointLight', 'Script', 'Shape', 'Sound', 'SpotLight', 'WorldInfo', // common nodes - 'CylinderSensor', 'PlaneSensor', 'ProximitySensor', 'SphereSensor', 'TimeSensor', 'TouchSensor', 'VisibilitySensor', // sensors - 'Box', 'Cone', 'Cylinder', 'ElevationGrid', 'Extrusion', 'IndexedFaceSet', 'IndexedLineSet', 'PointSet', 'Sphere', // geometries - 'Color', 'Coordinate', 'Normal', 'TextureCoordinate', // geometric properties - 'Appearance', 'FontStyle', 'ImageTexture', 'Material', 'MovieTexture', 'PixelTexture', 'TextureTransform', // appearance - 'ColorInterpolator', 'CoordinateInterpolator', 'NormalInterpolator', 'OrientationInterpolator', 'PositionInterpolator', 'ScalarInterpolator', // interpolators - 'Background', 'Fog', 'NavigationInfo', 'Viewpoint', // bindable nodes - 'Text' // Text must be placed at the end of the regex so there are no matches for TextureTransform and TextureCoordinate - ]; - - // - - var Version = createToken( { - name: 'Version', - pattern: /#VRML.*/, - longer_alt: Identifier - } ); - - var NodeName = createToken( { - name: 'NodeName', - pattern: new RegExp( nodeTypes.join( '|' ) ), - longer_alt: Identifier - } ); - - var DEF = createToken( { - name: 'DEF', - pattern: /DEF/, - longer_alt: Identifier - } ); - - var USE = createToken( { - name: 'USE', - pattern: /USE/, - longer_alt: Identifier - } ); - - var ROUTE = createToken( { - name: 'ROUTE', - pattern: /ROUTE/, - longer_alt: Identifier - } ); - - var TO = createToken( { - name: 'TO', - pattern: /TO/, - longer_alt: Identifier - } ); - - // - - var StringLiteral = createToken( { name: 'StringLiteral', pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } ); - var HexLiteral = createToken( { name: 'HexLiteral', pattern: /0[xX][0-9a-fA-F]+/ } ); - var NumberLiteral = createToken( { name: 'NumberLiteral', pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ } ); - var TrueLiteral = createToken( { name: 'TrueLiteral', pattern: /TRUE/ } ); - var FalseLiteral = createToken( { name: 'FalseLiteral', pattern: /FALSE/ } ); - var NullLiteral = createToken( { name: 'NullLiteral', pattern: /NULL/ } ); - var LSquare = createToken( { name: 'LSquare', pattern: /\[/ } ); - var RSquare = createToken( { name: 'RSquare', pattern: /]/ } ); - var LCurly = createToken( { name: 'LCurly', pattern: /{/ } ); - var RCurly = createToken( { name: 'RCurly', pattern: /}/ } ); - var Comment = createToken( { - name: 'Comment', - pattern: /#.*/, - group: chevrotain.Lexer.SKIPPED // eslint-disable-line no-undef - } ); - - // commas, blanks, tabs, newlines and carriage returns are whitespace characters wherever they appear outside of string fields - - var WhiteSpace = createToken( { - name: 'WhiteSpace', - pattern: /[ ,\s]/, - group: chevrotain.Lexer.SKIPPED // eslint-disable-line no-undef - } ); - - var tokens = [ - WhiteSpace, - // keywords appear before the Identifier - NodeName, - DEF, - USE, - ROUTE, - TO, - TrueLiteral, - FalseLiteral, - NullLiteral, - // the Identifier must appear after the keywords because all keywords are valid identifiers - Version, - Identifier, - RouteIdentifier, - StringLiteral, - HexLiteral, - NumberLiteral, - LSquare, - RSquare, - LCurly, - RCurly, - Comment - ]; - - var tokenVocabulary = {}; - - for ( var i = 0, l = tokens.length; i < l; i ++ ) { - - var token = tokens[ i ]; - - tokenVocabulary[ token.name ] = token; + return ast; - } + } - return { tokens: tokens, tokenVocabulary: tokenVocabulary }; + function createTokens() { - } + const createToken = chevrotain.createToken; // eslint-disable-line no-undef + // from http://gun.teipir.gr/VRML-amgem/spec/part1/concepts.html#SyntaxBasics - function createVisitor( BaseVRMLVisitor ) { + const RouteIdentifier = createToken( { name: 'RouteIdentifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*[\.][^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/ } ); + const Identifier = createToken( { name: 'Identifier', pattern: /[^\x30-\x39\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d][^\0-\x20\x22\x27\x23\x2b\x2c\x2d\x2e\x5b\x5d\x5c\x7b\x7d]*/, longer_alt: RouteIdentifier } ); - // the visitor is created dynmaically based on the given base class + // from http://gun.teipir.gr/VRML-amgem/spec/part1/nodesRef.html - function VRMLToASTVisitor() { + const nodeTypes = [ + 'Anchor', 'Billboard', 'Collision', 'Group', 'Transform', // grouping nodes + 'Inline', 'LOD', 'Switch', // special groups + 'AudioClip', 'DirectionalLight', 'PointLight', 'Script', 'Shape', 'Sound', 'SpotLight', 'WorldInfo', // common nodes + 'CylinderSensor', 'PlaneSensor', 'ProximitySensor', 'SphereSensor', 'TimeSensor', 'TouchSensor', 'VisibilitySensor', // sensors + 'Box', 'Cone', 'Cylinder', 'ElevationGrid', 'Extrusion', 'IndexedFaceSet', 'IndexedLineSet', 'PointSet', 'Sphere', // geometries + 'Color', 'Coordinate', 'Normal', 'TextureCoordinate', // geometric properties + 'Appearance', 'FontStyle', 'ImageTexture', 'Material', 'MovieTexture', 'PixelTexture', 'TextureTransform', // appearance + 'ColorInterpolator', 'CoordinateInterpolator', 'NormalInterpolator', 'OrientationInterpolator', 'PositionInterpolator', 'ScalarInterpolator', // interpolators + 'Background', 'Fog', 'NavigationInfo', 'Viewpoint', // bindable nodes + 'Text' // Text must be placed at the end of the regex so there are no matches for TextureTransform and TextureCoordinate + ]; - BaseVRMLVisitor.call( this ); + // - this.validateVisitor(); + const Version = createToken( { + name: 'Version', + pattern: /#VRML.*/, + longer_alt: Identifier + } ); - } + const NodeName = createToken( { + name: 'NodeName', + pattern: new RegExp( nodeTypes.join( '|' ) ), + longer_alt: Identifier + } ); - VRMLToASTVisitor.prototype = Object.assign( Object.create( BaseVRMLVisitor.prototype ), { + const DEF = createToken( { + name: 'DEF', + pattern: /DEF/, + longer_alt: Identifier + } ); - constructor: VRMLToASTVisitor, + const USE = createToken( { + name: 'USE', + pattern: /USE/, + longer_alt: Identifier + } ); - vrml: function ( ctx ) { + const ROUTE = createToken( { + name: 'ROUTE', + pattern: /ROUTE/, + longer_alt: Identifier + } ); - var data = { - version: this.visit( ctx.version ), - nodes: [], - routes: [] - }; + const TO = createToken( { + name: 'TO', + pattern: /TO/, + longer_alt: Identifier + } ); - for ( var i = 0, l = ctx.node.length; i < l; i ++ ) { + // - var node = ctx.node[ i ]; + const StringLiteral = createToken( { name: 'StringLiteral', pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } ); + 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/ } ); + const FalseLiteral = createToken( { name: 'FalseLiteral', pattern: /FALSE/ } ); + const NullLiteral = createToken( { name: 'NullLiteral', pattern: /NULL/ } ); + const LSquare = createToken( { name: 'LSquare', pattern: /\[/ } ); + const RSquare = createToken( { name: 'RSquare', pattern: /]/ } ); + const LCurly = createToken( { name: 'LCurly', pattern: /{/ } ); + const RCurly = createToken( { name: 'RCurly', pattern: /}/ } ); + const Comment = createToken( { + name: 'Comment', + pattern: /#.*/, + group: chevrotain.Lexer.SKIPPED // eslint-disable-line no-undef + } ); - data.nodes.push( this.visit( node ) ); + // commas, blanks, tabs, newlines and carriage returns are whitespace characters wherever they appear outside of string fields - } + const WhiteSpace = createToken( { + name: 'WhiteSpace', + pattern: /[ ,\s]/, + group: chevrotain.Lexer.SKIPPED // eslint-disable-line no-undef + } ); - if ( ctx.route ) { + const tokens = [ + WhiteSpace, + // keywords appear before the Identifier + NodeName, + DEF, + USE, + ROUTE, + TO, + TrueLiteral, + FalseLiteral, + NullLiteral, + // the Identifier must appear after the keywords because all keywords are valid identifiers + Version, + Identifier, + RouteIdentifier, + StringLiteral, + HexLiteral, + NumberLiteral, + LSquare, + RSquare, + LCurly, + RCurly, + Comment + ]; + + const tokenVocabulary = {}; + + for ( let i = 0, l = tokens.length; i < l; i ++ ) { + + const token = tokens[ i ]; + + tokenVocabulary[ token.name ] = token; - for ( var i = 0, l = ctx.route.length; i < l; i ++ ) { + } - var route = ctx.route[ i ]; + return { tokens: tokens, tokenVocabulary: tokenVocabulary }; - data.routes.push( this.visit( route ) ); + } - } - } + function createVisitor( BaseVRMLVisitor ) { - return data; + // the visitor is created dynmaically based on the given base class - }, + function VRMLToASTVisitor() { - version: function ( ctx ) { + BaseVRMLVisitor.call( this ); - return ctx.Version[ 0 ].image; + this.validateVisitor(); - }, + } - node: function ( ctx ) { + VRMLToASTVisitor.prototype = Object.assign( Object.create( BaseVRMLVisitor.prototype ), { - var data = { - name: ctx.NodeName[ 0 ].image, - fields: [] - }; + constructor: VRMLToASTVisitor, - if ( ctx.field ) { + vrml: function ( ctx ) { - for ( var i = 0, l = ctx.field.length; i < l; i ++ ) { + const data = { + version: this.visit( ctx.version ), + nodes: [], + routes: [] + }; - var field = ctx.field[ i ]; + for ( let i = 0, l = ctx.node.length; i < l; i ++ ) { - data.fields.push( this.visit( field ) ); + const node = ctx.node[ i ]; - } + data.nodes.push( this.visit( node ) ); - } + } + + if ( ctx.route ) { - // DEF + for ( let i = 0, l = ctx.route.length; i < l; i ++ ) { - if ( ctx.def ) { + const route = ctx.route[ i ]; - data.DEF = this.visit( ctx.def[ 0 ] ); + data.routes.push( this.visit( route ) ); } - return data; + } - }, + return data; - field: function ( ctx ) { + }, - var data = { - name: ctx.Identifier[ 0 ].image, - type: null, - values: null - }; + version: function ( ctx ) { - var result; + return ctx.Version[ 0 ].image; - // SFValue + }, - if ( ctx.singleFieldValue ) { + node: function ( ctx ) { - result = this.visit( ctx.singleFieldValue[ 0 ] ); + const data = { + name: ctx.NodeName[ 0 ].image, + fields: [] + }; - } + if ( ctx.field ) { - // MFValue + for ( let i = 0, l = ctx.field.length; i < l; i ++ ) { - if ( ctx.multiFieldValue ) { + const field = ctx.field[ i ]; - result = this.visit( ctx.multiFieldValue[ 0 ] ); + data.fields.push( this.visit( field ) ); } - data.type = result.type; - data.values = result.values; - - return data; + } - }, + // DEF - def: function ( ctx ) { + if ( ctx.def ) { - return ( ctx.Identifier || ctx.NodeName )[ 0 ].image; + data.DEF = this.visit( ctx.def[ 0 ] ); - }, + } - use: function ( ctx ) { + return data; - return { USE: ( ctx.Identifier || ctx.NodeName )[ 0 ].image }; + }, - }, + field: function ( ctx ) { - singleFieldValue: function ( ctx ) { + const data = { + name: ctx.Identifier[ 0 ].image, + type: null, + values: null + }; - return processField( this, ctx ); + let result; - }, + // SFValue - multiFieldValue: function ( ctx ) { + if ( ctx.singleFieldValue ) { - return processField( this, ctx ); + result = this.visit( ctx.singleFieldValue[ 0 ] ); - }, + } - route: function ( ctx ) { + // MFValue - var data = { - FROM: ctx.RouteIdentifier[ 0 ].image, - TO: ctx.RouteIdentifier[ 1 ].image - }; + if ( ctx.multiFieldValue ) { - return data; + result = this.visit( ctx.multiFieldValue[ 0 ] ); } - } ); + data.type = result.type; + data.values = result.values; - function processField( scope, ctx ) { + return data; - var field = { - type: null, - values: [] - }; + }, - if ( ctx.node ) { + def: function ( ctx ) { - field.type = 'node'; + return ( ctx.Identifier || ctx.NodeName )[ 0 ].image; - for ( var i = 0, l = ctx.node.length; i < l; i ++ ) { + }, - var node = ctx.node[ i ]; + use: function ( ctx ) { - field.values.push( scope.visit( node ) ); + return { USE: ( ctx.Identifier || ctx.NodeName )[ 0 ].image }; - } + }, - } + singleFieldValue: function ( ctx ) { - if ( ctx.use ) { + return processField( this, ctx ); - field.type = 'use'; + }, - for ( var i = 0, l = ctx.use.length; i < l; i ++ ) { + multiFieldValue: function ( ctx ) { - var use = ctx.use[ i ]; + return processField( this, ctx ); - field.values.push( scope.visit( use ) ); + }, - } + route: function ( ctx ) { - } + const data = { + FROM: ctx.RouteIdentifier[ 0 ].image, + TO: ctx.RouteIdentifier[ 1 ].image + }; - if ( ctx.StringLiteral ) { + return data; - field.type = 'string'; + } - for ( var i = 0, l = ctx.StringLiteral.length; i < l; i ++ ) { + } ); + + function processField( scope, ctx ) { - var stringLiteral = ctx.StringLiteral[ i ]; + const field = { + type: null, + values: [] + }; - field.values.push( stringLiteral.image.replace( /'|"/g, '' ) ); + if ( ctx.node ) { - } + field.type = 'node'; + + for ( let i = 0, l = ctx.node.length; i < l; i ++ ) { + + const node = ctx.node[ i ]; + + field.values.push( scope.visit( node ) ); } - if ( ctx.NumberLiteral ) { + } - field.type = 'number'; + if ( ctx.use ) { - for ( var i = 0, l = ctx.NumberLiteral.length; i < l; i ++ ) { + field.type = 'use'; - var numberLiteral = ctx.NumberLiteral[ i ]; + for ( let i = 0, l = ctx.use.length; i < l; i ++ ) { - field.values.push( parseFloat( numberLiteral.image ) ); + const use = ctx.use[ i ]; - } + field.values.push( scope.visit( use ) ); } - if ( ctx.HexLiteral ) { + } - field.type = 'hex'; + if ( ctx.StringLiteral ) { - for ( var i = 0, l = ctx.HexLiteral.length; i < l; i ++ ) { + field.type = 'string'; - var hexLiteral = ctx.HexLiteral[ i ]; + for ( let i = 0, l = ctx.StringLiteral.length; i < l; i ++ ) { - field.values.push( hexLiteral.image ); + const stringLiteral = ctx.StringLiteral[ i ]; - } + field.values.push( stringLiteral.image.replace( /'|"/g, '' ) ); } - if ( ctx.TrueLiteral ) { + } - field.type = 'boolean'; + if ( ctx.NumberLiteral ) { - for ( var i = 0, l = ctx.TrueLiteral.length; i < l; i ++ ) { + field.type = 'number'; - var trueLiteral = ctx.TrueLiteral[ i ]; + for ( let i = 0, l = ctx.NumberLiteral.length; i < l; i ++ ) { - if ( trueLiteral.image === 'TRUE' ) field.values.push( true ); + const numberLiteral = ctx.NumberLiteral[ i ]; - } + field.values.push( parseFloat( numberLiteral.image ) ); } - if ( ctx.FalseLiteral ) { + } - field.type = 'boolean'; + if ( ctx.HexLiteral ) { - for ( var i = 0, l = ctx.FalseLiteral.length; i < l; i ++ ) { + field.type = 'hex'; - var falseLiteral = ctx.FalseLiteral[ i ]; + for ( let i = 0, l = ctx.HexLiteral.length; i < l; i ++ ) { - if ( falseLiteral.image === 'FALSE' ) field.values.push( false ); + const hexLiteral = ctx.HexLiteral[ i ]; - } + field.values.push( hexLiteral.image ); } - if ( ctx.NullLiteral ) { + } - field.type = 'null'; + if ( ctx.TrueLiteral ) { - ctx.NullLiteral.forEach( function () { + field.type = 'boolean'; - field.values.push( null ); + for ( let i = 0, l = ctx.TrueLiteral.length; i < l; i ++ ) { - } ); + const trueLiteral = ctx.TrueLiteral[ i ]; - } + if ( trueLiteral.image === 'TRUE' ) field.values.push( true ); - return field; + } } - return new VRMLToASTVisitor(); + if ( ctx.FalseLiteral ) { - } + field.type = 'boolean'; + + for ( let i = 0, l = ctx.FalseLiteral.length; i < l; i ++ ) { + + const falseLiteral = ctx.FalseLiteral[ i ]; + + if ( falseLiteral.image === 'FALSE' ) field.values.push( false ); - function parseTree( tree ) { + } - // console.log( JSON.stringify( tree, null, 2 ) ); + } - var nodes = tree.nodes; - var scene = new Scene(); + if ( ctx.NullLiteral ) { - // first iteration: build nodemap based on DEF statements + field.type = 'null'; - for ( var i = 0, l = nodes.length; i < l; i ++ ) { + ctx.NullLiteral.forEach( function () { - var node = nodes[ i ]; + field.values.push( null ); - buildNodeMap( node ); + } ); } - // second iteration: build nodes + return field; - for ( var i = 0, l = nodes.length; i < l; i ++ ) { + } - var node = nodes[ i ]; - var object = getNode( node ); + return new VRMLToASTVisitor(); - if ( object instanceof Object3D ) scene.add( object ); + } - if ( node.name === 'WorldInfo' ) scene.userData.worldInfo = object; + function parseTree( tree ) { - } + // console.log( JSON.stringify( tree, null, 2 ) ); - return scene; + const nodes = tree.nodes; + const scene = new Scene(); - } + // first iteration: build nodemap based on DEF statements - function buildNodeMap( node ) { + for ( let i = 0, l = nodes.length; i < l; i ++ ) { - if ( node.DEF ) { + const node = nodes[ i ]; - nodeMap[ node.DEF ] = node; + buildNodeMap( node ); - } + } - var fields = node.fields; + // second iteration: build nodes - for ( var i = 0, l = fields.length; i < l; i ++ ) { + for ( let i = 0, l = nodes.length; i < l; i ++ ) { - var field = fields[ i ]; + const node = nodes[ i ]; + const object = getNode( node ); - if ( field.type === 'node' ) { + if ( object instanceof Object3D ) scene.add( object ); - var fieldValues = field.values; + if ( node.name === 'WorldInfo' ) scene.userData.worldInfo = object; - for ( var j = 0, jl = fieldValues.length; j < jl; j ++ ) { + } - buildNodeMap( fieldValues[ j ] ); + return scene; - } + } - } + function buildNodeMap( node ) { + if ( node.DEF ) { - } + nodeMap[ node.DEF ] = node; } + const fields = node.fields; - function getNode( node ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - // handle case where a node refers to a different one + const field = fields[ i ]; - if ( node.USE ) { + if ( field.type === 'node' ) { - return resolveUSE( node.USE ); + const fieldValues = field.values; - } + for ( let j = 0, jl = fieldValues.length; j < jl; j ++ ) { - if ( node.build !== undefined ) return node.build; + buildNodeMap( fieldValues[ j ] ); - node.build = buildNode( node ); + } + + } - return node.build; } - // node builder + } - function buildNode( node ) { - var nodeName = node.name; - var build; + function getNode( node ) { - switch ( nodeName ) { + // handle case where a node refers to a different one - case 'Group': - case 'Transform': - case 'Collision': - build = buildGroupingNode( node ); - break; + if ( node.USE ) { - case 'Background': - build = buildBackgroundNode( node ); - break; + return resolveUSE( node.USE ); - case 'Shape': - build = buildShapeNode( node ); - break; + } - case 'Appearance': - build = buildAppearanceNode( node ); - break; + if ( node.build !== undefined ) return node.build; - case 'Material': - build = buildMaterialNode( node ); - break; + node.build = buildNode( node ); - case 'ImageTexture': - build = buildImageTextureNode( node ); - break; + return node.build; - case 'PixelTexture': - build = buildPixelTextureNode( node ); - break; + } - case 'TextureTransform': - build = buildTextureTransformNode( node ); - break; + // node builder - case 'IndexedFaceSet': - build = buildIndexedFaceSetNode( node ); - break; + function buildNode( node ) { - case 'IndexedLineSet': - build = buildIndexedLineSetNode( node ); - break; + const nodeName = node.name; + let build; - case 'PointSet': - build = buildPointSetNode( node ); - break; + switch ( nodeName ) { - case 'Box': - build = buildBoxNode( node ); - break; + case 'Group': + case 'Transform': + case 'Collision': + build = buildGroupingNode( node ); + break; - case 'Cone': - build = buildConeNode( node ); - break; + case 'Background': + build = buildBackgroundNode( node ); + break; - case 'Cylinder': - build = buildCylinderNode( node ); - break; + case 'Shape': + build = buildShapeNode( node ); + break; + + case 'Appearance': + build = buildAppearanceNode( node ); + break; + + case 'Material': + build = buildMaterialNode( node ); + break; + + case 'ImageTexture': + build = buildImageTextureNode( node ); + break; - case 'Sphere': - build = buildSphereNode( node ); - break; + case 'PixelTexture': + build = buildPixelTextureNode( node ); + break; - case 'ElevationGrid': - build = buildElevationGridNode( node ); - break; + case 'TextureTransform': + build = buildTextureTransformNode( node ); + break; - case 'Extrusion': - build = buildExtrusionNode( node ); - break; + case 'IndexedFaceSet': + build = buildIndexedFaceSetNode( node ); + break; - case 'Color': - case 'Coordinate': - case 'Normal': - case 'TextureCoordinate': - build = buildGeometricNode( node ); - break; + case 'IndexedLineSet': + build = buildIndexedLineSetNode( node ); + break; - case 'WorldInfo': - build = buildWorldInfoNode( node ); - break; + case 'PointSet': + build = buildPointSetNode( node ); + break; - case 'Anchor': - case 'Billboard': + case 'Box': + build = buildBoxNode( node ); + break; - case 'Inline': - case 'LOD': - case 'Switch': + case 'Cone': + build = buildConeNode( node ); + break; - case 'AudioClip': - case 'DirectionalLight': - case 'PointLight': - case 'Script': - case 'Sound': - case 'SpotLight': + case 'Cylinder': + build = buildCylinderNode( node ); + break; - case 'CylinderSensor': - case 'PlaneSensor': - case 'ProximitySensor': - case 'SphereSensor': - case 'TimeSensor': - case 'TouchSensor': - case 'VisibilitySensor': + case 'Sphere': + build = buildSphereNode( node ); + break; - case 'Text': + case 'ElevationGrid': + build = buildElevationGridNode( node ); + break; - case 'FontStyle': - case 'MovieTexture': + case 'Extrusion': + build = buildExtrusionNode( node ); + break; - case 'ColorInterpolator': - case 'CoordinateInterpolator': - case 'NormalInterpolator': - case 'OrientationInterpolator': - case 'PositionInterpolator': - case 'ScalarInterpolator': + case 'Color': + case 'Coordinate': + case 'Normal': + case 'TextureCoordinate': + build = buildGeometricNode( node ); + break; - case 'Fog': - case 'NavigationInfo': - case 'Viewpoint': - // node not supported yet - break; + case 'WorldInfo': + build = buildWorldInfoNode( node ); + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown node:', nodeName ); - break; + case 'Anchor': + case 'Billboard': - } + case 'Inline': + case 'LOD': + case 'Switch': - if ( build !== undefined && node.DEF !== undefined && build.hasOwnProperty( 'name' ) === true ) { + case 'AudioClip': + case 'DirectionalLight': + case 'PointLight': + case 'Script': + case 'Sound': + case 'SpotLight': + + case 'CylinderSensor': + case 'PlaneSensor': + case 'ProximitySensor': + case 'SphereSensor': + case 'TimeSensor': + case 'TouchSensor': + case 'VisibilitySensor': + + case 'Text': + + case 'FontStyle': + case 'MovieTexture': + + case 'ColorInterpolator': + case 'CoordinateInterpolator': + case 'NormalInterpolator': + case 'OrientationInterpolator': + case 'PositionInterpolator': + case 'ScalarInterpolator': + + case 'Fog': + case 'NavigationInfo': + case 'Viewpoint': + // node not supported yet + break; + + default: + console.warn( 'THREE.VRMLLoader: Unknown node:', nodeName ); + break; - build.name = node.DEF; + } - } + if ( build !== undefined && node.DEF !== undefined && build.hasOwnProperty( 'name' ) === true ) { - return build; + build.name = node.DEF; } - function buildGroupingNode( node ) { + return build; - var object = new Group(); + } - // + function buildGroupingNode( node ) { - var fields = node.fields; + const object = new Group(); - for ( var i = 0, l = fields.length; i < l; i ++ ) { + // - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'bboxCenter': - // field not supported - break; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'bboxSize': - // field not supported - break; + switch ( fieldName ) { - case 'center': - // field not supported - break; + case 'bboxCenter': + // field not supported + break; - case 'children': - parseFieldChildren( fieldValues, object ); - break; + case 'bboxSize': + // field not supported + break; - case 'collide': - // field not supported - break; + case 'center': + // field not supported + break; - case 'rotation': - var axis = new Vector3( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - var angle = fieldValues[ 3 ]; - object.quaternion.setFromAxisAngle( axis, angle ); - break; + case 'children': + parseFieldChildren( fieldValues, object ); + break; - case 'scale': - object.scale.set( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - break; + case 'collide': + // field not supported + break; - case 'scaleOrientation': - // field not supported - break; + case 'rotation': + const axis = new Vector3( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); + const angle = fieldValues[ 3 ]; + object.quaternion.setFromAxisAngle( axis, angle ); + break; - case 'translation': - object.position.set( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - break; + case 'scale': + object.scale.set( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); + break; - case 'proxy': - // field not supported - break; + case 'scaleOrientation': + // field not supported + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'translation': + object.position.set( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); + break; - } + case 'proxy': + // field not supported + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; - return object; + } } - function buildBackgroundNode( node ) { + return object; - var group = new Group(); + } - var groundAngle, groundColor; - var skyAngle, skyColor; + function buildBackgroundNode( node ) { - var fields = node.fields; + const group = new Group(); - for ( var i = 0, l = fields.length; i < l; i ++ ) { + let groundAngle, groundColor; + let skyAngle, skyColor; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'groundAngle': - groundAngle = fieldValues; - break; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'groundColor': - groundColor = fieldValues; - break; + switch ( fieldName ) { - case 'backUrl': - // field not supported - break; + case 'groundAngle': + groundAngle = fieldValues; + break; - case 'bottomUrl': - // field not supported - break; + case 'groundColor': + groundColor = fieldValues; + break; - case 'frontUrl': - // field not supported - break; + case 'backUrl': + // field not supported + break; - case 'leftUrl': - // field not supported - break; + case 'bottomUrl': + // field not supported + break; - case 'rightUrl': - // field not supported - break; + case 'frontUrl': + // field not supported + break; - case 'topUrl': - // field not supported - break; + case 'leftUrl': + // field not supported + break; - case 'skyAngle': - skyAngle = fieldValues; - break; + case 'rightUrl': + // field not supported + break; - case 'skyColor': - skyColor = fieldValues; - break; + case 'topUrl': + // field not supported + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'skyAngle': + skyAngle = fieldValues; + break; - } + case 'skyColor': + skyColor = fieldValues; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; - var radius = 10000; + } - // sky + } - if ( skyColor ) { + const radius = 10000; - var skyGeometry = new SphereGeometry( radius, 32, 16 ); - var skyMaterial = new MeshBasicMaterial( { fog: false, side: BackSide, depthWrite: false, depthTest: false } ); + // sky - if ( skyColor.length > 3 ) { + if ( skyColor ) { - paintFaces( skyGeometry, radius, skyAngle, toColorArray( skyColor ), true ); - skyMaterial.vertexColors = true; + const skyGeometry = new SphereGeometry( radius, 32, 16 ); + const skyMaterial = new MeshBasicMaterial( { fog: false, side: BackSide, depthWrite: false, depthTest: false } ); - } else { + if ( skyColor.length > 3 ) { - skyMaterial.color.setRGB( skyColor[ 0 ], skyColor[ 1 ], skyColor[ 2 ] ); + paintFaces( skyGeometry, radius, skyAngle, toColorArray( skyColor ), true ); + skyMaterial.vertexColors = true; - } + } else { - var sky = new Mesh( skyGeometry, skyMaterial ); - group.add( sky ); + skyMaterial.color.setRGB( skyColor[ 0 ], skyColor[ 1 ], skyColor[ 2 ] ); } - // ground + const sky = new Mesh( skyGeometry, skyMaterial ); + group.add( sky ); - if ( groundColor ) { + } - if ( groundColor.length > 0 ) { + // ground - var groundGeometry = new SphereGeometry( radius, 32, 16, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI ); - var groundMaterial = new MeshBasicMaterial( { fog: false, side: BackSide, vertexColors: true, depthWrite: false, depthTest: false } ); + if ( groundColor ) { - paintFaces( groundGeometry, radius, groundAngle, toColorArray( groundColor ), false ); + if ( groundColor.length > 0 ) { - var ground = new Mesh( groundGeometry, groundMaterial ); - group.add( ground ); + const groundGeometry = new SphereGeometry( radius, 32, 16, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI ); + const groundMaterial = new MeshBasicMaterial( { fog: false, side: BackSide, vertexColors: true, depthWrite: false, depthTest: false } ); - } + paintFaces( groundGeometry, radius, groundAngle, toColorArray( groundColor ), false ); + + const ground = new Mesh( groundGeometry, groundMaterial ); + group.add( ground ); } - // render background group first + } - group.renderOrder = - Infinity; + // render background group first - return group; + group.renderOrder = - Infinity; - } + return group; - function buildShapeNode( node ) { + } - var fields = node.fields; + function buildShapeNode( node ) { - // if the appearance field is NULL or unspecified, lighting is off and the unlit object color is (0, 0, 0) + const fields = node.fields; - var material = new MeshBasicMaterial( { color: 0x000000 } ); - var geometry; + // if the appearance field is NULL or unspecified, lighting is off and the unlit object color is (0, 0, 0) - for ( var i = 0, l = fields.length; i < l; i ++ ) { + let material = new MeshBasicMaterial( { color: 0x000000 } ); + let geometry; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'appearance': - if ( fieldValues[ 0 ] !== null ) { + switch ( fieldName ) { - material = getNode( fieldValues[ 0 ] ); + case 'appearance': + if ( fieldValues[ 0 ] !== null ) { - } + material = getNode( fieldValues[ 0 ] ); - break; + } - case 'geometry': - if ( fieldValues[ 0 ] !== null ) { + break; - geometry = getNode( fieldValues[ 0 ] ); + case 'geometry': + if ( fieldValues[ 0 ] !== null ) { - } + geometry = getNode( fieldValues[ 0 ] ); - break; + } - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - // build 3D object + } - var object; + // build 3D object - if ( geometry && geometry.attributes.position ) { + let object; - var type = geometry._type; + if ( geometry && geometry.attributes.position ) { - if ( type === 'points' ) { // points + const type = geometry._type; - var pointsMaterial = new PointsMaterial( { color: 0xffffff } ); + if ( type === 'points' ) { // points - if ( geometry.attributes.color !== undefined ) { + const pointsMaterial = new PointsMaterial( { color: 0xffffff } ); - pointsMaterial.vertexColors = true; + if ( geometry.attributes.color !== undefined ) { - } else { + pointsMaterial.vertexColors = true; - // if the color field is NULL and there is a material defined for the appearance affecting this PointSet, then use the emissiveColor of the material to draw the points + } else { - if ( material.isMeshPhongMaterial ) { + // if the color field is NULL and there is a material defined for the appearance affecting this PointSet, then use the emissiveColor of the material to draw the points - pointsMaterial.color.copy( material.emissive ); + if ( material.isMeshPhongMaterial ) { - } + pointsMaterial.color.copy( material.emissive ); } - object = new Points( geometry, pointsMaterial ); + } - } else if ( type === 'line' ) { // lines + object = new Points( geometry, pointsMaterial ); - var lineMaterial = new LineBasicMaterial( { color: 0xffffff } ); + } else if ( type === 'line' ) { // lines - if ( geometry.attributes.color !== undefined ) { + const lineMaterial = new LineBasicMaterial( { color: 0xffffff } ); - lineMaterial.vertexColors = true; + if ( geometry.attributes.color !== undefined ) { - } else { + lineMaterial.vertexColors = true; - // if the color field is NULL and there is a material defined for the appearance affecting this IndexedLineSet, then use the emissiveColor of the material to draw the lines + } else { - if ( material.isMeshPhongMaterial ) { + // if the color field is NULL and there is a material defined for the appearance affecting this IndexedLineSet, then use the emissiveColor of the material to draw the lines - lineMaterial.color.copy( material.emissive ); + if ( material.isMeshPhongMaterial ) { - } + lineMaterial.color.copy( material.emissive ); } - object = new LineSegments( geometry, lineMaterial ); - - } else { // consider meshes + } - // check "solid" hint (it's placed in the geometry but affects the material) + object = new LineSegments( geometry, lineMaterial ); - if ( geometry._solid !== undefined ) { + } else { // consider meshes - material.side = ( geometry._solid ) ? FrontSide : DoubleSide; + // check "solid" hint (it's placed in the geometry but affects the material) - } + if ( geometry._solid !== undefined ) { - // check for vertex colors + material.side = ( geometry._solid ) ? FrontSide : DoubleSide; - if ( geometry.attributes.color !== undefined ) { + } - material.vertexColors = true; + // check for vertex colors - } + if ( geometry.attributes.color !== undefined ) { - object = new Mesh( geometry, material ); + material.vertexColors = true; } - } else { + object = new Mesh( geometry, material ); - object = new Object3D(); + } - // if the geometry field is NULL or no vertices are defined the object is not drawn + } else { - object.visible = false; + object = new Object3D(); - } + // if the geometry field is NULL or no vertices are defined the object is not drawn - return object; + object.visible = false; } - function buildAppearanceNode( node ) { + return object; - var material = new MeshPhongMaterial(); - var transformData; + } - var fields = node.fields; + function buildAppearanceNode( node ) { - for ( var i = 0, l = fields.length; i < l; i ++ ) { + let material = new MeshPhongMaterial(); + let transformData; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'material': - if ( fieldValues[ 0 ] !== null ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - var materialData = getNode( fieldValues[ 0 ] ); + switch ( fieldName ) { - if ( materialData.diffuseColor ) material.color.copy( materialData.diffuseColor ); - if ( materialData.emissiveColor ) material.emissive.copy( materialData.emissiveColor ); - if ( materialData.shininess ) material.shininess = materialData.shininess; - if ( materialData.specularColor ) material.specular.copy( materialData.specularColor ); - if ( materialData.transparency ) material.opacity = 1 - materialData.transparency; - if ( materialData.transparency > 0 ) material.transparent = true; + case 'material': + if ( fieldValues[ 0 ] !== null ) { - } else { + const materialData = getNode( fieldValues[ 0 ] ); - // if the material field is NULL or unspecified, lighting is off and the unlit object color is (0, 0, 0) + if ( materialData.diffuseColor ) material.color.copy( materialData.diffuseColor ); + if ( materialData.emissiveColor ) material.emissive.copy( materialData.emissiveColor ); + if ( materialData.shininess ) material.shininess = materialData.shininess; + if ( materialData.specularColor ) material.specular.copy( materialData.specularColor ); + if ( materialData.transparency ) material.opacity = 1 - materialData.transparency; + if ( materialData.transparency > 0 ) material.transparent = true; - material = new MeshBasicMaterial( { color: 0x000000 } ); + } else { - } + // if the material field is NULL or unspecified, lighting is off and the unlit object color is (0, 0, 0) - break; + material = new MeshBasicMaterial( { color: 0x000000 } ); - case 'texture': - var textureNode = fieldValues[ 0 ]; - if ( textureNode !== null ) { + } + + break; - if ( textureNode.name === 'ImageTexture' || textureNode.name === 'PixelTexture' ) { + case 'texture': + const textureNode = fieldValues[ 0 ]; + if ( textureNode !== null ) { - material.map = getNode( textureNode ); + if ( textureNode.name === 'ImageTexture' || textureNode.name === 'PixelTexture' ) { - } else { + material.map = getNode( textureNode ); - // MovieTexture not supported yet + } else { - } + // MovieTexture not supported yet } - break; + } - case 'textureTransform': - if ( fieldValues[ 0 ] !== null ) { + break; - transformData = getNode( fieldValues[ 0 ] ); + case 'textureTransform': + if ( fieldValues[ 0 ] !== null ) { - } + transformData = getNode( fieldValues[ 0 ] ); - break; + } - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - // only apply texture transform data if a texture was defined - - if ( material.map ) { + } - // respect VRML lighting model + // only apply texture transform data if a texture was defined - if ( material.map.__type ) { + if ( material.map ) { - switch ( material.map.__type ) { + // respect VRML lighting model - case TEXTURE_TYPE.INTENSITY_ALPHA: - material.opacity = 1; // ignore transparency - break; + if ( material.map.__type ) { - case TEXTURE_TYPE.RGB: - material.color.set( 0xffffff ); // ignore material color - break; + switch ( material.map.__type ) { - case TEXTURE_TYPE.RGBA: - material.color.set( 0xffffff ); // ignore material color - material.opacity = 1; // ignore transparency - break; + case TEXTURE_TYPE.INTENSITY_ALPHA: + material.opacity = 1; // ignore transparency + break; - default: + case TEXTURE_TYPE.RGB: + material.color.set( 0xffffff ); // ignore material color + break; - } + case TEXTURE_TYPE.RGBA: + material.color.set( 0xffffff ); // ignore material color + material.opacity = 1; // ignore transparency + break; - delete material.map.__type; + default: } - // apply texture transform - - if ( transformData ) { - - material.map.center.copy( transformData.center ); - material.map.rotation = transformData.rotation; - material.map.repeat.copy( transformData.scale ); - material.map.offset.copy( transformData.translation ); - - } + delete material.map.__type; } - return material; - - } - - function buildMaterialNode( node ) { - - var materialData = {}; - - var fields = node.fields; - - for ( var i = 0, l = fields.length; i < l; i ++ ) { + // apply texture transform - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + if ( transformData ) { - switch ( fieldName ) { + material.map.center.copy( transformData.center ); + material.map.rotation = transformData.rotation; + material.map.repeat.copy( transformData.scale ); + material.map.offset.copy( transformData.translation ); - case 'ambientIntensity': - // field not supported - break; - - case 'diffuseColor': - materialData.diffuseColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - break; + } - case 'emissiveColor': - materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - break; + } - case 'shininess': - materialData.shininess = fieldValues[ 0 ]; - break; + return material; - case 'specularColor': - materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - break; + } - case 'transparency': - materialData.transparency = fieldValues[ 0 ]; - break; + function buildMaterialNode( node ) { - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + const materialData = {}; - } + const fields = node.fields; - } + for ( let i = 0, l = fields.length; i < l; i ++ ) { - return materialData; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - } + switch ( fieldName ) { - function parseHexColor( hex, textureType, color ) { + case 'ambientIntensity': + // field not supported + break; - switch ( textureType ) { + case 'diffuseColor': + materialData.diffuseColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); + break; - case TEXTURE_TYPE.INTENSITY: - // Intensity texture: A one-component image specifies one-byte hexadecimal or integer values representing the intensity of the image - var value = parseInt( hex ); - color.r = value; - color.g = value; - color.b = value; + case 'emissiveColor': + materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); break; - case TEXTURE_TYPE.INTENSITY_ALPHA: - // Intensity+Alpha texture: A two-component image specifies the intensity in the first (high) byte and the alpha opacity in the second (low) byte. - var value = parseInt( '0x' + hex.substring( 2, 4 ) ); - color.r = value; - color.g = value; - color.b = value; - color.a = parseInt( '0x' + hex.substring( 4, 6 ) ); + case 'shininess': + materialData.shininess = fieldValues[ 0 ]; break; - case TEXTURE_TYPE.RGB: - // RGB texture: Pixels in a three-component image specify the red component in the first (high) byte, followed by the green and blue components - color.r = parseInt( '0x' + hex.substring( 2, 4 ) ); - color.g = parseInt( '0x' + hex.substring( 4, 6 ) ); - color.b = parseInt( '0x' + hex.substring( 6, 8 ) ); + case 'specularColor': + materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); break; - case TEXTURE_TYPE.RGBA: - // RGBA texture: Four-component images specify the alpha opacity byte after red/green/blue - color.r = parseInt( '0x' + hex.substring( 2, 4 ) ); - color.g = parseInt( '0x' + hex.substring( 4, 6 ) ); - color.b = parseInt( '0x' + hex.substring( 6, 8 ) ); - color.a = parseInt( '0x' + hex.substring( 8, 10 ) ); + case 'transparency': + materialData.transparency = fieldValues[ 0 ]; break; default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } } - function getTextureType( num_components ) { + return materialData; - var type; + } - switch ( num_components ) { + function parseHexColor( hex, textureType, color ) { + + let value; + + switch ( textureType ) { + + case TEXTURE_TYPE.INTENSITY: + // Intensity texture: A one-component image specifies one-byte hexadecimal or integer values representing the intensity of the image + value = parseInt( hex ); + color.r = value; + color.g = value; + color.b = value; + break; + + case TEXTURE_TYPE.INTENSITY_ALPHA: + // Intensity+Alpha texture: A two-component image specifies the intensity in the first (high) byte and the alpha opacity in the second (low) byte. + value = parseInt( '0x' + hex.substring( 2, 4 ) ); + color.r = value; + color.g = value; + color.b = value; + color.a = parseInt( '0x' + hex.substring( 4, 6 ) ); + break; + + case TEXTURE_TYPE.RGB: + // RGB texture: Pixels in a three-component image specify the red component in the first (high) byte, followed by the green and blue components + color.r = parseInt( '0x' + hex.substring( 2, 4 ) ); + color.g = parseInt( '0x' + hex.substring( 4, 6 ) ); + color.b = parseInt( '0x' + hex.substring( 6, 8 ) ); + break; + + case TEXTURE_TYPE.RGBA: + // RGBA texture: Four-component images specify the alpha opacity byte after red/green/blue + color.r = parseInt( '0x' + hex.substring( 2, 4 ) ); + color.g = parseInt( '0x' + hex.substring( 4, 6 ) ); + color.b = parseInt( '0x' + hex.substring( 6, 8 ) ); + color.a = parseInt( '0x' + hex.substring( 8, 10 ) ); + break; + + default: - case 1: - type = TEXTURE_TYPE.INTENSITY; - break; + } - case 2: - type = TEXTURE_TYPE.INTENSITY_ALPHA; - break; + } - case 3: - type = TEXTURE_TYPE.RGB; - break; + function getTextureType( num_components ) { - case 4: - type = TEXTURE_TYPE.RGBA; - break; + let type; - default: + switch ( num_components ) { - } + case 1: + type = TEXTURE_TYPE.INTENSITY; + break; + + case 2: + type = TEXTURE_TYPE.INTENSITY_ALPHA; + break; + + case 3: + type = TEXTURE_TYPE.RGB; + break; + + case 4: + type = TEXTURE_TYPE.RGBA; + break; - return type; + default: } - function buildPixelTextureNode( node ) { + return type; - var texture; - var wrapS = RepeatWrapping; - var wrapT = RepeatWrapping; + } + + function buildPixelTextureNode( node ) { - var fields = node.fields; + let texture; + let wrapS = RepeatWrapping; + let wrapT = RepeatWrapping; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'image': - var width = fieldValues[ 0 ]; - var height = fieldValues[ 1 ]; - var num_components = fieldValues[ 2 ]; + switch ( fieldName ) { - var useAlpha = ( num_components === 2 || num_components === 4 ); - var textureType = getTextureType( num_components ); + case 'image': + const width = fieldValues[ 0 ]; + const height = fieldValues[ 1 ]; + const num_components = fieldValues[ 2 ]; - var size = ( ( useAlpha === true ) ? 4 : 3 ) * ( width * height ); - var data = new Uint8Array( size ); + const useAlpha = ( num_components === 2 || num_components === 4 ); + const textureType = getTextureType( num_components ); - var color = { r: 0, g: 0, b: 0, a: 0 }; + const size = ( ( useAlpha === true ) ? 4 : 3 ) * ( width * height ); + const data = new Uint8Array( size ); - for ( var j = 3, k = 0, jl = fieldValues.length; j < jl; j ++, k ++ ) { + const color = { r: 0, g: 0, b: 0, a: 0 }; - parseHexColor( fieldValues[ j ], textureType, color ); + for ( let j = 3, k = 0, jl = fieldValues.length; j < jl; j ++, k ++ ) { - if ( useAlpha === true ) { + parseHexColor( fieldValues[ j ], textureType, color ); - var stride = k * 4; + if ( useAlpha === true ) { - data[ stride + 0 ] = color.r; - data[ stride + 1 ] = color.g; - data[ stride + 2 ] = color.b; - data[ stride + 3 ] = color.a; + const stride = k * 4; - } else { + data[ stride + 0 ] = color.r; + data[ stride + 1 ] = color.g; + data[ stride + 2 ] = color.b; + data[ stride + 3 ] = color.a; - var stride = k * 3; + } else { - data[ stride + 0 ] = color.r; - data[ stride + 1 ] = color.g; - data[ stride + 2 ] = color.b; + const stride = k * 3; - } + data[ stride + 0 ] = color.r; + data[ stride + 1 ] = color.g; + data[ stride + 2 ] = color.b; } - texture = new DataTexture( data, width, height, ( useAlpha === true ) ? RGBAFormat : RGBFormat ); - texture.__type = textureType; // needed for material modifications - break; + } - case 'repeatS': - if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping; - break; + texture = new DataTexture( data, width, height, ( useAlpha === true ) ? RGBAFormat : RGBFormat ); + texture.__type = textureType; // needed for material modifications + break; - case 'repeatT': - if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping; - break; + case 'repeatS': + if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'repeatT': + if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - if ( texture ) { - - texture.wrapS = wrapS; - texture.wrapT = wrapT; + } - } + if ( texture ) { - return texture; + texture.wrapS = wrapS; + texture.wrapT = wrapT; } - function buildImageTextureNode( node ) { + return texture; - var texture; - var wrapS = RepeatWrapping; - var wrapT = RepeatWrapping; + } - var fields = node.fields; + function buildImageTextureNode( node ) { - for ( var i = 0, l = fields.length; i < l; i ++ ) { + let texture; + let wrapS = RepeatWrapping; + let wrapT = RepeatWrapping; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'url': - var url = fieldValues[ 0 ]; - if ( url ) texture = textureLoader.load( url ); - break; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'repeatS': - if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping; - break; + switch ( fieldName ) { - case 'repeatT': - if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping; - break; + case 'url': + const url = fieldValues[ 0 ]; + if ( url ) texture = textureLoader.load( url ); + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'repeatS': + if ( fieldValues[ 0 ] === false ) wrapS = ClampToEdgeWrapping; + break; - } + case 'repeatT': + if ( fieldValues[ 0 ] === false ) wrapT = ClampToEdgeWrapping; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; - if ( texture ) { + } - texture.wrapS = wrapS; - texture.wrapT = wrapT; + } - } + if ( texture ) { - return texture; + texture.wrapS = wrapS; + texture.wrapT = wrapT; } - function buildTextureTransformNode( node ) { + return texture; - var transformData = { - center: new Vector2(), - rotation: new Vector2(), - scale: new Vector2(), - translation: new Vector2() - }; + } - var fields = node.fields; + function buildTextureTransformNode( node ) { - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const transformData = { + center: new Vector2(), + rotation: new Vector2(), + scale: new Vector2(), + translation: new Vector2() + }; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'center': - transformData.center.set( fieldValues[ 0 ], fieldValues[ 1 ] ); - break; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'rotation': - transformData.rotation = fieldValues[ 0 ]; - break; + switch ( fieldName ) { - case 'scale': - transformData.scale.set( fieldValues[ 0 ], fieldValues[ 1 ] ); - break; + case 'center': + transformData.center.set( fieldValues[ 0 ], fieldValues[ 1 ] ); + break; - case 'translation': - transformData.translation.set( fieldValues[ 0 ], fieldValues[ 1 ] ); - break; + case 'rotation': + transformData.rotation = fieldValues[ 0 ]; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'scale': + transformData.scale.set( fieldValues[ 0 ], fieldValues[ 1 ] ); + break; - } + case 'translation': + transformData.translation.set( fieldValues[ 0 ], fieldValues[ 1 ] ); + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; - return transformData; + } } - function buildGeometricNode( node ) { + return transformData; - return node.fields[ 0 ].values; + } - } + function buildGeometricNode( node ) { - function buildWorldInfoNode( node ) { + return node.fields[ 0 ].values; - var worldInfo = {}; + } - var fields = node.fields; + function buildWorldInfoNode( node ) { - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const worldInfo = {}; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'title': - worldInfo.title = fieldValues[ 0 ]; - break; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'info': - worldInfo.info = fieldValues; - break; + switch ( fieldName ) { - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'title': + worldInfo.title = fieldValues[ 0 ]; + break; - } + case 'info': + worldInfo.info = fieldValues; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; - return worldInfo; + } } - function buildIndexedFaceSetNode( node ) { + return worldInfo; - var color, coord, normal, texCoord; - var ccw = true, solid = true, creaseAngle = 0; - var colorIndex, coordIndex, normalIndex, texCoordIndex; - var colorPerVertex = true, normalPerVertex = true; + } - var fields = node.fields; + function buildIndexedFaceSetNode( node ) { - for ( var i = 0, l = fields.length; i < l; i ++ ) { + let color, coord, normal, texCoord; + let ccw = true, solid = true, creaseAngle = 0; + let colorIndex, coordIndex, normalIndex, texCoordIndex; + let colorPerVertex = true, normalPerVertex = true; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + const fields = node.fields; - switch ( fieldName ) { + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'color': - var colorNode = fieldValues[ 0 ]; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - if ( colorNode !== null ) { + switch ( fieldName ) { - color = getNode( colorNode ); + case 'color': + const colorNode = fieldValues[ 0 ]; - } + if ( colorNode !== null ) { - break; + color = getNode( colorNode ); - case 'coord': - var coordNode = fieldValues[ 0 ]; + } - if ( coordNode !== null ) { + break; - coord = getNode( coordNode ); + case 'coord': + const coordNode = fieldValues[ 0 ]; - } + if ( coordNode !== null ) { - break; + coord = getNode( coordNode ); - case 'normal': - var normalNode = fieldValues[ 0 ]; + } - if ( normalNode !== null ) { + break; - normal = getNode( normalNode ); + case 'normal': + const normalNode = fieldValues[ 0 ]; - } + if ( normalNode !== null ) { - break; + normal = getNode( normalNode ); - case 'texCoord': - var texCoordNode = fieldValues[ 0 ]; + } - if ( texCoordNode !== null ) { + break; - texCoord = getNode( texCoordNode ); + case 'texCoord': + const texCoordNode = fieldValues[ 0 ]; - } + if ( texCoordNode !== null ) { - break; + texCoord = getNode( texCoordNode ); - case 'ccw': - ccw = fieldValues[ 0 ]; - break; + } - case 'colorIndex': - colorIndex = fieldValues; - break; + break; - case 'colorPerVertex': - colorPerVertex = fieldValues[ 0 ]; - break; + case 'ccw': + ccw = fieldValues[ 0 ]; + break; - case 'convex': - // field not supported - break; + case 'colorIndex': + colorIndex = fieldValues; + break; - case 'coordIndex': - coordIndex = fieldValues; - break; + case 'colorPerVertex': + colorPerVertex = fieldValues[ 0 ]; + break; - case 'creaseAngle': - creaseAngle = fieldValues[ 0 ]; - break; + case 'convex': + // field not supported + break; - case 'normalIndex': - normalIndex = fieldValues; - break; + case 'coordIndex': + coordIndex = fieldValues; + break; - case 'normalPerVertex': - normalPerVertex = fieldValues[ 0 ]; - break; + case 'creaseAngle': + creaseAngle = fieldValues[ 0 ]; + break; - case 'solid': - solid = fieldValues[ 0 ]; - break; + case 'normalIndex': + normalIndex = fieldValues; + break; - case 'texCoordIndex': - texCoordIndex = fieldValues; - break; + case 'normalPerVertex': + normalPerVertex = fieldValues[ 0 ]; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'solid': + solid = fieldValues[ 0 ]; + break; - } + case 'texCoordIndex': + texCoordIndex = fieldValues; + break; + + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - if ( coordIndex === undefined ) { + } - console.warn( 'THREE.VRMLLoader: Missing coordIndex.' ); + if ( coordIndex === undefined ) { - return new BufferGeometry(); // handle VRML files with incomplete geometry definition + console.warn( 'THREE.VRMLLoader: Missing coordIndex.' ); - } + return new BufferGeometry(); // handle VRML files with incomplete geometry definition - var triangulatedCoordIndex = triangulateFaceIndex( coordIndex, ccw ); + } - var positionAttribute; - var colorAttribute; - var normalAttribute; - var uvAttribute; + const triangulatedCoordIndex = triangulateFaceIndex( coordIndex, ccw ); - if ( color ) { + let colorAttribute; + let normalAttribute; + let uvAttribute; - if ( colorPerVertex === true ) { + if ( color ) { - if ( colorIndex && colorIndex.length > 0 ) { + if ( colorPerVertex === true ) { - // if the colorIndex field is not empty, then it is used to choose colors for each vertex of the IndexedFaceSet. + if ( colorIndex && colorIndex.length > 0 ) { - var triangulatedColorIndex = triangulateFaceIndex( colorIndex, ccw ); - colorAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedColorIndex, color, 3 ); + // if the colorIndex field is not empty, then it is used to choose colors for each vertex of the IndexedFaceSet. - } else { + const triangulatedColorIndex = triangulateFaceIndex( colorIndex, ccw ); + colorAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedColorIndex, color, 3 ); - // if the colorIndex field is empty, then the coordIndex field is used to choose colors from the Color node + } else { - colorAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( color, 3 ) ); + // if the colorIndex field is empty, then the coordIndex field is used to choose colors from the Color node - } + colorAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( color, 3 ) ); - } else { + } - if ( colorIndex && colorIndex.length > 0 ) { + } else { - // if the colorIndex field is not empty, then they are used to choose one color for each face of the IndexedFaceSet + if ( colorIndex && colorIndex.length > 0 ) { - var flattenFaceColors = flattenData( color, colorIndex ); - var triangulatedFaceColors = triangulateFaceData( flattenFaceColors, coordIndex ); - colorAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceColors ); + // if the colorIndex field is not empty, then they are used to choose one color for each face of the IndexedFaceSet - } else { + const flattenFaceColors = flattenData( color, colorIndex ); + const triangulatedFaceColors = triangulateFaceData( flattenFaceColors, coordIndex ); + colorAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceColors ); - // if the colorIndex field is empty, then the color are applied to each face of the IndexedFaceSet in order + } else { - var triangulatedFaceColors = triangulateFaceData( color, coordIndex ); - colorAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceColors ); + // if the colorIndex field is empty, then the color are applied to each face of the IndexedFaceSet in order + const triangulatedFaceColors = triangulateFaceData( color, coordIndex ); + colorAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceColors ); - } } } - if ( normal ) { + } - if ( normalPerVertex === true ) { + if ( normal ) { - // consider vertex normals + if ( normalPerVertex === true ) { - if ( normalIndex && normalIndex.length > 0 ) { + // consider vertex normals - // if the normalIndex field is not empty, then it is used to choose normals for each vertex of the IndexedFaceSet. + if ( normalIndex && normalIndex.length > 0 ) { - var triangulatedNormalIndex = triangulateFaceIndex( normalIndex, ccw ); - normalAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedNormalIndex, normal, 3 ); + // if the normalIndex field is not empty, then it is used to choose normals for each vertex of the IndexedFaceSet. - } else { + const triangulatedNormalIndex = triangulateFaceIndex( normalIndex, ccw ); + normalAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedNormalIndex, normal, 3 ); - // if the normalIndex field is empty, then the coordIndex field is used to choose normals from the Normal node + } else { - normalAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( normal, 3 ) ); + // if the normalIndex field is empty, then the coordIndex field is used to choose normals from the Normal node - } + normalAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( normal, 3 ) ); - } else { + } - // consider face normals + } else { - if ( normalIndex && normalIndex.length > 0 ) { + // consider face normals - // if the normalIndex field is not empty, then they are used to choose one normal for each face of the IndexedFaceSet + if ( normalIndex && normalIndex.length > 0 ) { - var flattenFaceNormals = flattenData( normal, normalIndex ); - var triangulatedFaceNormals = triangulateFaceData( flattenFaceNormals, coordIndex ); - normalAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceNormals ); + // if the normalIndex field is not empty, then they are used to choose one normal for each face of the IndexedFaceSet - } else { + const flattenFaceNormals = flattenData( normal, normalIndex ); + const triangulatedFaceNormals = triangulateFaceData( flattenFaceNormals, coordIndex ); + normalAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceNormals ); - // if the normalIndex field is empty, then the normals are applied to each face of the IndexedFaceSet in order + } else { - var triangulatedFaceNormals = triangulateFaceData( normal, coordIndex ); - normalAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceNormals ); + // if the normalIndex field is empty, then the normals are applied to each face of the IndexedFaceSet in order - } + const triangulatedFaceNormals = triangulateFaceData( normal, coordIndex ); + normalAttribute = computeAttributeFromFaceData( triangulatedCoordIndex, triangulatedFaceNormals ); } - } else { + } - // if the normal field is NULL, then the loader should automatically generate normals, using creaseAngle to determine if and how normals are smoothed across shared vertices + } else { - normalAttribute = computeNormalAttribute( triangulatedCoordIndex, coord, creaseAngle ); + // if the normal field is NULL, then the loader should automatically generate normals, using creaseAngle to determine if and how normals are smoothed across shared vertices - } + normalAttribute = computeNormalAttribute( triangulatedCoordIndex, coord, creaseAngle ); - if ( texCoord ) { + } - // texture coordinates are always defined on vertex level + if ( texCoord ) { - if ( texCoordIndex && texCoordIndex.length > 0 ) { + // texture coordinates are always defined on vertex level - // if the texCoordIndex field is not empty, then it is used to choose texture coordinates for each vertex of the IndexedFaceSet. + if ( texCoordIndex && texCoordIndex.length > 0 ) { - var triangulatedTexCoordIndex = triangulateFaceIndex( texCoordIndex, ccw ); - uvAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedTexCoordIndex, texCoord, 2 ); + // if the texCoordIndex field is not empty, then it is used to choose texture coordinates for each vertex of the IndexedFaceSet. + const triangulatedTexCoordIndex = triangulateFaceIndex( texCoordIndex, ccw ); + uvAttribute = computeAttributeFromIndexedData( triangulatedCoordIndex, triangulatedTexCoordIndex, texCoord, 2 ); - } else { - // if the texCoordIndex field is empty, then the coordIndex array is used to choose texture coordinates from the TextureCoordinate node + } else { - uvAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( texCoord, 2 ) ); + // if the texCoordIndex field is empty, then the coordIndex array is used to choose texture coordinates from the TextureCoordinate node - } + uvAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( texCoord, 2 ) ); } - var geometry = new BufferGeometry(); - positionAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( coord, 3 ) ); + } - geometry.setAttribute( 'position', positionAttribute ); - geometry.setAttribute( 'normal', normalAttribute ); + const geometry = new BufferGeometry(); + const positionAttribute = toNonIndexedAttribute( triangulatedCoordIndex, new Float32BufferAttribute( coord, 3 ) ); - // optional attributes + geometry.setAttribute( 'position', positionAttribute ); + geometry.setAttribute( 'normal', normalAttribute ); - if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute ); - if ( uvAttribute ) geometry.setAttribute( 'uv', uvAttribute ); + // optional attributes - // "solid" influences the material so let's store it for later use + if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute ); + if ( uvAttribute ) geometry.setAttribute( 'uv', uvAttribute ); - geometry._solid = solid; - geometry._type = 'mesh'; + // "solid" influences the material so let's store it for later use - return geometry; + geometry._solid = solid; + geometry._type = 'mesh'; - } + return geometry; - function buildIndexedLineSetNode( node ) { + } - var color, coord; - var colorIndex, coordIndex; - var colorPerVertex = true; + function buildIndexedLineSetNode( node ) { - var fields = node.fields; + let color, coord; + let colorIndex, coordIndex; + let colorPerVertex = true; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'color': - var colorNode = fieldValues[ 0 ]; + switch ( fieldName ) { - if ( colorNode !== null ) { + case 'color': + const colorNode = fieldValues[ 0 ]; - color = getNode( colorNode ); + if ( colorNode !== null ) { - } + color = getNode( colorNode ); - break; + } - case 'coord': - var coordNode = fieldValues[ 0 ]; + break; - if ( coordNode !== null ) { + case 'coord': + const coordNode = fieldValues[ 0 ]; - coord = getNode( coordNode ); + if ( coordNode !== null ) { - } + coord = getNode( coordNode ); - break; + } - case 'colorIndex': - colorIndex = fieldValues; - break; + break; - case 'colorPerVertex': - colorPerVertex = fieldValues[ 0 ]; - break; + case 'colorIndex': + colorIndex = fieldValues; + break; - case 'coordIndex': - coordIndex = fieldValues; - break; + case 'colorPerVertex': + colorPerVertex = fieldValues[ 0 ]; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'coordIndex': + coordIndex = fieldValues; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - // build lines + } - var colorAttribute; + // build lines - var expandedLineIndex = expandLineIndex( coordIndex ); // create an index for three.js's linesegment primitive + let colorAttribute; - if ( color ) { + const expandedLineIndex = expandLineIndex( coordIndex ); // create an index for three.js's linesegment primitive - if ( colorPerVertex === true ) { + if ( color ) { - if ( colorIndex.length > 0 ) { + if ( colorPerVertex === true ) { - // if the colorIndex field is not empty, then one color is used for each polyline of the IndexedLineSet. + if ( colorIndex.length > 0 ) { - var expandedColorIndex = expandLineIndex( colorIndex ); // compute colors for each line segment (rendering primitve) - colorAttribute = computeAttributeFromIndexedData( expandedLineIndex, expandedColorIndex, color, 3 ); // compute data on vertex level + // if the colorIndex field is not empty, then one color is used for each polyline of the IndexedLineSet. - } else { + const expandedColorIndex = expandLineIndex( colorIndex ); // compute colors for each line segment (rendering primitve) + colorAttribute = computeAttributeFromIndexedData( expandedLineIndex, expandedColorIndex, color, 3 ); // compute data on vertex level - // if the colorIndex field is empty, then the colors are applied to each polyline of the IndexedLineSet in order. + } else { - colorAttribute = toNonIndexedAttribute( expandedLineIndex, new Float32BufferAttribute( color, 3 ) ); + // if the colorIndex field is empty, then the colors are applied to each polyline of the IndexedLineSet in order. - } + colorAttribute = toNonIndexedAttribute( expandedLineIndex, new Float32BufferAttribute( color, 3 ) ); - } else { + } - if ( colorIndex.length > 0 ) { + } else { - // if the colorIndex field is not empty, then colors are applied to each vertex of the IndexedLineSet + if ( colorIndex.length > 0 ) { - var flattenLineColors = flattenData( color, colorIndex ); // compute colors for each VRML primitve - var expandedLineColors = expandLineData( flattenLineColors, coordIndex ); // compute colors for each line segment (rendering primitve) - colorAttribute = computeAttributeFromLineData( expandedLineIndex, expandedLineColors ); // compute data on vertex level + // if the colorIndex field is not empty, then colors are applied to each vertex of the IndexedLineSet + const flattenLineColors = flattenData( color, colorIndex ); // compute colors for each VRML primitve + const expandedLineColors = expandLineData( flattenLineColors, coordIndex ); // compute colors for each line segment (rendering primitve) + colorAttribute = computeAttributeFromLineData( expandedLineIndex, expandedLineColors ); // compute data on vertex level - } else { - // if the colorIndex field is empty, then the coordIndex field is used to choose colors from the Color node + } else { - var expandedLineColors = expandLineData( color, coordIndex ); // compute colors for each line segment (rendering primitve) - colorAttribute = computeAttributeFromLineData( expandedLineIndex, expandedLineColors ); // compute data on vertex level + // if the colorIndex field is empty, then the coordIndex field is used to choose colors from the Color node - } + const expandedLineColors = expandLineData( color, coordIndex ); // compute colors for each line segment (rendering primitve) + colorAttribute = computeAttributeFromLineData( expandedLineIndex, expandedLineColors ); // compute data on vertex level } } - // + } - var geometry = new BufferGeometry(); + // - var positionAttribute = toNonIndexedAttribute( expandedLineIndex, new Float32BufferAttribute( coord, 3 ) ); - geometry.setAttribute( 'position', positionAttribute ); + const geometry = new BufferGeometry(); - if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute ); + const positionAttribute = toNonIndexedAttribute( expandedLineIndex, new Float32BufferAttribute( coord, 3 ) ); + geometry.setAttribute( 'position', positionAttribute ); - geometry._type = 'line'; + if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute ); - return geometry; + geometry._type = 'line'; - } + return geometry; - function buildPointSetNode( node ) { + } - var geometry; - var color, coord; + function buildPointSetNode( node ) { - var fields = node.fields; + let color, coord; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'color': - var colorNode = fieldValues[ 0 ]; + switch ( fieldName ) { - if ( colorNode !== null ) { + case 'color': + const colorNode = fieldValues[ 0 ]; - color = getNode( colorNode ); + if ( colorNode !== null ) { - } + color = getNode( colorNode ); - break; + } - case 'coord': - var coordNode = fieldValues[ 0 ]; + break; - if ( coordNode !== null ) { + case 'coord': + const coordNode = fieldValues[ 0 ]; - coord = getNode( coordNode ); + if ( coordNode !== null ) { - } + coord = getNode( coordNode ); - break; + } + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - var geometry = new BufferGeometry(); + } - geometry.setAttribute( 'position', new Float32BufferAttribute( coord, 3 ) ); - if ( color ) geometry.setAttribute( 'color', new Float32BufferAttribute( color, 3 ) ); + const geometry = new BufferGeometry(); - geometry._type = 'points'; + geometry.setAttribute( 'position', new Float32BufferAttribute( coord, 3 ) ); + if ( color ) geometry.setAttribute( 'color', new Float32BufferAttribute( color, 3 ) ); - return geometry; + geometry._type = 'points'; - } + return geometry; - function buildBoxNode( node ) { + } - var size = new Vector3( 2, 2, 2 ); + function buildBoxNode( node ) { - var fields = node.fields; + const size = new Vector3( 2, 2, 2 ); - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'size': - size.x = fieldValues[ 0 ]; - size.y = fieldValues[ 1 ]; - size.z = fieldValues[ 2 ]; - break; + switch ( fieldName ) { - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'size': + size.x = fieldValues[ 0 ]; + size.y = fieldValues[ 1 ]; + size.z = fieldValues[ 2 ]; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - var geometry = new BoxGeometry( size.x, size.y, size.z ); + } - return geometry; + const geometry = new BoxGeometry( size.x, size.y, size.z ); - } + return geometry; - function buildConeNode( node ) { + } - var radius = 1, height = 2, openEnded = false; + function buildConeNode( node ) { - var fields = node.fields; + let radius = 1, height = 2, openEnded = false; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'bottom': - openEnded = ! fieldValues[ 0 ]; - break; + switch ( fieldName ) { - case 'bottomRadius': - radius = fieldValues[ 0 ]; - break; + case 'bottom': + openEnded = ! fieldValues[ 0 ]; + break; - case 'height': - height = fieldValues[ 0 ]; - break; + case 'bottomRadius': + radius = fieldValues[ 0 ]; + break; - case 'side': - // field not supported - break; + case 'height': + height = fieldValues[ 0 ]; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'side': + // field not supported + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - var geometry = new ConeGeometry( radius, height, 16, 1, openEnded ); + } - return geometry; + const geometry = new ConeGeometry( radius, height, 16, 1, openEnded ); - } + return geometry; - function buildCylinderNode( node ) { + } - var radius = 1, height = 2; + function buildCylinderNode( node ) { - var fields = node.fields; + let radius = 1, height = 2; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'bottom': - // field not supported - break; + switch ( fieldName ) { - case 'radius': - radius = fieldValues[ 0 ]; - break; + case 'bottom': + // field not supported + break; - case 'height': - height = fieldValues[ 0 ]; - break; + case 'radius': + radius = fieldValues[ 0 ]; + break; - case 'side': - // field not supported - break; + case 'height': + height = fieldValues[ 0 ]; + break; - case 'top': - // field not supported - break; + case 'side': + // field not supported + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'top': + // field not supported + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - var geometry = new CylinderGeometry( radius, radius, height, 16, 1 ); + } - return geometry; + const geometry = new CylinderGeometry( radius, radius, height, 16, 1 ); - } + return geometry; - function buildSphereNode( node ) { + } - var radius = 1; + function buildSphereNode( node ) { - var fields = node.fields; + let radius = 1; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'radius': - radius = fieldValues[ 0 ]; - break; + switch ( fieldName ) { - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'radius': + radius = fieldValues[ 0 ]; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - var geometry = new SphereGeometry( radius, 16, 16 ); + } - return geometry; + const geometry = new SphereGeometry( radius, 16, 16 ); - } + return geometry; - function buildElevationGridNode( node ) { + } - var color; - var normal; - var texCoord; - var height; + function buildElevationGridNode( node ) { - var colorPerVertex = true; - var normalPerVertex = true; - var solid = true; - var ccw = true; - var creaseAngle = 0; - var xDimension = 2; - var zDimension = 2; - var xSpacing = 1; - var zSpacing = 1; + let color; + let normal; + let texCoord; + let height; - var fields = node.fields; + let colorPerVertex = true; + let normalPerVertex = true; + let solid = true; + let ccw = true; + let creaseAngle = 0; + let xDimension = 2; + let zDimension = 2; + let xSpacing = 1; + let zSpacing = 1; - for ( var i = 0, l = fields.length; i < l; i ++ ) { + const fields = node.fields; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - switch ( fieldName ) { + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'color': - var colorNode = fieldValues[ 0 ]; + switch ( fieldName ) { - if ( colorNode !== null ) { + case 'color': + const colorNode = fieldValues[ 0 ]; - color = getNode( colorNode ); + if ( colorNode !== null ) { - } + color = getNode( colorNode ); - break; + } - case 'normal': - var normalNode = fieldValues[ 0 ]; + break; - if ( normalNode !== null ) { + case 'normal': + const normalNode = fieldValues[ 0 ]; - normal = getNode( normalNode ); + if ( normalNode !== null ) { - } + normal = getNode( normalNode ); - break; + } - case 'texCoord': - var texCoordNode = fieldValues[ 0 ]; + break; - if ( texCoordNode !== null ) { + case 'texCoord': + const texCoordNode = fieldValues[ 0 ]; - texCoord = getNode( texCoordNode ); + if ( texCoordNode !== null ) { - } + texCoord = getNode( texCoordNode ); - break; + } - case 'height': - height = fieldValues; - break; + break; - case 'ccw': - ccw = fieldValues[ 0 ]; - break; + case 'height': + height = fieldValues; + break; - case 'colorPerVertex': - colorPerVertex = fieldValues[ 0 ]; - break; + case 'ccw': + ccw = fieldValues[ 0 ]; + break; - case 'creaseAngle': - creaseAngle = fieldValues[ 0 ]; - break; + case 'colorPerVertex': + colorPerVertex = fieldValues[ 0 ]; + break; - case 'normalPerVertex': - normalPerVertex = fieldValues[ 0 ]; - break; + case 'creaseAngle': + creaseAngle = fieldValues[ 0 ]; + break; - case 'solid': - solid = fieldValues[ 0 ]; - break; + case 'normalPerVertex': + normalPerVertex = fieldValues[ 0 ]; + break; - case 'xDimension': - xDimension = fieldValues[ 0 ]; - break; + case 'solid': + solid = fieldValues[ 0 ]; + break; - case 'xSpacing': - xSpacing = fieldValues[ 0 ]; - break; + case 'xDimension': + xDimension = fieldValues[ 0 ]; + break; - case 'zDimension': - zDimension = fieldValues[ 0 ]; - break; + case 'xSpacing': + xSpacing = fieldValues[ 0 ]; + break; - case 'zSpacing': - zSpacing = fieldValues[ 0 ]; - break; + case 'zDimension': + zDimension = fieldValues[ 0 ]; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'zSpacing': + zSpacing = fieldValues[ 0 ]; + break; - } + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - // vertex data + } - var vertices = []; - var normals = []; - var colors = []; - var uvs = []; + // vertex data - for ( var i = 0; i < zDimension; i ++ ) { + const vertices = []; + const normals = []; + const colors = []; + const uvs = []; - for ( var j = 0; j < xDimension; j ++ ) { + for ( let i = 0; i < zDimension; i ++ ) { - // compute a row major index + for ( let j = 0; j < xDimension; j ++ ) { - var index = ( i * xDimension ) + j; + // compute a row major index - // vertices + const index = ( i * xDimension ) + j; - var x = xSpacing * i; - var y = height[ index ]; - var z = zSpacing * j; + // vertices - vertices.push( x, y, z ); + const x = xSpacing * i; + const y = height[ index ]; + const z = zSpacing * j; - // colors + vertices.push( x, y, z ); - if ( color && colorPerVertex === true ) { + // colors - var r = color[ index * 3 + 0 ]; - var g = color[ index * 3 + 1 ]; - var b = color[ index * 3 + 2 ]; + if ( color && colorPerVertex === true ) { - colors.push( r, g, b ); + const r = color[ index * 3 + 0 ]; + const g = color[ index * 3 + 1 ]; + const b = color[ index * 3 + 2 ]; - } + colors.push( r, g, b ); - // normals + } - if ( normal && normalPerVertex === true ) { + // normals - var xn = normal[ index * 3 + 0 ]; - var yn = normal[ index * 3 + 1 ]; - var zn = normal[ index * 3 + 2 ]; + if ( normal && normalPerVertex === true ) { - normals.push( xn, yn, zn ); + const xn = normal[ index * 3 + 0 ]; + const yn = normal[ index * 3 + 1 ]; + const zn = normal[ index * 3 + 2 ]; - } + normals.push( xn, yn, zn ); - // uvs + } - if ( texCoord ) { + // uvs - var s = texCoord[ index * 2 + 0 ]; - var t = texCoord[ index * 2 + 1 ]; + if ( texCoord ) { - uvs.push( s, t ); + const s = texCoord[ index * 2 + 0 ]; + const t = texCoord[ index * 2 + 1 ]; + uvs.push( s, t ); - } else { - uvs.push( i / ( xDimension - 1 ), j / ( zDimension - 1 ) ); + } else { - } + uvs.push( i / ( xDimension - 1 ), j / ( zDimension - 1 ) ); } } - // indices + } - var indices = []; + // indices - for ( var i = 0; i < xDimension - 1; i ++ ) { + const indices = []; - for ( var j = 0; j < zDimension - 1; j ++ ) { + for ( let i = 0; i < xDimension - 1; i ++ ) { - // from https://tecfa.unige.ch/guides/vrml/vrml97/spec/part1/nodesRef.html#ElevationGrid + for ( let j = 0; j < zDimension - 1; j ++ ) { - var a = i + j * xDimension; - var b = i + ( j + 1 ) * xDimension; - var c = ( i + 1 ) + ( j + 1 ) * xDimension; - var d = ( i + 1 ) + j * xDimension; + // from https://tecfa.unige.ch/guides/vrml/vrml97/spec/part1/nodesRef.html#ElevationGrid - // faces + const a = i + j * xDimension; + const b = i + ( j + 1 ) * xDimension; + const c = ( i + 1 ) + ( j + 1 ) * xDimension; + const d = ( i + 1 ) + j * xDimension; - if ( ccw === true ) { + // faces - indices.push( a, c, b ); - indices.push( c, a, d ); + if ( ccw === true ) { - } else { + indices.push( a, c, b ); + indices.push( c, a, d ); - indices.push( a, b, c ); - indices.push( c, d, a ); + } else { - } + indices.push( a, b, c ); + indices.push( c, d, a ); } } - // + } - var positionAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( vertices, 3 ) ); - var uvAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( uvs, 2 ) ); - var colorAttribute; - var normalAttribute; + // - // color attribute + const positionAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( vertices, 3 ) ); + const uvAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( uvs, 2 ) ); + let colorAttribute; + let normalAttribute; - if ( color ) { + // color attribute - if ( colorPerVertex === false ) { + if ( color ) { - for ( var i = 0; i < xDimension - 1; i ++ ) { + if ( colorPerVertex === false ) { - for ( var j = 0; j < zDimension - 1; j ++ ) { + for ( let i = 0; i < xDimension - 1; i ++ ) { - var index = i + j * ( xDimension - 1 ); + for ( let j = 0; j < zDimension - 1; j ++ ) { - var r = color[ index * 3 + 0 ]; - var g = color[ index * 3 + 1 ]; - var b = color[ index * 3 + 2 ]; + const index = i + j * ( xDimension - 1 ); - // one color per quad + const r = color[ index * 3 + 0 ]; + const g = color[ index * 3 + 1 ]; + const b = color[ index * 3 + 2 ]; - colors.push( r, g, b ); colors.push( r, g, b ); colors.push( r, g, b ); - colors.push( r, g, b ); colors.push( r, g, b ); colors.push( r, g, b ); + // one color per quad - } + colors.push( r, g, b ); colors.push( r, g, b ); colors.push( r, g, b ); + colors.push( r, g, b ); colors.push( r, g, b ); colors.push( r, g, b ); } - colorAttribute = new Float32BufferAttribute( colors, 3 ); + } - } else { + colorAttribute = new Float32BufferAttribute( colors, 3 ); - colorAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( colors, 3 ) ); + } else { - } + colorAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( colors, 3 ) ); } - // normal attribute + } - if ( normal ) { + // normal attribute - if ( normalPerVertex === false ) { + if ( normal ) { - for ( var i = 0; i < xDimension - 1; i ++ ) { + if ( normalPerVertex === false ) { - for ( var j = 0; j < zDimension - 1; j ++ ) { + for ( let i = 0; i < xDimension - 1; i ++ ) { - var index = i + j * ( xDimension - 1 ); + for ( let j = 0; j < zDimension - 1; j ++ ) { - var xn = normal[ index * 3 + 0 ]; - var yn = normal[ index * 3 + 1 ]; - var zn = normal[ index * 3 + 2 ]; + const index = i + j * ( xDimension - 1 ); - // one normal per quad + const xn = normal[ index * 3 + 0 ]; + const yn = normal[ index * 3 + 1 ]; + const zn = normal[ index * 3 + 2 ]; - normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); - normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); + // one normal per quad - } + normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); + normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); normals.push( xn, yn, zn ); } - normalAttribute = new Float32BufferAttribute( normals, 3 ); - - } else { - - normalAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( normals, 3 ) ); - } + normalAttribute = new Float32BufferAttribute( normals, 3 ); + } else { - normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle ); + normalAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( normals, 3 ) ); } - // build geometry + } else { - var geometry = new BufferGeometry(); - geometry.setAttribute( 'position', positionAttribute ); - geometry.setAttribute( 'normal', normalAttribute ); - geometry.setAttribute( 'uv', uvAttribute ); + normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle ); - if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute ); + } - // "solid" influences the material so let's store it for later use + // build geometry - geometry._solid = solid; - geometry._type = 'mesh'; + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', positionAttribute ); + geometry.setAttribute( 'normal', normalAttribute ); + geometry.setAttribute( 'uv', uvAttribute ); - return geometry; + if ( colorAttribute ) geometry.setAttribute( 'color', colorAttribute ); - } + // "solid" influences the material so let's store it for later use - function buildExtrusionNode( node ) { + geometry._solid = solid; + geometry._type = 'mesh'; - var crossSection = [ 1, 1, 1, - 1, - 1, - 1, - 1, 1, 1, 1 ]; - var spine = [ 0, 0, 0, 0, 1, 0 ]; - var scale; - var orientation; + return geometry; - var beginCap = true; - var ccw = true; - var creaseAngle = 0; - var endCap = true; - var solid = true; + } - var fields = node.fields; + function buildExtrusionNode( node ) { - for ( var i = 0, l = fields.length; i < l; i ++ ) { + let crossSection = [ 1, 1, 1, - 1, - 1, - 1, - 1, 1, 1, 1 ]; + let spine = [ 0, 0, 0, 0, 1, 0 ]; + let scale; + let orientation; - var field = fields[ i ]; - var fieldName = field.name; - var fieldValues = field.values; + let beginCap = true; + let ccw = true; + let creaseAngle = 0; + let endCap = true; + let solid = true; - switch ( fieldName ) { + const fields = node.fields; - case 'beginCap': - beginCap = fieldValues[ 0 ]; - break; + for ( let i = 0, l = fields.length; i < l; i ++ ) { - case 'ccw': - ccw = fieldValues[ 0 ]; - break; + const field = fields[ i ]; + const fieldName = field.name; + const fieldValues = field.values; - case 'convex': - // field not supported - break; + switch ( fieldName ) { - case 'creaseAngle': - creaseAngle = fieldValues[ 0 ]; - break; + case 'beginCap': + beginCap = fieldValues[ 0 ]; + break; - case 'crossSection': - crossSection = fieldValues; - break; + case 'ccw': + ccw = fieldValues[ 0 ]; + break; - case 'endCap': - endCap = fieldValues[ 0 ]; - break; + case 'convex': + // field not supported + break; - case 'orientation': - orientation = fieldValues; - break; + case 'creaseAngle': + creaseAngle = fieldValues[ 0 ]; + break; - case 'scale': - scale = fieldValues; - break; + case 'crossSection': + crossSection = fieldValues; + break; - case 'solid': - solid = fieldValues[ 0 ]; - break; + case 'endCap': + endCap = fieldValues[ 0 ]; + break; - case 'spine': - spine = fieldValues; // only extrusion along the Y-axis are supported so far - break; + case 'orientation': + orientation = fieldValues; + break; - default: - console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); - break; + case 'scale': + scale = fieldValues; + break; - } + case 'solid': + solid = fieldValues[ 0 ]; + break; + + case 'spine': + spine = fieldValues; // only extrusion along the Y-axis are supported so far + break; + + default: + console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName ); + break; } - var crossSectionClosed = ( crossSection[ 0 ] === crossSection[ crossSection.length - 2 ] && crossSection[ 1 ] === crossSection[ crossSection.length - 1 ] ); + } - // vertices + const crossSectionClosed = ( crossSection[ 0 ] === crossSection[ crossSection.length - 2 ] && crossSection[ 1 ] === crossSection[ crossSection.length - 1 ] ); - var vertices = []; - var spineVector = new Vector3(); - var scaling = new Vector3(); + // vertices - var axis = new Vector3(); - var vertex = new Vector3(); - var quaternion = new Quaternion(); + const vertices = []; + const spineVector = new Vector3(); + const scaling = new Vector3(); - for ( var i = 0, j = 0, o = 0, il = spine.length; i < il; i += 3, j += 2, o += 4 ) { + const axis = new Vector3(); + const vertex = new Vector3(); + const quaternion = new Quaternion(); - spineVector.fromArray( spine, i ); + for ( let i = 0, j = 0, o = 0, il = spine.length; i < il; i += 3, j += 2, o += 4 ) { - scaling.x = scale ? scale[ j + 0 ] : 1; - scaling.y = 1; - scaling.z = scale ? scale[ j + 1 ] : 1; + spineVector.fromArray( spine, i ); - axis.x = orientation ? orientation[ o + 0 ] : 0; - axis.y = orientation ? orientation[ o + 1 ] : 0; - axis.z = orientation ? orientation[ o + 2 ] : 1; - var angle = orientation ? orientation[ o + 3 ] : 0; + scaling.x = scale ? scale[ j + 0 ] : 1; + scaling.y = 1; + scaling.z = scale ? scale[ j + 1 ] : 1; - for ( var k = 0, kl = crossSection.length; k < kl; k += 2 ) { + axis.x = orientation ? orientation[ o + 0 ] : 0; + axis.y = orientation ? orientation[ o + 1 ] : 0; + axis.z = orientation ? orientation[ o + 2 ] : 1; + const angle = orientation ? orientation[ o + 3 ] : 0; - vertex.x = crossSection[ k + 0 ]; - vertex.y = 0; - vertex.z = crossSection[ k + 1 ]; + for ( let k = 0, kl = crossSection.length; k < kl; k += 2 ) { - // scale + vertex.x = crossSection[ k + 0 ]; + vertex.y = 0; + vertex.z = crossSection[ k + 1 ]; - vertex.multiply( scaling ); + // scale - // rotate + vertex.multiply( scaling ); - quaternion.setFromAxisAngle( axis, angle ); - vertex.applyQuaternion( quaternion ); + // rotate - // translate + quaternion.setFromAxisAngle( axis, angle ); + vertex.applyQuaternion( quaternion ); - vertex.add( spineVector ); + // translate - vertices.push( vertex.x, vertex.y, vertex.z ); + vertex.add( spineVector ); - } + vertices.push( vertex.x, vertex.y, vertex.z ); } - // indices + } - var indices = []; + // indices - var spineCount = spine.length / 3; - var crossSectionCount = crossSection.length / 2; + const indices = []; - for ( var i = 0; i < spineCount - 1; i ++ ) { + const spineCount = spine.length / 3; + const crossSectionCount = crossSection.length / 2; - for ( var j = 0; j < crossSectionCount - 1; j ++ ) { + for ( let i = 0; i < spineCount - 1; i ++ ) { - var a = j + i * crossSectionCount; - var b = ( j + 1 ) + i * crossSectionCount; - var c = j + ( i + 1 ) * crossSectionCount; - var d = ( j + 1 ) + ( i + 1 ) * crossSectionCount; + for ( let j = 0; j < crossSectionCount - 1; j ++ ) { - if ( ( j === crossSectionCount - 2 ) && ( crossSectionClosed === true ) ) { + const a = j + i * crossSectionCount; + let b = ( j + 1 ) + i * crossSectionCount; + const c = j + ( i + 1 ) * crossSectionCount; + let d = ( j + 1 ) + ( i + 1 ) * crossSectionCount; - b = i * crossSectionCount; - d = ( i + 1 ) * crossSectionCount; + if ( ( j === crossSectionCount - 2 ) && ( crossSectionClosed === true ) ) { - } + b = i * crossSectionCount; + d = ( i + 1 ) * crossSectionCount; - if ( ccw === true ) { + } - indices.push( a, b, c ); - indices.push( c, b, d ); + if ( ccw === true ) { - } else { + indices.push( a, b, c ); + indices.push( c, b, d ); - indices.push( a, c, b ); - indices.push( c, d, b ); + } else { - } + indices.push( a, c, b ); + indices.push( c, d, b ); } } - // triangulate cap + } - if ( beginCap === true || endCap === true ) { + // triangulate cap - var contour = []; + if ( beginCap === true || endCap === true ) { - for ( var i = 0, l = crossSection.length; i < l; i += 2 ) { + const contour = []; - contour.push( new Vector2( crossSection[ i ], crossSection[ i + 1 ] ) ); + for ( let i = 0, l = crossSection.length; i < l; i += 2 ) { - } + contour.push( new Vector2( crossSection[ i ], crossSection[ i + 1 ] ) ); - var faces = ShapeUtils.triangulateShape( contour, [] ); - var capIndices = []; + } - for ( var i = 0, l = faces.length; i < l; i ++ ) { + const faces = ShapeUtils.triangulateShape( contour, [] ); + const capIndices = []; - var face = faces[ i ]; + for ( let i = 0, l = faces.length; i < l; i ++ ) { - capIndices.push( face[ 0 ], face[ 1 ], face[ 2 ] ); + const face = faces[ i ]; - } + capIndices.push( face[ 0 ], face[ 1 ], face[ 2 ] ); - // begin cap + } - if ( beginCap === true ) { + // begin cap - for ( var i = 0, l = capIndices.length; i < l; i += 3 ) { + if ( beginCap === true ) { - if ( ccw === true ) { + for ( let i = 0, l = capIndices.length; i < l; i += 3 ) { - indices.push( capIndices[ i + 0 ], capIndices[ i + 1 ], capIndices[ i + 2 ] ); + if ( ccw === true ) { - } else { + indices.push( capIndices[ i + 0 ], capIndices[ i + 1 ], capIndices[ i + 2 ] ); - indices.push( capIndices[ i + 0 ], capIndices[ i + 2 ], capIndices[ i + 1 ] ); + } else { - } + indices.push( capIndices[ i + 0 ], capIndices[ i + 2 ], capIndices[ i + 1 ] ); } } - // end cap + } - if ( endCap === true ) { + // end cap - var indexOffset = crossSectionCount * ( spineCount - 1 ); // references to the first vertex of the last cross section + if ( endCap === true ) { - for ( var i = 0, l = capIndices.length; i < l; i += 3 ) { + const indexOffset = crossSectionCount * ( spineCount - 1 ); // references to the first vertex of the last cross section - if ( ccw === true ) { + for ( let i = 0, l = capIndices.length; i < l; i += 3 ) { - indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 2 ], indexOffset + capIndices[ i + 1 ] ); + if ( ccw === true ) { - } else { + indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 2 ], indexOffset + capIndices[ i + 1 ] ); - indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 1 ], indexOffset + capIndices[ i + 2 ] ); + } else { - } + indices.push( indexOffset + capIndices[ i + 0 ], indexOffset + capIndices[ i + 1 ], indexOffset + capIndices[ i + 2 ] ); } @@ -2682,593 +2675,597 @@ var VRMLLoader = ( function () { } - var positionAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( vertices, 3 ) ); - var normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle ); + } - var geometry = new BufferGeometry(); - geometry.setAttribute( 'position', positionAttribute ); - geometry.setAttribute( 'normal', normalAttribute ); - // no uvs yet + const positionAttribute = toNonIndexedAttribute( indices, new Float32BufferAttribute( vertices, 3 ) ); + const normalAttribute = computeNormalAttribute( indices, vertices, creaseAngle ); - // "solid" influences the material so let's store it for later use + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', positionAttribute ); + geometry.setAttribute( 'normal', normalAttribute ); + // no uvs yet - geometry._solid = solid; - geometry._type = 'mesh'; + // "solid" influences the material so let's store it for later use - return geometry; + geometry._solid = solid; + geometry._type = 'mesh'; - } + return geometry; - // helper functions + } - function resolveUSE( identifier ) { + // helper functions - var node = nodeMap[ identifier ]; - var build = getNode( node ); + function resolveUSE( identifier ) { - // because the same 3D objects can have different transformations, it's necessary to clone them. - // materials can be influenced by the geometry (e.g. vertex normals). cloning is necessary to avoid - // any side effects + const node = nodeMap[ identifier ]; + const build = getNode( node ); - return ( build.isObject3D || build.isMaterial ) ? build.clone() : build; + // because the same 3D objects can have different transformations, it's necessary to clone them. + // materials can be influenced by the geometry (e.g. vertex normals). cloning is necessary to avoid + // any side effects - } + return ( build.isObject3D || build.isMaterial ) ? build.clone() : build; - function parseFieldChildren( children, owner ) { + } - for ( var i = 0, l = children.length; i < l; i ++ ) { + function parseFieldChildren( children, owner ) { - var object = getNode( children[ i ] ); + for ( let i = 0, l = children.length; i < l; i ++ ) { - if ( object instanceof Object3D ) owner.add( object ); + const object = getNode( children[ i ] ); - } + if ( object instanceof Object3D ) owner.add( object ); } - function triangulateFaceIndex( index, ccw ) { + } - var indices = []; + function triangulateFaceIndex( index, ccw ) { - // since face defintions can have more than three vertices, it's necessary to - // perform a simple triangulation + const indices = []; - var start = 0; + // since face defintions can have more than three vertices, it's necessary to + // perform a simple triangulation - for ( var i = 0, l = index.length; i < l; i ++ ) { + let start = 0; - var i1 = index[ start ]; - var i2 = index[ i + ( ccw ? 1 : 2 ) ]; - var i3 = index[ i + ( ccw ? 2 : 1 ) ]; + for ( let i = 0, l = index.length; i < l; i ++ ) { - indices.push( i1, i2, i3 ); + const i1 = index[ start ]; + const i2 = index[ i + ( ccw ? 1 : 2 ) ]; + const i3 = index[ i + ( ccw ? 2 : 1 ) ]; - // an index of -1 indicates that the current face has ended and the next one begins + indices.push( i1, i2, i3 ); - if ( index[ i + 3 ] === - 1 || i + 3 >= l ) { + // an index of -1 indicates that the current face has ended and the next one begins - i += 3; - start = i + 1; + if ( index[ i + 3 ] === - 1 || i + 3 >= l ) { - } + i += 3; + start = i + 1; } - return indices; - } - function triangulateFaceData( data, index ) { + return indices; + + } - var triangulatedData = []; + function triangulateFaceData( data, index ) { - var start = 0; + const triangulatedData = []; - for ( var i = 0, l = index.length; i < l; i ++ ) { + let start = 0; - var stride = start * 3; + for ( let i = 0, l = index.length; i < l; i ++ ) { - var x = data[ stride ]; - var y = data[ stride + 1 ]; - var z = data[ stride + 2 ]; + const stride = start * 3; - triangulatedData.push( x, y, z ); + const x = data[ stride ]; + const y = data[ stride + 1 ]; + const z = data[ stride + 2 ]; - // an index of -1 indicates that the current face has ended and the next one begins + triangulatedData.push( x, y, z ); - if ( index[ i + 3 ] === - 1 || i + 3 >= l ) { + // an index of -1 indicates that the current face has ended and the next one begins - i += 3; - start ++; + if ( index[ i + 3 ] === - 1 || i + 3 >= l ) { - } + i += 3; + start ++; } - return triangulatedData; - } - function flattenData( data, index ) { + return triangulatedData; - var flattenData = []; + } - for ( var i = 0, l = index.length; i < l; i ++ ) { + function flattenData( data, index ) { - var i1 = index[ i ]; + const flattenData = []; - var stride = i1 * 3; + for ( let i = 0, l = index.length; i < l; i ++ ) { - var x = data[ stride ]; - var y = data[ stride + 1 ]; - var z = data[ stride + 2 ]; + const i1 = index[ i ]; - flattenData.push( x, y, z ); + const stride = i1 * 3; - } + const x = data[ stride ]; + const y = data[ stride + 1 ]; + const z = data[ stride + 2 ]; - return flattenData; + flattenData.push( x, y, z ); } - function expandLineIndex( index ) { + return flattenData; - var indices = []; + } - for ( var i = 0, l = index.length; i < l; i ++ ) { + function expandLineIndex( index ) { - var i1 = index[ i ]; - var i2 = index[ i + 1 ]; + const indices = []; - indices.push( i1, i2 ); + for ( let i = 0, l = index.length; i < l; i ++ ) { - // an index of -1 indicates that the current line has ended and the next one begins + const i1 = index[ i ]; + const i2 = index[ i + 1 ]; - if ( index[ i + 2 ] === - 1 || i + 2 >= l ) { + indices.push( i1, i2 ); - i += 2; + // an index of -1 indicates that the current line has ended and the next one begins - } + if ( index[ i + 2 ] === - 1 || i + 2 >= l ) { - } + i += 2; - return indices; + } } - function expandLineData( data, index ) { + return indices; - var triangulatedData = []; + } - var start = 0; + function expandLineData( data, index ) { - for ( var i = 0, l = index.length; i < l; i ++ ) { + const triangulatedData = []; - var stride = start * 3; + let start = 0; - var x = data[ stride ]; - var y = data[ stride + 1 ]; - var z = data[ stride + 2 ]; + for ( let i = 0, l = index.length; i < l; i ++ ) { - triangulatedData.push( x, y, z ); + const stride = start * 3; - // an index of -1 indicates that the current line has ended and the next one begins + const x = data[ stride ]; + const y = data[ stride + 1 ]; + const z = data[ stride + 2 ]; - if ( index[ i + 2 ] === - 1 || i + 2 >= l ) { + triangulatedData.push( x, y, z ); - i += 2; - start ++; + // an index of -1 indicates that the current line has ended and the next one begins - } + if ( index[ i + 2 ] === - 1 || i + 2 >= l ) { - } + i += 2; + start ++; - return triangulatedData; + } } - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); + return triangulatedData; + + } - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); + const vA = new Vector3(); + const vB = new Vector3(); + const vC = new Vector3(); - function computeAttributeFromIndexedData( coordIndex, index, data, itemSize ) { + const uvA = new Vector2(); + const uvB = new Vector2(); + const uvC = new Vector2(); - var array = []; + function computeAttributeFromIndexedData( coordIndex, index, data, itemSize ) { - // we use the coordIndex.length as delimiter since normalIndex must contain at least as many indices + const array = []; - for ( var i = 0, l = coordIndex.length; i < l; i += 3 ) { + // we use the coordIndex.length as delimiter since normalIndex must contain at least as many indices - var a = index[ i ]; - var b = index[ i + 1 ]; - var c = index[ i + 2 ]; + for ( let i = 0, l = coordIndex.length; i < l; i += 3 ) { - if ( itemSize === 2 ) { + const a = index[ i ]; + const b = index[ i + 1 ]; + const c = index[ i + 2 ]; - uvA.fromArray( data, a * itemSize ); - uvB.fromArray( data, b * itemSize ); - uvC.fromArray( data, c * itemSize ); + if ( itemSize === 2 ) { - array.push( uvA.x, uvA.y ); - array.push( uvB.x, uvB.y ); - array.push( uvC.x, uvC.y ); + uvA.fromArray( data, a * itemSize ); + uvB.fromArray( data, b * itemSize ); + uvC.fromArray( data, c * itemSize ); - } else { + array.push( uvA.x, uvA.y ); + array.push( uvB.x, uvB.y ); + array.push( uvC.x, uvC.y ); - vA.fromArray( data, a * itemSize ); - vB.fromArray( data, b * itemSize ); - vC.fromArray( data, c * itemSize ); + } else { - array.push( vA.x, vA.y, vA.z ); - array.push( vB.x, vB.y, vB.z ); - array.push( vC.x, vC.y, vC.z ); + vA.fromArray( data, a * itemSize ); + vB.fromArray( data, b * itemSize ); + vC.fromArray( data, c * itemSize ); - } + array.push( vA.x, vA.y, vA.z ); + array.push( vB.x, vB.y, vB.z ); + array.push( vC.x, vC.y, vC.z ); } - return new Float32BufferAttribute( array, itemSize ); - } - function computeAttributeFromFaceData( index, faceData ) { + return new Float32BufferAttribute( array, itemSize ); - var array = []; + } - for ( var i = 0, j = 0, l = index.length; i < l; i += 3, j ++ ) { + function computeAttributeFromFaceData( index, faceData ) { - vA.fromArray( faceData, j * 3 ); + const array = []; - array.push( vA.x, vA.y, vA.z ); - array.push( vA.x, vA.y, vA.z ); - array.push( vA.x, vA.y, vA.z ); + for ( let i = 0, j = 0, l = index.length; i < l; i += 3, j ++ ) { - } + vA.fromArray( faceData, j * 3 ); - return new Float32BufferAttribute( array, 3 ); + array.push( vA.x, vA.y, vA.z ); + array.push( vA.x, vA.y, vA.z ); + array.push( vA.x, vA.y, vA.z ); } - function computeAttributeFromLineData( index, lineData ) { + return new Float32BufferAttribute( array, 3 ); - var array = []; + } - for ( var i = 0, j = 0, l = index.length; i < l; i += 2, j ++ ) { + function computeAttributeFromLineData( index, lineData ) { - vA.fromArray( lineData, j * 3 ); + const array = []; - array.push( vA.x, vA.y, vA.z ); - array.push( vA.x, vA.y, vA.z ); + for ( let i = 0, j = 0, l = index.length; i < l; i += 2, j ++ ) { - } + vA.fromArray( lineData, j * 3 ); - return new Float32BufferAttribute( array, 3 ); + array.push( vA.x, vA.y, vA.z ); + array.push( vA.x, vA.y, vA.z ); } - function toNonIndexedAttribute( indices, attribute ) { + return new Float32BufferAttribute( array, 3 ); - var array = attribute.array; - var itemSize = attribute.itemSize; + } - var array2 = new array.constructor( indices.length * itemSize ); + function toNonIndexedAttribute( indices, attribute ) { - var index = 0, index2 = 0; + const array = attribute.array; + const itemSize = attribute.itemSize; - for ( var i = 0, l = indices.length; i < l; i ++ ) { + const array2 = new array.constructor( indices.length * itemSize ); - index = indices[ i ] * itemSize; + let index = 0, index2 = 0; - for ( var j = 0; j < itemSize; j ++ ) { + for ( let i = 0, l = indices.length; i < l; i ++ ) { - array2[ index2 ++ ] = array[ index ++ ]; + index = indices[ i ] * itemSize; - } + for ( let j = 0; j < itemSize; j ++ ) { - } + array2[ index2 ++ ] = array[ index ++ ]; - return new Float32BufferAttribute( array2, itemSize ); + } } - var ab = new Vector3(); - var cb = new Vector3(); + return new Float32BufferAttribute( array2, itemSize ); - function computeNormalAttribute( index, coord, creaseAngle ) { + } - var faces = []; - var vertexNormals = {}; + const ab = new Vector3(); + const cb = new Vector3(); - // prepare face and raw vertex normals + function computeNormalAttribute( index, coord, creaseAngle ) { - for ( var i = 0, l = index.length; i < l; i += 3 ) { + const faces = []; + const vertexNormals = {}; - var a = index[ i ]; - var b = index[ i + 1 ]; - var c = index[ i + 2 ]; + // prepare face and raw vertex normals - var face = new Face( a, b, c ); + for ( let i = 0, l = index.length; i < l; i += 3 ) { - vA.fromArray( coord, a * 3 ); - vB.fromArray( coord, b * 3 ); - vC.fromArray( coord, c * 3 ); + const a = index[ i ]; + const b = index[ i + 1 ]; + const c = index[ i + 2 ]; - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); + const face = new Face( a, b, c ); - cb.normalize(); + vA.fromArray( coord, a * 3 ); + vB.fromArray( coord, b * 3 ); + vC.fromArray( coord, c * 3 ); - face.normal.copy( cb ); + cb.subVectors( vC, vB ); + ab.subVectors( vA, vB ); + cb.cross( ab ); - if ( vertexNormals[ a ] === undefined ) vertexNormals[ a ] = []; - if ( vertexNormals[ b ] === undefined ) vertexNormals[ b ] = []; - if ( vertexNormals[ c ] === undefined ) vertexNormals[ c ] = []; + cb.normalize(); - vertexNormals[ a ].push( face.normal ); - vertexNormals[ b ].push( face.normal ); - vertexNormals[ c ].push( face.normal ); + face.normal.copy( cb ); - faces.push( face ); + if ( vertexNormals[ a ] === undefined ) vertexNormals[ a ] = []; + if ( vertexNormals[ b ] === undefined ) vertexNormals[ b ] = []; + if ( vertexNormals[ c ] === undefined ) vertexNormals[ c ] = []; - } + vertexNormals[ a ].push( face.normal ); + vertexNormals[ b ].push( face.normal ); + vertexNormals[ c ].push( face.normal ); - // compute vertex normals and build final geometry + faces.push( face ); - var normals = []; + } - for ( var i = 0, l = faces.length; i < l; i ++ ) { + // compute vertex normals and build final geometry - var face = faces[ i ]; + const normals = []; - var nA = weightedNormal( vertexNormals[ face.a ], face.normal, creaseAngle ); - var nB = weightedNormal( vertexNormals[ face.b ], face.normal, creaseAngle ); - var nC = weightedNormal( vertexNormals[ face.c ], face.normal, creaseAngle ); + for ( let i = 0, l = faces.length; i < l; i ++ ) { - vA.fromArray( coord, face.a * 3 ); - vB.fromArray( coord, face.b * 3 ); - vC.fromArray( coord, face.c * 3 ); + const face = faces[ i ]; - normals.push( nA.x, nA.y, nA.z ); - normals.push( nB.x, nB.y, nB.z ); - normals.push( nC.x, nC.y, nC.z ); + const nA = weightedNormal( vertexNormals[ face.a ], face.normal, creaseAngle ); + const nB = weightedNormal( vertexNormals[ face.b ], face.normal, creaseAngle ); + const nC = weightedNormal( vertexNormals[ face.c ], face.normal, creaseAngle ); - } + vA.fromArray( coord, face.a * 3 ); + vB.fromArray( coord, face.b * 3 ); + vC.fromArray( coord, face.c * 3 ); - return new Float32BufferAttribute( normals, 3 ); + normals.push( nA.x, nA.y, nA.z ); + normals.push( nB.x, nB.y, nB.z ); + normals.push( nC.x, nC.y, nC.z ); } - function weightedNormal( normals, vector, creaseAngle ) { + return new Float32BufferAttribute( normals, 3 ); - var normal = new Vector3(); + } - if ( creaseAngle === 0 ) { + function weightedNormal( normals, vector, creaseAngle ) { - normal.copy( vector ); + const normal = new Vector3(); - } else { + if ( creaseAngle === 0 ) { - for ( var i = 0, l = normals.length; i < l; i ++ ) { + normal.copy( vector ); - if ( normals[ i ].angleTo( vector ) < creaseAngle ) { + } else { - normal.add( normals[ i ] ); + for ( let i = 0, l = normals.length; i < l; i ++ ) { - } + if ( normals[ i ].angleTo( vector ) < creaseAngle ) { + + normal.add( normals[ i ] ); } } - return normal.normalize(); - } - function toColorArray( colors ) { + return normal.normalize(); - var array = []; + } - for ( var i = 0, l = colors.length; i < l; i += 3 ) { + function toColorArray( colors ) { - array.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); + const array = []; - } + for ( let i = 0, l = colors.length; i < l; i += 3 ) { - return array; + array.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); } - /** - * Vertically paints the faces interpolating between the - * specified colors at the specified angels. This is used for the Background - * node, but could be applied to other nodes with multiple faces as well. - * - * When used with the Background node, default is directionIsDown is true if - * interpolating the skyColor down from the Zenith. When interpolationg up from - * the Nadir i.e. interpolating the groundColor, the directionIsDown is false. - * - * The first angle is never specified, it is the Zenith (0 rad). Angles are specified - * in radians. The geometry is thought a sphere, but could be anything. The color interpolation - * is linear along the Y axis in any case. - * - * You must specify one more color than you have angles at the beginning of the colors array. - * This is the color of the Zenith (the top of the shape). - * - * @param {BufferGeometry} geometry - * @param {number} radius - * @param {array} angles - * @param {array} colors - * @param {boolean} topDown - Whether to work top down or bottom up. - */ - function paintFaces( geometry, radius, angles, colors, topDown ) { + return array; - // compute threshold values + } + + /** + * Vertically paints the faces interpolating between the + * specified colors at the specified angels. This is used for the Background + * node, but could be applied to other nodes with multiple faces as well. + * + * When used with the Background node, default is directionIsDown is true if + * interpolating the skyColor down from the Zenith. When interpolationg up from + * the Nadir i.e. interpolating the groundColor, the directionIsDown is false. + * + * The first angle is never specified, it is the Zenith (0 rad). Angles are specified + * in radians. The geometry is thought a sphere, but could be anything. The color interpolation + * is linear along the Y axis in any case. + * + * You must specify one more color than you have angles at the beginning of the colors array. + * This is the color of the Zenith (the top of the shape). + * + * @param {BufferGeometry} geometry + * @param {number} radius + * @param {array} angles + * @param {array} colors + * @param {boolean} topDown - Whether to work top down or bottom up. + */ + function paintFaces( geometry, radius, angles, colors, topDown ) { + + // compute threshold values + + const thresholds = []; + const startAngle = ( topDown === true ) ? 0 : Math.PI; + + for ( let i = 0, l = colors.length; i < l; i ++ ) { + + let angle = ( i === 0 ) ? 0 : angles[ i - 1 ]; + angle = ( topDown === true ) ? angle : ( startAngle - angle ); + + const point = new Vector3(); + point.setFromSphericalCoords( radius, angle, 0 ); + + thresholds.push( point ); - var thresholds = []; - var startAngle = ( topDown === true ) ? 0 : Math.PI; + } - for ( var i = 0, l = colors.length; i < l; i ++ ) { + // generate vertex colors - var angle = ( i === 0 ) ? 0 : angles[ i - 1 ]; - angle = ( topDown === true ) ? angle : ( startAngle - angle ); + const indices = geometry.index; + const positionAttribute = geometry.attributes.position; + const colorAttribute = new BufferAttribute( new Float32Array( geometry.attributes.position.count * 3 ), 3 ); - var point = new Vector3(); - point.setFromSphericalCoords( radius, angle, 0 ); + const position = new Vector3(); + const color = new Color(); - thresholds.push( point ); + for ( let i = 0; i < indices.count; i ++ ) { - } + const index = indices.getX( i ); + position.fromBufferAttribute( positionAttribute, index ); - // generate vertex colors + let thresholdIndexA, thresholdIndexB; + let t = 1; - var indices = geometry.index; - var positionAttribute = geometry.attributes.position; - var colorAttribute = new BufferAttribute( new Float32Array( geometry.attributes.position.count * 3 ), 3 ); + for ( let j = 1; j < thresholds.length; j ++ ) { - var position = new Vector3(); - var color = new Color(); + thresholdIndexA = j - 1; + thresholdIndexB = j; - for ( var i = 0; i < indices.count; i ++ ) { + const thresholdA = thresholds[ thresholdIndexA ]; + const thresholdB = thresholds[ thresholdIndexB ]; - var index = indices.getX( i ); - position.fromBufferAttribute( positionAttribute, index ); + if ( topDown === true ) { - var thresholdIndexA, thresholdIndexB; - var t = 1; + // interpolation for sky color - for ( var j = 1; j < thresholds.length; j ++ ) { + if ( position.y <= thresholdA.y && position.y > thresholdB.y ) { - thresholdIndexA = j - 1; - thresholdIndexB = j; + t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y ); - var thresholdA = thresholds[ thresholdIndexA ]; - var thresholdB = thresholds[ thresholdIndexB ]; + break; - if ( topDown === true ) { + } - // interpolation for sky color + } else { - if ( position.y <= thresholdA.y && position.y > thresholdB.y ) { + // interpolation for ground color - t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y ); + if ( position.y >= thresholdA.y && position.y < thresholdB.y ) { - break; + t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y ); - } + break; - } else { + } - // interpolation for ground color + } - if ( position.y >= thresholdA.y && position.y < thresholdB.y ) { + } - t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y ); + const colorA = colors[ thresholdIndexA ]; + const colorB = colors[ thresholdIndexB ]; - break; + color.copy( colorA ).lerp( colorB, t ); - } + colorAttribute.setXYZ( index, color.r, color.g, color.b ); - } + } - } + geometry.setAttribute( 'color', colorAttribute ); - var colorA = colors[ thresholdIndexA ]; - var colorB = colors[ thresholdIndexB ]; + } - color.copy( colorA ).lerp( colorB, t ); + // - colorAttribute.setXYZ( index, color.r, color.g, color.b ); + const textureLoader = new TextureLoader( this.manager ); + textureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); - } + // check version (only 2.0 is supported) - geometry.setAttribute( 'color', colorAttribute ); + if ( data.indexOf( '#VRML V2.0' ) === - 1 ) { - } + throw Error( 'THREE.VRMLLexer: Version of VRML asset not supported.' ); - // + } - var textureLoader = new TextureLoader( this.manager ); - textureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin ); + // create JSON representing the tree structure of the VRML asset - // check version (only 2.0 is supported) + const tree = generateVRMLTree( data ); - if ( data.indexOf( '#VRML V2.0' ) === - 1 ) { + // parse the tree structure to a three.js scene - throw Error( 'THREE.VRMLLexer: Version of VRML asset not supported.' ); + const scene = parseTree( tree ); - } + return scene; - // create JSON representing the tree structure of the VRML asset + } - var tree = generateVRMLTree( data ); +} - // parse the tree structure to a three.js scene +class VRMLLexer { - var scene = parseTree( tree ); + constructor( tokens ) { - return scene; + this.lexer = new chevrotain.Lexer( tokens ); // eslint-disable-line no-undef - } + } - } ); + lex( inputText ) { - function VRMLLexer( tokens ) { + const lexingResult = this.lexer.tokenize( inputText ); - this.lexer = new chevrotain.Lexer( tokens ); // eslint-disable-line no-undef + if ( lexingResult.errors.length > 0 ) { - } + console.error( lexingResult.errors ); - VRMLLexer.prototype = { + throw Error( 'THREE.VRMLLexer: Lexing errors detected.' ); - constructor: VRMLLexer, + } - lex: function ( inputText ) { + return lexingResult; - var lexingResult = this.lexer.tokenize( inputText ); + } - if ( lexingResult.errors.length > 0 ) { +} - console.error( lexingResult.errors ); +const CstParser = chevrotain.CstParser;// eslint-disable-line no-undef - throw Error( 'THREE.VRMLLexer: Lexing errors detected.' ); +class VRMLParser extends CstParser { - } + constructor( tokenVocabulary ) { - return lexingResult; + super( tokenVocabulary ); - } + const $ = this; - }; - - function VRMLParser( tokenVocabulary ) { - - chevrotain.Parser.call( this, tokenVocabulary ); // eslint-disable-line no-undef - - var $ = this; - - var Version = tokenVocabulary[ 'Version' ]; - var LCurly = tokenVocabulary[ 'LCurly' ]; - var RCurly = tokenVocabulary[ 'RCurly' ]; - var LSquare = tokenVocabulary[ 'LSquare' ]; - var RSquare = tokenVocabulary[ 'RSquare' ]; - var Identifier = tokenVocabulary[ 'Identifier' ]; - var RouteIdentifier = tokenVocabulary[ 'RouteIdentifier' ]; - var StringLiteral = tokenVocabulary[ 'StringLiteral' ]; - var HexLiteral = tokenVocabulary[ 'HexLiteral' ]; - var NumberLiteral = tokenVocabulary[ 'NumberLiteral' ]; - var TrueLiteral = tokenVocabulary[ 'TrueLiteral' ]; - var FalseLiteral = tokenVocabulary[ 'FalseLiteral' ]; - var NullLiteral = tokenVocabulary[ 'NullLiteral' ]; - var DEF = tokenVocabulary[ 'DEF' ]; - var USE = tokenVocabulary[ 'USE' ]; - var ROUTE = tokenVocabulary[ 'ROUTE' ]; - var TO = tokenVocabulary[ 'TO' ]; - var NodeName = tokenVocabulary[ 'NodeName' ]; + const Version = tokenVocabulary[ 'Version' ]; + const LCurly = tokenVocabulary[ 'LCurly' ]; + const RCurly = tokenVocabulary[ 'RCurly' ]; + const LSquare = tokenVocabulary[ 'LSquare' ]; + const RSquare = tokenVocabulary[ 'RSquare' ]; + const Identifier = tokenVocabulary[ 'Identifier' ]; + const RouteIdentifier = tokenVocabulary[ 'RouteIdentifier' ]; + const StringLiteral = tokenVocabulary[ 'StringLiteral' ]; + const HexLiteral = tokenVocabulary[ 'HexLiteral' ]; + const NumberLiteral = tokenVocabulary[ 'NumberLiteral' ]; + const TrueLiteral = tokenVocabulary[ 'TrueLiteral' ]; + const FalseLiteral = tokenVocabulary[ 'FalseLiteral' ]; + const NullLiteral = tokenVocabulary[ 'NullLiteral' ]; + const DEF = tokenVocabulary[ 'DEF' ]; + const USE = tokenVocabulary[ 'USE' ]; + const ROUTE = tokenVocabulary[ 'ROUTE' ]; + const TO = tokenVocabulary[ 'TO' ]; + const NodeName = tokenVocabulary[ 'NodeName' ]; $.RULE( 'vrml', function () { @@ -3474,10 +3471,11 @@ var VRMLLoader = ( function () { } - VRMLParser.prototype = Object.create( chevrotain.Parser.prototype ); // eslint-disable-line no-undef - VRMLParser.prototype.constructor = VRMLParser; +} - function Face( a, b, c ) { +class Face { + + constructor( a, b, c ) { this.a = a; this.b = b; @@ -3486,15 +3484,13 @@ var VRMLLoader = ( function () { } - var TEXTURE_TYPE = { - INTENSITY: 1, - INTENSITY_ALPHA: 2, - RGB: 3, - RGBA: 4 - }; - - return VRMLLoader; +} -} )(); +const TEXTURE_TYPE = { + INTENSITY: 1, + INTENSITY_ALPHA: 2, + RGB: 3, + RGBA: 4 +}; export { VRMLLoader }; diff --git a/examples/jsm/loaders/VRMLoader.js b/examples/jsm/loaders/VRMLoader.js index 66638bd42b18a5..cf8c87e1e4bed9 100644 --- a/examples/jsm/loaders/VRMLoader.js +++ b/examples/jsm/loaders/VRMLoader.js @@ -8,9 +8,9 @@ import { GLTFLoader } from '../loaders/GLTFLoader.js'; // VRM is based on glTF 2.0 and VRM extension is defined // in top-level json.extensions.VRM -var VRMLoader = ( function () { +class VRMLoader extends Loader { - function VRMLoader( manager ) { + constructor( manager ) { if ( GLTFLoader === undefined ) { @@ -18,69 +18,61 @@ var VRMLoader = ( function () { } - Loader.call( this, manager ); + super( manager ); - this.gltfLoader = new GLTFLoader( this.manager ); + this.gltfLoader = new GLTFLoader( manager ); } - VRMLoader.prototype = Object.assign( Object.create( Loader.prototype ), { + load( url, onLoad, onProgress, onError ) { - constructor: VRMLoader, + const scope = this; - load: function ( url, onLoad, onProgress, onError ) { + this.gltfLoader.load( url, function ( gltf ) { - var scope = this; + try { - this.gltfLoader.load( url, function ( gltf ) { + scope.parse( gltf, onLoad ); - try { + } catch ( e ) { - scope.parse( gltf, onLoad ); + if ( onError ) { - } catch ( e ) { + onError( e ); - if ( onError ) { + } else { - onError( e ); - - } else { - - console.error( e ); - - } - - scope.manager.itemError( url ); + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); - }, + } - setDRACOLoader: function ( dracoLoader ) { + }, onProgress, onError ); - this.gltfLoader.setDRACOLoader( dracoLoader ); - return this; + } - }, + setDRACOLoader( dracoLoader ) { - parse: function ( gltf, onLoad ) { + this.gltfLoader.setDRACOLoader( dracoLoader ); + return this; - // var gltfParser = gltf.parser; - // var gltfExtensions = gltf.userData.gltfExtensions || {}; - // var vrmExtension = gltfExtensions.VRM || {}; + } - // handle VRM Extension here + parse( gltf, onLoad ) { - onLoad( gltf ); + // const gltfParser = gltf.parser; + // const gltfExtensions = gltf.userData.gltfExtensions || {}; + // const vrmExtension = gltfExtensions.VRM || {}; - } + // handle VRM Extension here - } ); + onLoad( gltf ); - return VRMLoader; + } -} )(); +} export { VRMLoader }; diff --git a/examples/jsm/loaders/VTKLoader.js b/examples/jsm/loaders/VTKLoader.js index 6ebba6c9823020..11004ed31bb0c2 100644 --- a/examples/jsm/loaders/VTKLoader.js +++ b/examples/jsm/loaders/VTKLoader.js @@ -6,23 +6,21 @@ import { Loader, LoaderUtils } from '../../../build/three.module.js'; -import * as fflate from '../libs/fflate.module.min.js'; +import * as fflate from '../libs/fflate.module.js'; -var VTKLoader = function ( manager ) { +class VTKLoader extends Loader { - Loader.call( this, manager ); + constructor( manager ) { -}; + super( manager ); -VTKLoader.prototype = Object.assign( Object.create( Loader.prototype ), { - - constructor: VTKLoader, + } - load: function ( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError ) { - var scope = this; + const scope = this; - var loader = new FileLoader( scope.manager ); + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); loader.setRequestHeader( scope.requestHeader ); @@ -51,9 +49,9 @@ VTKLoader.prototype = Object.assign( Object.create( Loader.prototype ), { }, onProgress, onError ); - }, + } - parse: function ( data ) { + parse( data ) { function parseASCII( data ) { @@ -553,23 +551,23 @@ VTKLoader.prototype = Object.assign( Object.create( Loader.prototype ), { function Float32Concat( first, second ) { - var firstLength = first.length, result = new Float32Array( firstLength + second.length ); + const firstLength = first.length, result = new Float32Array( firstLength + second.length ); - result.set( first ); - result.set( second, firstLength ); + result.set( first ); + result.set( second, firstLength ); - return result; + return result; } function Int32Concat( first, second ) { - var firstLength = first.length, result = new Int32Array( firstLength + second.length ); + var firstLength = first.length, result = new Int32Array( firstLength + second.length ); - result.set( first ); - result.set( second, firstLength ); + result.set( first ); + result.set( second, firstLength ); - return result; + return result; } @@ -1179,6 +1177,6 @@ VTKLoader.prototype = Object.assign( Object.create( Loader.prototype ), { } -} ); +} export { VTKLoader }; diff --git a/examples/jsm/loaders/XLoader.js b/examples/jsm/loaders/XLoader.js deleted file mode 100644 index 6133ad43e13387..00000000000000 --- a/examples/jsm/loaders/XLoader.js +++ /dev/null @@ -1,1759 +0,0 @@ -import { - AnimationClip, - AnimationMixer, - Bone, - BufferGeometry, - FileLoader, - Float32BufferAttribute, - FrontSide, - Loader, - LoaderUtils, - Matrix4, - Mesh, - MeshPhongMaterial, - Quaternion, - Skeleton, - SkinnedMesh, - TextureLoader, - Uint16BufferAttribute, - Vector2, - Vector3 -} from '../../../build/three.module.js'; - -var XLoader = ( function () { - - var classCallCheck = function ( instance, Constructor ) { - - if ( ! ( instance instanceof Constructor ) ) { - - throw new TypeError( 'Cannot call a class as a function' ); - - } - - }; - - var createClass = function () { - - function defineProperties( target, props ) { - - for ( var i = 0; i < props.length; i ++ ) { - - var descriptor = props[ i ]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ( 'value' in descriptor ) descriptor.writable = true; - Object.defineProperty( target, descriptor.key, descriptor ); - - } - - } - - return function ( Constructor, protoProps, staticProps ) { - - if ( protoProps ) defineProperties( Constructor.prototype, protoProps ); - if ( staticProps ) defineProperties( Constructor, staticProps ); - return Constructor; - - }; - - }(); - - var XboneInf = function XboneInf() { - - classCallCheck( this, XboneInf ); - - this.boneName = ''; - this.BoneIndex = 0; - this.Indeces = []; - this.Weights = []; - this.initMatrix = null; - this.OffsetMatrix = null; - - }; - - var XAnimationInfo = function XAnimationInfo() { - - classCallCheck( this, XAnimationInfo ); - - this.animeName = ''; - this.boneName = ''; - this.targetBone = null; - this.keyType = 4; - this.frameStartLv = 0; - this.keyFrames = []; - this.InverseMx = null; - - }; - - var XAnimationObj = function () { - - function XAnimationObj( _flags ) { - - classCallCheck( this, XAnimationObj ); - - this.fps = 30; - this.name = 'xanimation'; - this.length = 0; - this.hierarchy = []; - this.putFlags = _flags; - if ( this.putFlags.putPos === undefined ) { - - this.putFlags.putPos = true; - - } - - if ( this.putFlags.putRot === undefined ) { - - this.putFlags.putRot = true; - - } - - if ( this.putFlags.putScl === undefined ) { - - this.putFlags.putScl = true; - - } - - } - - createClass( XAnimationObj, [ { - key: 'make', - value: function make( XAnimationInfoArray ) { - - for ( var i = 0; i < XAnimationInfoArray.length; i ++ ) { - - this.hierarchy.push( this.makeBonekeys( XAnimationInfoArray[ i ] ) ); - - } - - this.length = this.hierarchy[ 0 ].keys[ this.hierarchy[ 0 ].keys.length - 1 ].time; - - } - }, { - key: 'clone', - value: function clone() { - - return Object.assign( {}, this ); - - } - }, { - key: 'makeBonekeys', - value: function makeBonekeys( XAnimationInfo ) { - - var refObj = {}; - refObj.name = XAnimationInfo.boneName; - refObj.parent = ''; - refObj.keys = this.keyFrameRefactor( XAnimationInfo ); - refObj.copy = function () { - - return Object.assign( {}, this ); - - }; - - return refObj; - - } - }, { - key: 'keyFrameRefactor', - value: function keyFrameRefactor( XAnimationInfo ) { - - var keys = []; - for ( var i = 0; i < XAnimationInfo.keyFrames.length; i ++ ) { - - var keyframe = {}; - keyframe.time = XAnimationInfo.keyFrames[ i ].time * this.fps; - if ( XAnimationInfo.keyFrames[ i ].pos && this.putFlags.putPos ) { - - keyframe.pos = XAnimationInfo.keyFrames[ i ].pos; - - } - - if ( XAnimationInfo.keyFrames[ i ].rot && this.putFlags.putRot ) { - - keyframe.rot = XAnimationInfo.keyFrames[ i ].rot; - - } - - if ( XAnimationInfo.keyFrames[ i ].scl && this.putFlags.putScl ) { - - keyframe.scl = XAnimationInfo.keyFrames[ i ].scl; - - } - - if ( XAnimationInfo.keyFrames[ i ].matrix ) { - - keyframe.matrix = XAnimationInfo.keyFrames[ i ].matrix; - if ( this.putFlags.putPos ) { - - keyframe.pos = new Vector3().setFromMatrixPosition( keyframe.matrix ); - - } - - if ( this.putFlags.putRot ) { - - keyframe.rot = new Quaternion().setFromRotationMatrix( keyframe.matrix ); - - } - - if ( this.putFlags.putScl ) { - - keyframe.scl = new Vector3().setFromMatrixScale( keyframe.matrix ); - - } - - } - - keys.push( keyframe ); - - } - - return keys; - - } - } ] ); - return XAnimationObj; - - }(); - - var XKeyFrameInfo = function XKeyFrameInfo() { - - classCallCheck( this, XKeyFrameInfo ); - - this.index = 0; - this.Frame = 0; - this.time = 0.0; - this.matrix = null; - - }; - - var XLoader = function () { - - function XLoader( manager ) { - - Loader.call( this, manager ); - - classCallCheck( this, XLoader ); - - this.debug = false; - this.texloader = new TextureLoader( this.manager ); - this.url = ''; - this._putMatLength = 0; - this._nowMat = null; - this._nowFrameName = ''; - this.frameHierarchie = []; - this.Hierarchies = {}; - this.HieStack = []; - this._currentObject = {}; - this._currentFrame = {}; - this._data = null; - this.onLoad = null; - this.IsUvYReverse = true; - this.Meshes = []; - this.animations = []; - this.animTicksPerSecond = 30; - this._currentGeo = null; - this._currentAnime = null; - this._currentAnimeFrames = null; - - } - - createClass( XLoader, [ { - key: '_setArgOption', - value: function _setArgOption( _arg ) { - - var _start = arguments.length > 1 && arguments[ 1 ] !== undefined ? arguments[ 1 ] : 0; - - if ( ! _arg ) { - - return; - - } - - for ( var i = _start; i < _arg.length; i ++ ) { - - switch ( i ) { - - case 0: - this.url = _arg[ i ]; - break; - case 1: - this.options = _arg[ i ]; - break; - - } - - } - - if ( this.options === undefined ) { - - this.options = {}; - - } - - } - }, { - key: 'load', - value: function load( _arg, onLoad, onProgress, onError ) { - - var _this = this; - - this._setArgOption( _arg ); - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); - loader.load( this.url, function ( response ) { - - try { - - _this.parse( response, onLoad ); - - } catch ( e ) { - - if ( onError ) { - - onError( e ); - - } else { - - console.error( e ); - - } - - _this.manager.itemError( _this.url ); - - } - - }, onProgress, onError ); - - } - }, { - key: '_readLine', - value: function _readLine( line ) { - - var readed = 0; - while ( true ) { - - var find = - 1; - find = line.indexOf( '//', readed ); - if ( find === - 1 ) { - - find = line.indexOf( '#', readed ); - - } - - if ( find > - 1 && find < 2 ) { - - var foundNewLine = - 1; - foundNewLine = line.indexOf( '\r\n', readed ); - if ( foundNewLine > 0 ) { - - readed = foundNewLine + 2; - - } else { - - foundNewLine = line.indexOf( '\r', readed ); - if ( foundNewLine > 0 ) { - - readed = foundNewLine + 1; - - } else { - - readed = line.indexOf( '\n', readed ) + 1; - - } - - } - - } else { - - break; - - } - - } - - return line.substr( readed ); - - } - }, { - key: '_readLine', - value: function _readLine( line ) { - - var readed = 0; - while ( true ) { - - var find = - 1; - find = line.indexOf( '//', readed ); - if ( find === - 1 ) { - - find = line.indexOf( '#', readed ); - - } - - if ( find > - 1 && find < 2 ) { - - var foundNewLine = - 1; - foundNewLine = line.indexOf( '\r\n', readed ); - if ( foundNewLine > 0 ) { - - readed = foundNewLine + 2; - - } else { - - foundNewLine = line.indexOf( '\r', readed ); - if ( foundNewLine > 0 ) { - - readed = foundNewLine + 1; - - } else { - - readed = line.indexOf( '\n', readed ) + 1; - - } - - } - - } else { - - break; - - } - - } - - return line.substr( readed ); - - } - }, { - key: '_isBinary', - value: function _isBinary( binData ) { - - var reader = new DataView( binData ); - var face_size = 32 / 8 * 3 + 32 / 8 * 3 * 3 + 16 / 8; - var n_faces = reader.getUint32( 80, true ); - var expect = 80 + 32 / 8 + n_faces * face_size; - if ( expect === reader.byteLength ) { - - return true; - - } - - var fileLength = reader.byteLength; - for ( var index = 0; index < fileLength; index ++ ) { - - if ( reader.getUint8( index, false ) > 127 ) { - - return true; - - } - - } - - return false; - - } - }, { - key: '_ensureBinary', - value: function _ensureBinary( buf ) { - - if ( typeof buf === 'string' ) { - - var array_buffer = new Uint8Array( buf.length ); - for ( var i = 0; i < buf.length; i ++ ) { - - array_buffer[ i ] = buf.charCodeAt( i ) & 0xff; - - } - - return array_buffer.buffer || array_buffer; - - } else { - - return buf; - - } - - } - }, { - key: '_ensureString', - value: function _ensureString( buf ) { - - if ( typeof buf !== 'string' ) { - - return LoaderUtils.decodeText( new Uint8Array( buf ) ); - - } else { - - return buf; - - } - - } - }, { - key: 'parse', - value: function _parse( data, onLoad ) { - - var binData = this._ensureBinary( data ); - this._data = this._ensureString( data ); - this.onLoad = onLoad; - return this._isBinary( binData ) ? this._parseBinary( binData ) : this._parseASCII(); - - } - }, { - key: '_parseBinary', - value: function _parseBinary( data ) { - - return this._parseASCII( LoaderUtils.decodeText( new Uint8Array( data ) ) ); - - } - }, { - key: '_parseASCII', - value: function _parseASCII() { - - var path; - - if ( this.resourcePath !== '' ) { - - path = this.resourcePath; - - } else if ( this.path !== '' ) { - - path = this.path; - - } else { - - path = LoaderUtils.extractUrlBase( this.url ); - - } - - this.texloader.setPath( path ).setCrossOrigin( this.crossOrigin ); - - var endRead = 16; - this.Hierarchies.children = []; - this._hierarchieParse( this.Hierarchies, endRead ); - this._changeRoot(); - this._currentObject = this.Hierarchies.children.shift(); - this._mainloop(); - - } - }, { - key: '_hierarchieParse', - value: function _hierarchieParse( _parent, _end ) { - - var endRead = _end; - while ( true ) { - - var find1 = this._data.indexOf( '{', endRead ) + 1; - var findEnd = this._data.indexOf( '}', endRead ); - var findNext = this._data.indexOf( '{', find1 ) + 1; - if ( find1 > 0 && findEnd > find1 ) { - - var _currentObject = {}; - _currentObject.children = []; - var nameData = this._readLine( this._data.substr( endRead, find1 - endRead - 1 ) ).trim(); - var word = nameData.split( / /g ); - if ( word.length > 0 ) { - - _currentObject.type = word[ 0 ]; - if ( word.length >= 2 ) { - - _currentObject.name = word[ 1 ]; - - } else { - - _currentObject.name = word[ 0 ] + this.Hierarchies.children.length; - - } - - } else { - - _currentObject.name = nameData; - _currentObject.type = ''; - - } - - if ( _currentObject.type === 'Animation' ) { - - _currentObject.data = this._data.substr( findNext, findEnd - findNext ).trim(); - var refs = this._hierarchieParse( _currentObject, findEnd + 1 ); - endRead = refs.end; - _currentObject.children = refs.parent.children; - - } else { - - var DataEnder = this._data.lastIndexOf( ';', findNext > 0 ? Math.min( findNext, findEnd ) : findEnd ); - _currentObject.data = this._data.substr( find1, DataEnder - find1 ).trim(); - if ( findNext <= 0 || findEnd < findNext ) { - - endRead = findEnd + 1; - - } else { - - var nextStart = Math.max( DataEnder + 1, find1 ); - var _refs = this._hierarchieParse( _currentObject, nextStart ); - endRead = _refs.end; - _currentObject.children = _refs.parent.children; - - } - - } - - _currentObject.parent = _parent; - if ( _currentObject.type != 'template' ) { - - _parent.children.push( _currentObject ); - - } - - } else { - - endRead = find1 === - 1 ? this._data.length : findEnd + 1; - break; - - } - - } - - return { - parent: _parent, - end: endRead - }; - - } - }, { - key: '_mainloop', - value: function _mainloop() { - - var _this2 = this; - - this._mainProc(); - if ( this._currentObject.parent || this._currentObject.children.length > 0 || ! this._currentObject.worked ) { - - setTimeout( function () { - - _this2._mainloop(); - - }, 1 ); - - } else { - - setTimeout( function () { - - _this2.onLoad( { - models: _this2.Meshes, - animations: _this2.animations - } ); - - }, 1 ); - - } - - } - }, { - key: '_mainProc', - value: function _mainProc() { - - var breakFlag = false; - while ( true ) { - - if ( ! this._currentObject.worked ) { - - switch ( this._currentObject.type ) { - - case 'template': - break; - case 'AnimTicksPerSecond': - this.animTicksPerSecond = parseInt( this._currentObject.data ); - break; - case 'Frame': - this._setFrame(); - break; - case 'FrameTransformMatrix': - this._setFrameTransformMatrix(); - break; - case 'Mesh': - this._changeRoot(); - this._currentGeo = {}; - this._currentGeo.name = this._currentObject.name.trim(); - this._currentGeo.parentName = this._getParentName( this._currentObject ).trim(); - this._currentGeo.VertexSetedBoneCount = []; - this._currentGeo.GeometryData = { - vertices: [], - normals: [], - uvs: [], - skinIndices: [], - skinWeights: [], - indices: [], - materialIndices: [] - }; - this._currentGeo.Materials = []; - this._currentGeo.normalVectors = []; - this._currentGeo.BoneInfs = []; - this._currentGeo.baseFrame = this._currentFrame; - this._makeBoneFrom_CurrentFrame(); - this._readVertexDatas(); - breakFlag = true; - break; - case 'MeshNormals': - this._readVertexDatas(); - break; - case 'MeshTextureCoords': - this._setMeshTextureCoords(); - break; - case 'VertexDuplicationIndices': - break; - case 'MeshMaterialList': - this._setMeshMaterialList(); - break; - case 'Material': - this._setMaterial(); - break; - case 'SkinWeights': - this._setSkinWeights(); - break; - case 'AnimationSet': - this._changeRoot(); - this._currentAnime = {}; - this._currentAnime.name = this._currentObject.name.trim(); - this._currentAnime.AnimeFrames = []; - break; - case 'Animation': - if ( this._currentAnimeFrames ) { - - this._currentAnime.AnimeFrames.push( this._currentAnimeFrames ); - - } - - this._currentAnimeFrames = new XAnimationInfo(); - this._currentAnimeFrames.boneName = this._currentObject.data.trim(); - break; - case 'AnimationKey': - this._readAnimationKey(); - breakFlag = true; - break; - - } - - this._currentObject.worked = true; - - } - - if ( this._currentObject.children.length > 0 ) { - - this._currentObject = this._currentObject.children.shift(); - if ( this.debug ) { - - console.log( 'processing ' + this._currentObject.name ); - - } - - if ( breakFlag ) break; - - } else { - - if ( this._currentObject.worked ) { - - if ( this._currentObject.parent && ! this._currentObject.parent.parent ) { - - this._changeRoot(); - - } - - } - - if ( this._currentObject.parent ) { - - this._currentObject = this._currentObject.parent; - - } else { - - breakFlag = true; - - } - - if ( breakFlag ) break; - - } - - } - - return; - - } - }, { - key: '_changeRoot', - value: function _changeRoot() { - - if ( this._currentGeo != null && this._currentGeo.name ) { - - this._makeOutputGeometry(); - - } - - this._currentGeo = {}; - if ( this._currentAnime != null && this._currentAnime.name ) { - - if ( this._currentAnimeFrames ) { - - this._currentAnime.AnimeFrames.push( this._currentAnimeFrames ); - this._currentAnimeFrames = null; - - } - - this._makeOutputAnimation(); - - } - - this._currentAnime = {}; - - } - }, { - key: '_getParentName', - value: function _getParentName( _obj ) { - - if ( _obj.parent ) { - - if ( _obj.parent.name ) { - - return _obj.parent.name; - - } else { - - return this._getParentName( _obj.parent ); - - } - - } else { - - return ''; - - } - - } - }, { - key: '_setFrame', - value: function _setFrame() { - - this._nowFrameName = this._currentObject.name.trim(); - this._currentFrame = {}; - this._currentFrame.name = this._nowFrameName; - this._currentFrame.children = []; - if ( this._currentObject.parent && this._currentObject.parent.name ) { - - this._currentFrame.parentName = this._currentObject.parent.name; - - } - - this.frameHierarchie.push( this._nowFrameName ); - this.HieStack[ this._nowFrameName ] = this._currentFrame; - - } - }, { - key: '_setFrameTransformMatrix', - value: function _setFrameTransformMatrix() { - - this._currentFrame.FrameTransformMatrix = new Matrix4(); - var data = this._currentObject.data.split( ',' ); - this._ParseMatrixData( this._currentFrame.FrameTransformMatrix, data ); - this._makeBoneFrom_CurrentFrame(); - - } - }, { - key: '_makeBoneFrom_CurrentFrame', - value: function _makeBoneFrom_CurrentFrame() { - - if ( ! this._currentFrame.FrameTransformMatrix ) { - - return; - - } - - var b = new Bone(); - b.name = this._currentFrame.name; - b.applyMatrix4( this._currentFrame.FrameTransformMatrix ); - b.matrixWorld = b.matrix; - b.FrameTransformMatrix = this._currentFrame.FrameTransformMatrix; - this._currentFrame.putBone = b; - if ( this._currentFrame.parentName ) { - - for ( var frame in this.HieStack ) { - - if ( this.HieStack[ frame ].name === this._currentFrame.parentName ) { - - this.HieStack[ frame ].putBone.add( this._currentFrame.putBone ); - - } - - } - - } - - } - }, { - key: '_readVertexDatas', - value: function _readVertexDatas() { - - var endRead = 0; - var mode = 0; - var mode_local = 0; - var maxLength = 0; - while ( true ) { - - var changeMode = false; - if ( mode_local === 0 ) { - - var refO = this._readInt1( endRead ); - endRead = refO.endRead; - mode_local = 1; - maxLength = this._currentObject.data.indexOf( ';;', endRead ) + 1; - if ( maxLength <= 0 ) { - - maxLength = this._currentObject.data.length; - - } - - } else { - - var find = 0; - switch ( mode ) { - - case 0: - find = this._currentObject.data.indexOf( ',', endRead ) + 1; - break; - case 1: - find = this._currentObject.data.indexOf( ';,', endRead ) + 1; - break; - - } - - if ( find === 0 || find > maxLength ) { - - find = maxLength; - mode_local = 0; - changeMode = true; - - } - - switch ( this._currentObject.type ) { - - case 'Mesh': - switch ( mode ) { - - case 0: - this._readVertex1( this._currentObject.data.substr( endRead, find - endRead ) ); - break; - case 1: - this._readFace1( this._currentObject.data.substr( endRead, find - endRead ) ); - break; - - } - - break; - case 'MeshNormals': - switch ( mode ) { - - case 0: - this._readNormalVector1( this._currentObject.data.substr( endRead, find - endRead ) ); - break; - - } - - break; - - } - - endRead = find + 1; - if ( changeMode ) { - - mode ++; - - } - - } - - if ( endRead >= this._currentObject.data.length ) { - - break; - - } - - } - - } - }, { - key: '_readInt1', - value: function _readInt1( start ) { - - var find = this._currentObject.data.indexOf( ';', start ); - return { - refI: parseInt( this._currentObject.data.substr( start, find - start ) ), - endRead: find + 1 - }; - - } - }, { - key: '_readVertex1', - value: function _readVertex1( line ) { - - var data = this._readLine( line.trim() ).substr( 0, line.length - 2 ).split( ';' ); - this._currentGeo.GeometryData.vertices.push( parseFloat( data[ 0 ] ), parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) ); - this._currentGeo.GeometryData.skinIndices.push( 0, 0, 0, 0 ); - this._currentGeo.GeometryData.skinWeights.push( 1, 0, 0, 0 ); - this._currentGeo.VertexSetedBoneCount.push( 0 ); - - } - }, { - key: '_readFace1', - value: function _readFace1( line ) { - - var data = this._readLine( line.trim() ).substr( 2, line.length - 4 ).split( ',' ); - this._currentGeo.GeometryData.indices.push( parseInt( data[ 0 ], 10 ), parseInt( data[ 1 ], 10 ), parseInt( data[ 2 ], 10 ) ); - - } - }, { - key: '_readNormalVector1', - value: function _readNormalVector1( line ) { - - var data = this._readLine( line.trim() ).substr( 0, line.length - 2 ).split( ';' ); - this._currentGeo.GeometryData.normals.push( parseFloat( data[ 0 ] ), parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) ); - - } - }, { - key: '_buildGeometry', - value: function _buildGeometry() { - - var bufferGeometry = new BufferGeometry(); - var position = []; - var normals = []; - var uvs = []; - var skinIndices = []; - var skinWeights = []; - - // - - var data = this._currentGeo.GeometryData; - - for ( var i = 0, l = data.indices.length; i < l; i ++ ) { - - var stride2 = data.indices[ i ] * 2; - var stride3 = data.indices[ i ] * 3; - var stride4 = data.indices[ i ] * 4; - - position.push( data.vertices[ stride3 ], data.vertices[ stride3 + 1 ], data.vertices[ stride3 + 2 ] ); - normals.push( data.normals[ stride3 ], data.normals[ stride3 + 1 ], data.normals[ stride3 + 2 ] ); - skinIndices.push( data.skinIndices[ stride4 ], data.skinIndices[ stride4 + 1 ], data.skinIndices[ stride4 + 2 ], data.skinIndices[ stride4 + 3 ] ); - skinWeights.push( data.skinWeights[ stride4 ], data.skinWeights[ stride4 + 1 ], data.skinWeights[ stride4 + 2 ], data.skinWeights[ stride4 + 3 ] ); - uvs.push( data.uvs[ stride2 ], data.uvs[ stride2 + 1 ] ); - - } - - // - - bufferGeometry.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - bufferGeometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - bufferGeometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - bufferGeometry.setAttribute( 'skinIndex', new Uint16BufferAttribute( skinIndices, 4 ) ); - bufferGeometry.setAttribute( 'skinWeight', new Float32BufferAttribute( skinWeights, 4 ) ); - - this._computeGroups( bufferGeometry, data.materialIndices ); - - return bufferGeometry; - - } - }, { - key: '_computeGroups', - value: function _computeGroups( bufferGeometry, materialIndices ) { - - var group; - var groups = []; - var materialIndex = undefined; - - for ( var i = 0; i < materialIndices.length; i ++ ) { - - var currentMaterialIndex = materialIndices[ i ]; - - if ( currentMaterialIndex !== materialIndex ) { - - materialIndex = currentMaterialIndex; - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - group = { - start: i * 3, - materialIndex: materialIndex - }; - - } - - } - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - bufferGeometry.groups = groups; - - } - }, { - key: '_setMeshTextureCoords', - value: function _setMeshTextureCoords() { - - var endRead = 0; - var mode = 0; - var mode_local = 0; - while ( true ) { - - switch ( mode ) { - - case 0: - if ( mode_local === 0 ) { - - var refO = this._readInt1( 0 ); - endRead = refO.endRead; - mode_local = 1; - - } else { - - var find = this._currentObject.data.indexOf( ',', endRead ) + 1; - if ( find === 0 ) { - - find = this._currentObject.data.length; - mode = 2; - mode_local = 0; - - } - - var line = this._currentObject.data.substr( endRead, find - endRead ); - var data = this._readLine( line.trim() ).split( ';' ); - if ( this.IsUvYReverse ) { - - this._currentGeo.GeometryData.uvs.push( parseFloat( data[ 0 ] ), 1 - parseFloat( data[ 1 ] ) ); - - } else { - - this._currentGeo.GeometryData.uvs.push( parseFloat( data[ 0 ] ), parseFloat( data[ 1 ] ) ); - - } - - endRead = find + 1; - - } - - break; - - } - - if ( endRead >= this._currentObject.data.length ) { - - break; - - } - - } - - } - }, { - key: '_setMeshMaterialList', - value: function _setMeshMaterialList() { - - var endRead = 0; - var mode = 0; - var mode_local = 0; - while ( true ) { - - if ( mode_local < 2 ) { - - var refO = this._readInt1( endRead ); - endRead = refO.endRead; - mode_local ++; - - } else { - - var find = this._currentObject.data.indexOf( ';', endRead ); - if ( find === - 1 ) { - - find = this._currentObject.data.length; - mode = 3; - mode_local = 0; - - } - - var line = this._currentObject.data.substr( endRead, find - endRead ); - var data = this._readLine( line.trim() ).split( ',' ); - for ( var i = 0; i < data.length; i ++ ) { - - this._currentGeo.GeometryData.materialIndices[ i ] = parseInt( data[ i ] ); - - } - - endRead = this._currentObject.data.length; - - } - - if ( endRead >= this._currentObject.data.length || mode >= 3 ) { - - break; - - } - - } - - } - }, { - key: '_setMaterial', - value: function _setMaterial() { - - var _nowMat = new MeshPhongMaterial( { - color: Math.random() * 0xffffff - } ); - _nowMat.side = FrontSide; - _nowMat.name = this._currentObject.name; - var endRead = 0; - var find = this._currentObject.data.indexOf( ';;', endRead ); - var line = this._currentObject.data.substr( endRead, find - endRead ); - var data = this._readLine( line.trim() ).split( ';' ); - _nowMat.color.r = parseFloat( data[ 0 ] ); - _nowMat.color.g = parseFloat( data[ 1 ] ); - _nowMat.color.b = parseFloat( data[ 2 ] ); - endRead = find + 2; - find = this._currentObject.data.indexOf( ';', endRead ); - line = this._currentObject.data.substr( endRead, find - endRead ); - _nowMat.shininess = parseFloat( this._readLine( line ) ); - endRead = find + 1; - find = this._currentObject.data.indexOf( ';;', endRead ); - line = this._currentObject.data.substr( endRead, find - endRead ); - var data2 = this._readLine( line.trim() ).split( ';' ); - _nowMat.specular.r = parseFloat( data2[ 0 ] ); - _nowMat.specular.g = parseFloat( data2[ 1 ] ); - _nowMat.specular.b = parseFloat( data2[ 2 ] ); - endRead = find + 2; - find = this._currentObject.data.indexOf( ';;', endRead ); - if ( find === - 1 ) { - - find = this._currentObject.data.length; - - } - - line = this._currentObject.data.substr( endRead, find - endRead ); - var data3 = this._readLine( line.trim() ).split( ';' ); - _nowMat.emissive.r = parseFloat( data3[ 0 ] ); - _nowMat.emissive.g = parseFloat( data3[ 1 ] ); - _nowMat.emissive.b = parseFloat( data3[ 2 ] ); - var localObject = null; - while ( true ) { - - if ( this._currentObject.children.length > 0 ) { - - localObject = this._currentObject.children.shift(); - if ( this.debug ) { - - console.log( 'processing ' + localObject.name ); - - } - - var fileName = localObject.data.substr( 1, localObject.data.length - 2 ); - switch ( localObject.type ) { - - case 'TextureFilename': - _nowMat.map = this.texloader.load( fileName ); - break; - case 'BumpMapFilename': - _nowMat.bumpMap = this.texloader.load( fileName ); - _nowMat.bumpScale = 0.05; - break; - case 'NormalMapFilename': - _nowMat.normalMap = this.texloader.load( fileName ); - _nowMat.normalScale = new Vector2( 2, 2 ); - break; - case 'EmissiveMapFilename': - _nowMat.emissiveMap = this.texloader.load( fileName ); - break; - case 'LightMapFilename': - _nowMat.lightMap = this.texloader.load( fileName ); - break; - - } - - } else { - - break; - - } - - } - - this._currentGeo.Materials.push( _nowMat ); - - } - }, { - key: '_setSkinWeights', - value: function _setSkinWeights() { - - var boneInf = new XboneInf(); - var endRead = 0; - var find = this._currentObject.data.indexOf( ';', endRead ); - var line = this._currentObject.data.substr( endRead, find - endRead ); - endRead = find + 1; - boneInf.boneName = line.substr( 1, line.length - 2 ); - boneInf.BoneIndex = this._currentGeo.BoneInfs.length; - find = this._currentObject.data.indexOf( ';', endRead ); - endRead = find + 1; - find = this._currentObject.data.indexOf( ';', endRead ); - line = this._currentObject.data.substr( endRead, find - endRead ); - var data = this._readLine( line.trim() ).split( ',' ); - for ( var i = 0; i < data.length; i ++ ) { - - boneInf.Indeces.push( parseInt( data[ i ] ) ); - - } - - endRead = find + 1; - find = this._currentObject.data.indexOf( ';', endRead ); - line = this._currentObject.data.substr( endRead, find - endRead ); - var data2 = this._readLine( line.trim() ).split( ',' ); - for ( var _i = 0; _i < data2.length; _i ++ ) { - - boneInf.Weights.push( parseFloat( data2[ _i ] ) ); - - } - - endRead = find + 1; - find = this._currentObject.data.indexOf( ';', endRead ); - if ( find <= 0 ) { - - find = this._currentObject.data.length; - - } - - line = this._currentObject.data.substr( endRead, find - endRead ); - var data3 = this._readLine( line.trim() ).split( ',' ); - boneInf.OffsetMatrix = new Matrix4(); - this._ParseMatrixData( boneInf.OffsetMatrix, data3 ); - this._currentGeo.BoneInfs.push( boneInf ); - - } - }, { - key: '_makePutBoneList', - value: function _makePutBoneList( _RootName, _bones ) { - - var putting = false; - for ( var frame in this.HieStack ) { - - if ( this.HieStack[ frame ].name === _RootName || putting ) { - - putting = true; - var b = new Bone(); - b.name = this.HieStack[ frame ].name; - b.applyMatrix4( this.HieStack[ frame ].FrameTransformMatrix ); - b.matrixWorld = b.matrix; - b.FrameTransformMatrix = this.HieStack[ frame ].FrameTransformMatrix; - b.pos = new Vector3().setFromMatrixPosition( b.FrameTransformMatrix ).toArray(); - b.rotq = new Quaternion().setFromRotationMatrix( b.FrameTransformMatrix ).toArray(); - b.scl = new Vector3().setFromMatrixScale( b.FrameTransformMatrix ).toArray(); - if ( this.HieStack[ frame ].parentName && this.HieStack[ frame ].parentName.length > 0 ) { - - for ( var i = 0; i < _bones.length; i ++ ) { - - if ( this.HieStack[ frame ].parentName === _bones[ i ].name ) { - - _bones[ i ].add( b ); - b.parent = i; - break; - - } - - } - - } - - _bones.push( b ); - - } - - } - - } - }, { - key: '_makeOutputGeometry', - value: function _makeOutputGeometry() { - - var mesh = null; - if ( this._currentGeo.BoneInfs.length > 0 ) { - - var putBones = []; - this._makePutBoneList( this._currentGeo.baseFrame.parentName, putBones ); - for ( var bi = 0; bi < this._currentGeo.BoneInfs.length; bi ++ ) { - - var boneIndex = 0; - for ( var bb = 0; bb < putBones.length; bb ++ ) { - - if ( putBones[ bb ].name === this._currentGeo.BoneInfs[ bi ].boneName ) { - - boneIndex = bb; - putBones[ bb ].OffsetMatrix = new Matrix4(); - putBones[ bb ].OffsetMatrix.copy( this._currentGeo.BoneInfs[ bi ].OffsetMatrix ); - break; - - } - - } - - for ( var vi = 0; vi < this._currentGeo.BoneInfs[ bi ].Indeces.length; vi ++ ) { - - var nowVertexID = this._currentGeo.BoneInfs[ bi ].Indeces[ vi ]; - var nowVal = this._currentGeo.BoneInfs[ bi ].Weights[ vi ]; - - var stride = nowVertexID * 4; - - switch ( this._currentGeo.VertexSetedBoneCount[ nowVertexID ] ) { - - case 0: - this._currentGeo.GeometryData.skinIndices[ stride ] = boneIndex; - this._currentGeo.GeometryData.skinWeights[ stride ] = nowVal; - break; - case 1: - this._currentGeo.GeometryData.skinIndices[ stride + 1 ] = boneIndex; - this._currentGeo.GeometryData.skinWeights[ stride + 1 ] = nowVal; - break; - case 2: - this._currentGeo.GeometryData.skinIndices[ stride + 2 ] = boneIndex; - this._currentGeo.GeometryData.skinWeights[ stride + 2 ] = nowVal; - break; - case 3: - this._currentGeo.GeometryData.skinIndices[ stride + 3 ] = boneIndex; - this._currentGeo.GeometryData.skinWeights[ stride + 3 ] = nowVal; - break; - - } - - this._currentGeo.VertexSetedBoneCount[ nowVertexID ] ++; - if ( this._currentGeo.VertexSetedBoneCount[ nowVertexID ] > 4 ) { - - console.log( 'warn! over 4 bone weight! :' + nowVertexID ); - - } - - } - - } - - for ( var sk = 0; sk < this._currentGeo.Materials.length; sk ++ ) { - - this._currentGeo.Materials[ sk ].skinning = true; - - } - - var offsetList = []; - for ( var _bi = 0; _bi < putBones.length; _bi ++ ) { - - if ( putBones[ _bi ].OffsetMatrix ) { - - offsetList.push( putBones[ _bi ].OffsetMatrix ); - - } else { - - offsetList.push( new Matrix4() ); - - } - - } - - var bufferGeometry = this._buildGeometry(); - mesh = new SkinnedMesh( bufferGeometry, this._currentGeo.Materials.length === 1 ? this._currentGeo.Materials[ 0 ] : this._currentGeo.Materials ); - - this._initSkeleton( mesh, putBones, offsetList ); - - } else { - - var _bufferGeometry = this._buildGeometry(); - mesh = new Mesh( _bufferGeometry, this._currentGeo.Materials.length === 1 ? this._currentGeo.Materials[ 0 ] : this._currentGeo.Materials ); - - } - - mesh.name = this._currentGeo.name; - var worldBaseMx = new Matrix4(); - var currentMxFrame = this._currentGeo.baseFrame.putBone; - if ( currentMxFrame && currentMxFrame.parent ) { - - while ( true ) { - - currentMxFrame = currentMxFrame.parent; - if ( currentMxFrame ) { - - worldBaseMx.multiply( currentMxFrame.FrameTransformMatrix ); - - } else { - - break; - - } - - } - - mesh.applyMatrix4( worldBaseMx ); - - } - - this.Meshes.push( mesh ); - - } - }, { - key: '_initSkeleton', - value: function _initSkeleton( mesh, boneList, boneInverses ) { - - var bones = [], bone, gbone; - var i, il; - - for ( i = 0, il = boneList.length; i < il; i ++ ) { - - gbone = boneList[ i ]; - - bone = new Bone(); - bones.push( bone ); - - bone.name = gbone.name; - bone.position.fromArray( gbone.pos ); - bone.quaternion.fromArray( gbone.rotq ); - if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl ); - - } - - for ( i = 0, il = boneList.length; i < il; i ++ ) { - - gbone = boneList[ i ]; - - if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { - - bones[ gbone.parent ].add( bones[ i ] ); - - } else { - - mesh.add( bones[ i ] ); - - } - - } - - mesh.updateMatrixWorld( true ); - - var skeleton = new Skeleton( bones, boneInverses ); - mesh.bind( skeleton, mesh.matrixWorld ); - - } - - }, { - key: '_readAnimationKey', - value: function _readAnimationKey() { - - var endRead = 0; - var find = this._currentObject.data.indexOf( ';', endRead ); - var line = this._currentObject.data.substr( endRead, find - endRead ); - endRead = find + 1; - var nowKeyType = parseInt( this._readLine( line ) ); - find = this._currentObject.data.indexOf( ';', endRead ); - endRead = find + 1; - line = this._currentObject.data.substr( endRead ); - var data = this._readLine( line.trim() ).split( ';;,' ); - for ( var i = 0; i < data.length; i ++ ) { - - var data2 = data[ i ].split( ';' ); - var keyInfo = new XKeyFrameInfo(); - keyInfo.type = nowKeyType; - keyInfo.Frame = parseInt( data2[ 0 ] ); - keyInfo.index = this._currentAnimeFrames.keyFrames.length; - keyInfo.time = keyInfo.Frame; - if ( nowKeyType != 4 ) { - - var frameFound = false; - for ( var mm = 0; mm < this._currentAnimeFrames.keyFrames.length; mm ++ ) { - - if ( this._currentAnimeFrames.keyFrames[ mm ].Frame === keyInfo.Frame ) { - - keyInfo = this._currentAnimeFrames.keyFrames[ mm ]; - frameFound = true; - break; - - } - - } - - var frameValue = data2[ 2 ].split( ',' ); - switch ( nowKeyType ) { - - case 0: - keyInfo.rot = new Quaternion( parseFloat( frameValue[ 1 ] ), parseFloat( frameValue[ 2 ] ), parseFloat( frameValue[ 3 ] ), parseFloat( frameValue[ 0 ] ) * - 1 ); - break; - case 1: - keyInfo.scl = new Vector3( parseFloat( frameValue[ 0 ] ), parseFloat( frameValue[ 1 ] ), parseFloat( frameValue[ 2 ] ) ); - break; - case 2: - keyInfo.pos = new Vector3( parseFloat( frameValue[ 0 ] ), parseFloat( frameValue[ 1 ] ), parseFloat( frameValue[ 2 ] ) ); - break; - - } - - if ( ! frameFound ) { - - this._currentAnimeFrames.keyFrames.push( keyInfo ); - - } - - } else { - - keyInfo.matrix = new Matrix4(); - this._ParseMatrixData( keyInfo.matrix, data2[ 2 ].split( ',' ) ); - this._currentAnimeFrames.keyFrames.push( keyInfo ); - - } - - } - - } - }, { - key: '_makeOutputAnimation', - value: function _makeOutputAnimation() { - - var animationObj = new XAnimationObj( this.options ); - animationObj.fps = this.animTicksPerSecond; - animationObj.name = this._currentAnime.name; - animationObj.make( this._currentAnime.AnimeFrames ); - this.animations.push( animationObj ); - - } - }, { - key: 'assignAnimation', - value: function assignAnimation( _model, _animation ) { - - var model = _model; - var animation = _animation; - if ( ! model ) { - - model = this.Meshes[ 0 ]; - - } - - if ( ! animation ) { - - animation = this.animations[ 0 ]; - - } - - if ( ! model || ! animation ) { - - return null; - - } - - var put = {}; - put.fps = animation.fps; - put.name = animation.name; - put.length = animation.length; - put.hierarchy = []; - for ( var b = 0; b < model.skeleton.bones.length; b ++ ) { - - var findAnimation = false; - for ( var i = 0; i < animation.hierarchy.length; i ++ ) { - - if ( model.skeleton.bones[ b ].name === animation.hierarchy[ i ].name ) { - - findAnimation = true; - var c_key = animation.hierarchy[ i ].copy(); - c_key.parent = - 1; - if ( model.skeleton.bones[ b ].parent && model.skeleton.bones[ b ].parent.type === 'Bone' ) { - - for ( var bb = 0; bb < put.hierarchy.length; bb ++ ) { - - if ( put.hierarchy[ bb ].name === model.skeleton.bones[ b ].parent.name ) { - - c_key.parent = bb; - c_key.parentName = model.skeleton.bones[ b ].parent.name; - - } - - } - - } - - put.hierarchy.push( c_key ); - break; - - } - - } - - if ( ! findAnimation ) { - - var _c_key = animation.hierarchy[ 0 ].copy(); - _c_key.name = model.skeleton.bones[ b ].name; - _c_key.parent = - 1; - for ( var k = 0; k < _c_key.keys.length; k ++ ) { - - if ( _c_key.keys[ k ].pos ) { - - _c_key.keys[ k ].pos.set( 0, 0, 0 ); - - } - - if ( _c_key.keys[ k ].scl ) { - - _c_key.keys[ k ].scl.set( 1, 1, 1 ); - - } - - if ( _c_key.keys[ k ].rot ) { - - _c_key.keys[ k ].rot.set( 0, 0, 0, 1 ); - - } - - } - - put.hierarchy.push( _c_key ); - - } - - } - - if ( ! model.geometry.animations ) { - - model.geometry.animations = []; - - } - - model.geometry.animations.push( AnimationClip.parseAnimation( put, model.skeleton.bones ) ); - if ( ! model.animationMixer ) { - - model.animationMixer = new AnimationMixer( model ); - - } - - return put; - - } - }, { - key: '_ParseMatrixData', - value: function _ParseMatrixData( targetMatrix, data ) { - - targetMatrix.set( parseFloat( data[ 0 ] ), parseFloat( data[ 4 ] ), parseFloat( data[ 8 ] ), parseFloat( data[ 12 ] ), parseFloat( data[ 1 ] ), parseFloat( data[ 5 ] ), parseFloat( data[ 9 ] ), parseFloat( data[ 13 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 6 ] ), parseFloat( data[ 10 ] ), parseFloat( data[ 14 ] ), parseFloat( data[ 3 ] ), parseFloat( data[ 7 ] ), parseFloat( data[ 11 ] ), parseFloat( data[ 15 ] ) ); - - } - } ] ); - return XLoader; - - }(); - - return XLoader; - -} )(); - -export { XLoader }; diff --git a/examples/jsm/loaders/ifc/web-ifc-api.js b/examples/jsm/loaders/ifc/web-ifc-api.js index 57440cda30548b..c5ea0e61e637ce 100644 --- a/examples/jsm/loaders/ifc/web-ifc-api.js +++ b/examples/jsm/loaders/ifc/web-ifc-api.js @@ -6,6 +6,8 @@ var __commonJS = (callback, module) => () => { return module.exports; }; +let WasmPath = ""; + // dist/web-ifc.js var require_web_ifc = __commonJS((exports, module) => { var WebIFCWasm2 = function() { @@ -539,8 +541,7 @@ var require_web_ifc = __commonJS((exports, module) => { function isFileURI(filename) { return hasPrefix(filename, fileURIPrefix); } - var path = import.meta.url.substring(0, import.meta.url.lastIndexOf("/")+1); - var wasmBinaryFile = path + "web-ifc.wasm"; + var wasmBinaryFile = WasmPath + "web-ifc.wasm"; if (!isDataURI(wasmBinaryFile)) { wasmBinaryFile = locateFile(wasmBinaryFile); } @@ -576,7 +577,7 @@ var require_web_ifc = __commonJS((exports, module) => { function receiveInstance(instance, module2) { var exports3 = instance.exports; Module["asm"] = exports3; - wasmTable = Module["asm"]["L"]; + wasmTable = Module["asm"]["P"]; removeRunDependency("wasm-instantiate"); } addRunDependency("wasm-instantiate"); @@ -4111,6 +4112,36 @@ var require_web_ifc = __commonJS((exports, module) => { emval_handle_array[handle].refcount += 1; } } + function __emval_new_array() { + return __emval_register([]); + } + var emval_symbols = {}; + function getStringOrSymbol(address) { + var symbol = emval_symbols[address]; + if (symbol === void 0) { + return readLatin1String(address); + } else { + return symbol; + } + } + function __emval_new_cstring(v) { + return __emval_register(getStringOrSymbol(v)); + } + function __emval_new_object() { + return __emval_register({}); + } + function requireHandle(handle) { + if (!handle) { + throwBindingError("Cannot use deleted val. handle = " + handle); + } + return emval_handle_array[handle].value; + } + function __emval_set_property(handle, key2, value) { + handle = requireHandle(handle); + key2 = requireHandle(key2); + value = requireHandle(value); + handle[key2] = value; + } function requireRegisteredType(rawType, humanName) { var impl = registeredTypes[rawType]; if (impl === void 0) { @@ -4575,43 +4606,43 @@ var require_web_ifc = __commonJS((exports, module) => { __ATINIT__.push({func: function() { ___wasm_call_ctors(); }}); - var asmLibraryArg = {t: ___assert_fail, E: ___sys_ioctl, F: ___sys_open, u: __embind_finalize_value_array, j: __embind_finalize_value_object, H: __embind_register_bool, m: __embind_register_class, l: __embind_register_class_constructor, d: __embind_register_class_function, G: __embind_register_emval, q: __embind_register_float, i: __embind_register_function, f: __embind_register_integer, e: __embind_register_memory_view, r: __embind_register_std_string, n: __embind_register_std_wstring, v: __embind_register_value_array, c: __embind_register_value_array_element, k: __embind_register_value_object, g: __embind_register_value_object_field, I: __embind_register_void, J: __emval_decref, K: __emval_incref, s: __emval_take_value, b: _abort, C: _clock_gettime, y: _emscripten_memcpy_big, h: _emscripten_resize_heap, A: _environ_get, B: _environ_sizes_get, p: _fd_close, D: _fd_read, w: _fd_seek, o: _fd_write, a: wasmMemory, x: _setTempRet0, z: _strftime_l}; + var asmLibraryArg = {t: ___assert_fail, I: ___sys_ioctl, J: ___sys_open, N: __embind_finalize_value_array, r: __embind_finalize_value_object, L: __embind_register_bool, n: __embind_register_class, o: __embind_register_class_constructor, d: __embind_register_class_function, K: __embind_register_emval, w: __embind_register_float, l: __embind_register_function, h: __embind_register_integer, g: __embind_register_memory_view, x: __embind_register_std_string, q: __embind_register_std_wstring, O: __embind_register_value_array, e: __embind_register_value_array_element, s: __embind_register_value_object, i: __embind_register_value_object_field, M: __embind_register_void, c: __emval_decref, k: __emval_incref, y: __emval_new_array, p: __emval_new_cstring, z: __emval_new_object, j: __emval_set_property, f: __emval_take_value, b: _abort, G: _clock_gettime, C: _emscripten_memcpy_big, m: _emscripten_resize_heap, E: _environ_get, F: _environ_sizes_get, v: _fd_close, H: _fd_read, A: _fd_seek, u: _fd_write, a: wasmMemory, B: _setTempRet0, D: _strftime_l}; var asm = createWasm(); var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() { - return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["M"]).apply(null, arguments); + return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["Q"]).apply(null, arguments); }; var _main = Module["_main"] = function() { - return (_main = Module["_main"] = Module["asm"]["N"]).apply(null, arguments); + return (_main = Module["_main"] = Module["asm"]["R"]).apply(null, arguments); + }; + var _malloc = Module["_malloc"] = function() { + return (_malloc = Module["_malloc"] = Module["asm"]["S"]).apply(null, arguments); }; var ___getTypeName = Module["___getTypeName"] = function() { - return (___getTypeName = Module["___getTypeName"] = Module["asm"]["O"]).apply(null, arguments); + return (___getTypeName = Module["___getTypeName"] = Module["asm"]["T"]).apply(null, arguments); }; var ___embind_register_native_and_builtin_types = Module["___embind_register_native_and_builtin_types"] = function() { - return (___embind_register_native_and_builtin_types = Module["___embind_register_native_and_builtin_types"] = Module["asm"]["P"]).apply(null, arguments); + return (___embind_register_native_and_builtin_types = Module["___embind_register_native_and_builtin_types"] = Module["asm"]["U"]).apply(null, arguments); }; var ___errno_location = Module["___errno_location"] = function() { - return (___errno_location = Module["___errno_location"] = Module["asm"]["Q"]).apply(null, arguments); + return (___errno_location = Module["___errno_location"] = Module["asm"]["V"]).apply(null, arguments); }; var _free = Module["_free"] = function() { - return (_free = Module["_free"] = Module["asm"]["R"]).apply(null, arguments); - }; - var _malloc = Module["_malloc"] = function() { - return (_malloc = Module["_malloc"] = Module["asm"]["S"]).apply(null, arguments); + return (_free = Module["_free"] = Module["asm"]["W"]).apply(null, arguments); }; var dynCall_jiji = Module["dynCall_jiji"] = function() { - return (dynCall_jiji = Module["dynCall_jiji"] = Module["asm"]["T"]).apply(null, arguments); + return (dynCall_jiji = Module["dynCall_jiji"] = Module["asm"]["X"]).apply(null, arguments); }; var dynCall_viijii = Module["dynCall_viijii"] = function() { - return (dynCall_viijii = Module["dynCall_viijii"] = Module["asm"]["U"]).apply(null, arguments); + return (dynCall_viijii = Module["dynCall_viijii"] = Module["asm"]["Y"]).apply(null, arguments); }; var dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = function() { - return (dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = Module["asm"]["V"]).apply(null, arguments); + return (dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = Module["asm"]["Z"]).apply(null, arguments); }; var dynCall_iiiiij = Module["dynCall_iiiiij"] = function() { - return (dynCall_iiiiij = Module["dynCall_iiiiij"] = Module["asm"]["W"]).apply(null, arguments); + return (dynCall_iiiiij = Module["dynCall_iiiiij"] = Module["asm"]["_"]).apply(null, arguments); }; var dynCall_iiiiijj = Module["dynCall_iiiiijj"] = function() { - return (dynCall_iiiiijj = Module["dynCall_iiiiijj"] = Module["asm"]["X"]).apply(null, arguments); + return (dynCall_iiiiijj = Module["dynCall_iiiiijj"] = Module["asm"]["$"]).apply(null, arguments); }; Module["addRunDependency"] = addRunDependency; Module["removeRunDependency"] = removeRunDependency; @@ -4761,6 +4792,12 @@ var IfcAPI = class { GetGeometry(modelID, geometryExpressID) { return this.wasmModule.GetGeometry(modelID, geometryExpressID); } + GetLine(modelID, expressID) { + return this.wasmModule.GetLine(modelID, expressID); + } + GetLineIDsWithType(modelID, type) { + return this.wasmModule.GetLineIDsWithType(modelID, type); + } SetGeometryTransformation(modelID, transformationMatrix) { if (transformationMatrix.length != 16) { console.log(`Bad transformation matrix size: ${transformationMatrix.length}`); @@ -4786,6 +4823,9 @@ var IfcAPI = class { LoadAllGeometry(modelID) { return this.wasmModule.LoadAllGeometry(modelID); } + SetWasmPath(path){ + WasmPath = path; + } }; export { IfcAPI, diff --git a/examples/jsm/loaders/ifc/web-ifc.wasm b/examples/jsm/loaders/ifc/web-ifc.wasm index 686044f09faef9..f87db7f2a45018 100644 Binary files a/examples/jsm/loaders/ifc/web-ifc.wasm and b/examples/jsm/loaders/ifc/web-ifc.wasm differ diff --git a/examples/jsm/math/Capsule.js b/examples/jsm/math/Capsule.js index 4b53999e8ca736..38119c4414dea9 100644 --- a/examples/jsm/math/Capsule.js +++ b/examples/jsm/math/Capsule.js @@ -2,142 +2,136 @@ import { Vector3 } from '../../../build/three.module.js'; +const _v1 = new Vector3(); +const _v2 = new Vector3(); +const _v3 = new Vector3(); -var Capsule = ( function () { +const EPS = 1e-10; - var _v1 = new Vector3(); - var _v2 = new Vector3(); - var _v3 = new Vector3(); +class Capsule { - var EPS = 1e-10; + constructor( start = new Vector3( 0, 0, 0 ), end = new Vector3( 0, 1, 0 ), radius = 1 ) { - function Capsule( start, end, radius ) { - - this.start = start == undefined ? new Vector3( 0, 0, 0 ) : start; - this.end = end == undefined ? new Vector3( 0, 1, 0 ) : end; - this.radius = radius == undefined ? 1 : radius; + this.start = start; + this.end = end; + this.radius = radius; } - Object.assign( Capsule.prototype, { - - clone: function () { - - return new Capsule( this.start.clone(), this.end.clone(), this.radius ); - - }, - - set: function ( start, end, radius ) { + clone() { - this.start.copy( start ); - this.end.copy( end ); - this.radius = radius; + return new Capsule( this.start.clone(), this.end.clone(), this.radius ); - }, - - copy: function ( capsule ) { + } - this.start.copy( capsule.start ); - this.end.copy( capsule.end ); - this.radius = capsule.radius; + set( start, end, radius ) { - }, + this.start.copy( start ); + this.end.copy( end ); + this.radius = radius; - getCenter: function ( target ) { + } - return target.copy( this.end ).add( this.start ).multiplyScalar( 0.5 ); + copy( capsule ) { - }, + this.start.copy( capsule.start ); + this.end.copy( capsule.end ); + this.radius = capsule.radius; - translate: function ( v ) { + } - this.start.add( v ); - this.end.add( v ); + getCenter( target ) { - }, + return target.copy( this.end ).add( this.start ).multiplyScalar( 0.5 ); - checkAABBAxis: function ( p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius ) { + } - return ( - ( minx - p1x < radius || minx - p2x < radius ) && - ( p1x - maxx < radius || p2x - maxx < radius ) && - ( miny - p1y < radius || miny - p2y < radius ) && - ( p1y - maxy < radius || p2y - maxy < radius ) - ); + translate( v ) { - }, + this.start.add( v ); + this.end.add( v ); - intersectsBox: function ( box ) { + } - return ( - this.checkAABBAxis( - this.start.x, this.start.y, this.end.x, this.end.y, - box.min.x, box.max.x, box.min.y, box.max.y, - this.radius ) && - this.checkAABBAxis( - this.start.x, this.start.z, this.end.x, this.end.z, - box.min.x, box.max.x, box.min.z, box.max.z, - this.radius ) && - this.checkAABBAxis( - this.start.y, this.start.z, this.end.y, this.end.z, - box.min.y, box.max.y, box.min.z, box.max.z, - this.radius ) - ); + checkAABBAxis( p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius ) { - }, + return ( + ( minx - p1x < radius || minx - p2x < radius ) && + ( p1x - maxx < radius || p2x - maxx < radius ) && + ( miny - p1y < radius || miny - p2y < radius ) && + ( p1y - maxy < radius || p2y - maxy < radius ) + ); - lineLineMinimumPoints: function ( line1, line2 ) { + } - var r = _v1.copy( line1.end ).sub( line1.start ); - var s = _v2.copy( line2.end ).sub( line2.start ); - var w = _v3.copy( line2.start ).sub( line1.start ); + intersectsBox( box ) { + + return ( + this.checkAABBAxis( + this.start.x, this.start.y, this.end.x, this.end.y, + box.min.x, box.max.x, box.min.y, box.max.y, + this.radius ) && + this.checkAABBAxis( + this.start.x, this.start.z, this.end.x, this.end.z, + box.min.x, box.max.x, box.min.z, box.max.z, + this.radius ) && + this.checkAABBAxis( + this.start.y, this.start.z, this.end.y, this.end.z, + box.min.y, box.max.y, box.min.z, box.max.z, + this.radius ) + ); - var a = r.dot( s ), - b = r.dot( r ), - c = s.dot( s ), - d = s.dot( w ), - e = r.dot( w ); + } - var t1, t2, divisor = b * c - a * a; + lineLineMinimumPoints( line1, line2 ) { - if ( Math.abs( divisor ) < EPS ) { + const r = _v1.copy( line1.end ).sub( line1.start ); + const s = _v2.copy( line2.end ).sub( line2.start ); + const w = _v3.copy( line2.start ).sub( line1.start ); - var d1 = - d / c; - var d2 = ( a - d ) / c; + const a = r.dot( s ), + b = r.dot( r ), + c = s.dot( s ), + d = s.dot( w ), + e = r.dot( w ); - if ( Math.abs( d1 - 0.5 ) < Math.abs( d2 - 0.5 ) ) { + let t1, t2; + const divisor = b * c - a * a; - t1 = 0; - t2 = d1; + if ( Math.abs( divisor ) < EPS ) { - } else { + const d1 = - d / c; + const d2 = ( a - d ) / c; - t1 = 1; - t2 = d2; + if ( Math.abs( d1 - 0.5 ) < Math.abs( d2 - 0.5 ) ) { - } + t1 = 0; + t2 = d1; } else { - t1 = ( d * a + e * c ) / divisor; - t2 = ( t1 * a - d ) / c; + t1 = 1; + t2 = d2; } - t2 = Math.max( 0, Math.min( 1, t2 ) ); - t1 = Math.max( 0, Math.min( 1, t1 ) ); + } else { - var point1 = r.multiplyScalar( t1 ).add( line1.start ); - var point2 = s.multiplyScalar( t2 ).add( line2.start ); - - return [ point1, point2 ]; + t1 = ( d * a + e * c ) / divisor; + t2 = ( t1 * a - d ) / c; } - } ); + t2 = Math.max( 0, Math.min( 1, t2 ) ); + t1 = Math.max( 0, Math.min( 1, t1 ) ); + + const point1 = r.multiplyScalar( t1 ).add( line1.start ); + const point2 = s.multiplyScalar( t2 ).add( line2.start ); - return Capsule; + return [ point1, point2 ]; + + } -} )(); +} export { Capsule }; diff --git a/examples/jsm/math/ColorConverter.js b/examples/jsm/math/ColorConverter.js index 7309dd97b4bcae..faf7f9f49ba7c8 100644 --- a/examples/jsm/math/ColorConverter.js +++ b/examples/jsm/math/ColorConverter.js @@ -2,9 +2,11 @@ import { MathUtils } from '../../../build/three.module.js'; -var ColorConverter = { +const _hsl = {}; - setHSV: function ( color, h, s, v ) { +class ColorConverter { + + static setHSV( color, h, s, v ) { // https://gist.github.com/xpansive/1337890#file-index-js @@ -14,49 +16,43 @@ var ColorConverter = { return color.setHSL( h, ( s * v ) / ( ( h = ( 2 - s ) * v ) < 1 ? h : ( 2 - h ) ), h * 0.5 ); - }, - - getHSV: function () { - - var hsl = {}; - - return function getHSV( color, target ) { + } - if ( target === undefined ) { + static getHSV( color, target ) { - console.warn( 'THREE.ColorConverter: .getHSV() target is now required' ); - target = { h: 0, s: 0, l: 0 }; + if ( target === undefined ) { - } + console.warn( 'THREE.ColorConverter: .getHSV() target is now required' ); + target = { h: 0, s: 0, l: 0 }; - color.getHSL( hsl ); + } - // based on https://gist.github.com/xpansive/1337890#file-index-js - hsl.s *= ( hsl.l < 0.5 ) ? hsl.l : ( 1 - hsl.l ); + color.getHSL( _hsl ); - target.h = hsl.h; - target.s = 2 * hsl.s / ( hsl.l + hsl.s ); - target.v = hsl.l + hsl.s; + // based on https://gist.github.com/xpansive/1337890#file-index-js + _hsl.s *= ( _hsl.l < 0.5 ) ? _hsl.l : ( 1 - _hsl.l ); - return target; + target.h = _hsl.h; + target.s = 2 * _hsl.s / ( _hsl.l + _hsl.s ); + target.v = _hsl.l + _hsl.s; - }; + return target; - }(), + } // where c, m, y, k is between 0 and 1 - setCMYK: function ( color, c, m, y, k ) { + static setCMYK( color, c, m, y, k ) { - var r = ( 1 - c ) * ( 1 - k ); - var g = ( 1 - m ) * ( 1 - k ); - var b = ( 1 - y ) * ( 1 - k ); + const r = ( 1 - c ) * ( 1 - k ); + const g = ( 1 - m ) * ( 1 - k ); + const b = ( 1 - y ) * ( 1 - k ); return color.setRGB( r, g, b ); - }, + } - getCMYK: function ( color, target ) { + static getCMYK( color, target ) { if ( target === undefined ) { @@ -65,14 +61,14 @@ var ColorConverter = { } - var r = color.r; - var g = color.g; - var b = color.b; + const r = color.r; + const g = color.g; + const b = color.b; - var k = 1 - Math.max( r, g, b ); - var c = ( 1 - r - k ) / ( 1 - k ); - var m = ( 1 - g - k ) / ( 1 - k ); - var y = ( 1 - b - k ) / ( 1 - k ); + const k = 1 - Math.max( r, g, b ); + const c = ( 1 - r - k ) / ( 1 - k ); + const m = ( 1 - g - k ) / ( 1 - k ); + const y = ( 1 - b - k ) / ( 1 - k ); target.c = c; target.m = m; @@ -83,7 +79,6 @@ var ColorConverter = { } - -}; +} export { ColorConverter }; diff --git a/examples/jsm/math/ConvexHull.js b/examples/jsm/math/ConvexHull.js index 6e24ea26a72318..e42cc74ec3572e 100644 --- a/examples/jsm/math/ConvexHull.js +++ b/examples/jsm/math/ConvexHull.js @@ -9,14 +9,18 @@ import { * Ported from: https://github.com/maurizzzio/quickhull3d/ by Mauricio Poppe (https://github.com/maurizzzio) */ -var ConvexHull = ( function () { +const Visible = 0; +const Deleted = 1; - var Visible = 0; - var Deleted = 1; +const _v1 = new Vector3(); +const _line3 = new Line3(); +const _plane = new Plane(); +const _closestPoint = new Vector3(); +const _triangle = new Triangle(); - var v1 = new Vector3(); +class ConvexHull { - function ConvexHull() { + constructor() { this.tolerance = - 1; @@ -40,70 +44,64 @@ var ConvexHull = ( function () { } - Object.assign( ConvexHull.prototype, { + setFromPoints( points ) { - setFromPoints: function ( points ) { + if ( Array.isArray( points ) !== true ) { - if ( Array.isArray( points ) !== true ) { + console.error( 'THREE.ConvexHull: Points parameter is not an array.' ); - console.error( 'THREE.ConvexHull: Points parameter is not an array.' ); - - } - - if ( points.length < 4 ) { - - console.error( 'THREE.ConvexHull: The algorithm needs at least four points.' ); + } - } + if ( points.length < 4 ) { - this.makeEmpty(); + console.error( 'THREE.ConvexHull: The algorithm needs at least four points.' ); - for ( var i = 0, l = points.length; i < l; i ++ ) { + } - this.vertices.push( new VertexNode( points[ i ] ) ); + this.makeEmpty(); - } + for ( let i = 0, l = points.length; i < l; i ++ ) { - this.compute(); + this.vertices.push( new VertexNode( points[ i ] ) ); - return this; + } - }, + this.compute(); - setFromObject: function ( object ) { + return this; - var points = []; + } - object.updateMatrixWorld( true ); + setFromObject( object ) { - object.traverse( function ( node ) { + const points = []; - var i, l, point; + object.updateMatrixWorld( true ); - var geometry = node.geometry; + object.traverse( function ( node ) { - if ( geometry !== undefined ) { + const geometry = node.geometry; - if ( geometry.isGeometry ) { + if ( geometry !== undefined ) { - console.error( 'THREE.ConvexHull no longer supports Geometry. Use THREE.BufferGeometry instead.' ); - return; + if ( geometry.isGeometry ) { - } else if ( geometry.isBufferGeometry ) { + console.error( 'THREE.ConvexHull no longer supports Geometry. Use THREE.BufferGeometry instead.' ); + return; - var attribute = geometry.attributes.position; + } else if ( geometry.isBufferGeometry ) { - if ( attribute !== undefined ) { + const attribute = geometry.attributes.position; - for ( i = 0, l = attribute.count; i < l; i ++ ) { + if ( attribute !== undefined ) { - point = new Vector3(); + for ( let i = 0, l = attribute.count; i < l; i ++ ) { - point.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); + const point = new Vector3(); - points.push( point ); + point.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); - } + points.push( point ); } @@ -111,834 +109,821 @@ var ConvexHull = ( function () { } - } ); + } - return this.setFromPoints( points ); + } ); - }, + return this.setFromPoints( points ); - containsPoint: function ( point ) { + } - var faces = this.faces; + containsPoint( point ) { - for ( var i = 0, l = faces.length; i < l; i ++ ) { + const faces = this.faces; - var face = faces[ i ]; + for ( let i = 0, l = faces.length; i < l; i ++ ) { - // compute signed distance and check on what half space the point lies + const face = faces[ i ]; - if ( face.distanceToPoint( point ) > this.tolerance ) return false; + // compute signed distance and check on what half space the point lies - } + if ( face.distanceToPoint( point ) > this.tolerance ) return false; - return true; + } - }, + return true; - intersectRay: function ( ray, target ) { + } - // based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II + intersectRay( ray, target ) { - var faces = this.faces; + // based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II - var tNear = - Infinity; - var tFar = Infinity; + const faces = this.faces; - for ( var i = 0, l = faces.length; i < l; i ++ ) { + let tNear = - Infinity; + let tFar = Infinity; - var face = faces[ i ]; + for ( let i = 0, l = faces.length; i < l; i ++ ) { - // interpret faces as planes for the further computation + const face = faces[ i ]; - var vN = face.distanceToPoint( ray.origin ); - var vD = face.normal.dot( ray.direction ); + // interpret faces as planes for the further computation - // if the origin is on the positive side of a plane (so the plane can "see" the origin) and - // the ray is turned away or parallel to the plane, there is no intersection + const vN = face.distanceToPoint( ray.origin ); + const vD = face.normal.dot( ray.direction ); - if ( vN > 0 && vD >= 0 ) return null; + // if the origin is on the positive side of a plane (so the plane can "see" the origin) and + // the ray is turned away or parallel to the plane, there is no intersection - // compute the distance from the ray’s origin to the intersection with the plane + if ( vN > 0 && vD >= 0 ) return null; - var t = ( vD !== 0 ) ? ( - vN / vD ) : 0; + // compute the distance from the ray’s origin to the intersection with the plane - // only proceed if the distance is positive. a negative distance means the intersection point - // lies "behind" the origin + const t = ( vD !== 0 ) ? ( - vN / vD ) : 0; - if ( t <= 0 ) continue; + // only proceed if the distance is positive. a negative distance means the intersection point + // lies "behind" the origin - // now categorized plane as front-facing or back-facing + if ( t <= 0 ) continue; - if ( vD > 0 ) { + // now categorized plane as front-facing or back-facing - // plane faces away from the ray, so this plane is a back-face + if ( vD > 0 ) { - tFar = Math.min( t, tFar ); + // plane faces away from the ray, so this plane is a back-face - } else { + tFar = Math.min( t, tFar ); - // front-face + } else { - tNear = Math.max( t, tNear ); + // front-face - } + tNear = Math.max( t, tNear ); - if ( tNear > tFar ) { + } - // if tNear ever is greater than tFar, the ray must miss the convex hull + if ( tNear > tFar ) { - return null; + // if tNear ever is greater than tFar, the ray must miss the convex hull - } + return null; } - // evaluate intersection point + } - // always try tNear first since its the closer intersection point + // evaluate intersection point - if ( tNear !== - Infinity ) { + // always try tNear first since its the closer intersection point - ray.at( tNear, target ); + if ( tNear !== - Infinity ) { - } else { + ray.at( tNear, target ); - ray.at( tFar, target ); + } else { - } + ray.at( tFar, target ); - return target; + } - }, + return target; - intersectsRay: function ( ray ) { + } - return this.intersectRay( ray, v1 ) !== null; + intersectsRay( ray ) { - }, + return this.intersectRay( ray, _v1 ) !== null; - makeEmpty: function () { + } - this.faces = []; - this.vertices = []; + makeEmpty() { - return this; + this.faces = []; + this.vertices = []; - }, + return this; - // Adds a vertex to the 'assigned' list of vertices and assigns it to the given face + } - addVertexToFace: function ( vertex, face ) { + // Adds a vertex to the 'assigned' list of vertices and assigns it to the given face - vertex.face = face; + addVertexToFace( vertex, face ) { - if ( face.outside === null ) { + vertex.face = face; - this.assigned.append( vertex ); + if ( face.outside === null ) { - } else { + this.assigned.append( vertex ); - this.assigned.insertBefore( face.outside, vertex ); + } else { - } + this.assigned.insertBefore( face.outside, vertex ); - face.outside = vertex; + } - return this; + face.outside = vertex; - }, + return this; - // Removes a vertex from the 'assigned' list of vertices and from the given face + } - removeVertexFromFace: function ( vertex, face ) { + // Removes a vertex from the 'assigned' list of vertices and from the given face - if ( vertex === face.outside ) { + removeVertexFromFace( vertex, face ) { - // fix face.outside link + if ( vertex === face.outside ) { - if ( vertex.next !== null && vertex.next.face === face ) { + // fix face.outside link - // face has at least 2 outside vertices, move the 'outside' reference + if ( vertex.next !== null && vertex.next.face === face ) { - face.outside = vertex.next; + // face has at least 2 outside vertices, move the 'outside' reference - } else { + face.outside = vertex.next; - // vertex was the only outside vertex that face had + } else { - face.outside = null; + // vertex was the only outside vertex that face had - } + face.outside = null; } - this.assigned.remove( vertex ); + } - return this; + this.assigned.remove( vertex ); - }, + return this; - // Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list + } - removeAllVerticesFromFace: function ( face ) { + // Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list - if ( face.outside !== null ) { + removeAllVerticesFromFace( face ) { - // reference to the first and last vertex of this face + if ( face.outside !== null ) { - var start = face.outside; - var end = face.outside; + // reference to the first and last vertex of this face - while ( end.next !== null && end.next.face === face ) { + const start = face.outside; + let end = face.outside; - end = end.next; + while ( end.next !== null && end.next.face === face ) { - } + end = end.next; - this.assigned.removeSubList( start, end ); + } - // fix references + this.assigned.removeSubList( start, end ); - start.prev = end.next = null; - face.outside = null; + // fix references - return start; + start.prev = end.next = null; + face.outside = null; - } + return start; - }, + } - // Removes all the visible vertices that 'face' is able to see + } - deleteFaceVertices: function ( face, absorbingFace ) { + // Removes all the visible vertices that 'face' is able to see - var faceVertices = this.removeAllVerticesFromFace( face ); + deleteFaceVertices( face, absorbingFace ) { - if ( faceVertices !== undefined ) { + const faceVertices = this.removeAllVerticesFromFace( face ); - if ( absorbingFace === undefined ) { + if ( faceVertices !== undefined ) { - // mark the vertices to be reassigned to some other face + if ( absorbingFace === undefined ) { - this.unassigned.appendChain( faceVertices ); + // mark the vertices to be reassigned to some other face + this.unassigned.appendChain( faceVertices ); - } else { - // if there's an absorbing face try to assign as many vertices as possible to it + } else { - var vertex = faceVertices; + // if there's an absorbing face try to assign as many vertices as possible to it - do { + let vertex = faceVertices; - // we need to buffer the subsequent vertex at this point because the 'vertex.next' reference - // will be changed by upcoming method calls + do { - var nextVertex = vertex.next; + // we need to buffer the subsequent vertex at this point because the 'vertex.next' reference + // will be changed by upcoming method calls - var distance = absorbingFace.distanceToPoint( vertex.point ); + const nextVertex = vertex.next; - // check if 'vertex' is able to see 'absorbingFace' + const distance = absorbingFace.distanceToPoint( vertex.point ); - if ( distance > this.tolerance ) { + // check if 'vertex' is able to see 'absorbingFace' - this.addVertexToFace( vertex, absorbingFace ); + if ( distance > this.tolerance ) { - } else { + this.addVertexToFace( vertex, absorbingFace ); - this.unassigned.append( vertex ); + } else { - } + this.unassigned.append( vertex ); - // now assign next vertex + } - vertex = nextVertex; + // now assign next vertex - } while ( vertex !== null ); + vertex = nextVertex; - } + } while ( vertex !== null ); } - return this; - - }, + } - // Reassigns as many vertices as possible from the unassigned list to the new faces + return this; - resolveUnassignedPoints: function ( newFaces ) { + } - if ( this.unassigned.isEmpty() === false ) { + // Reassigns as many vertices as possible from the unassigned list to the new faces - var vertex = this.unassigned.first(); + resolveUnassignedPoints( newFaces ) { - do { + if ( this.unassigned.isEmpty() === false ) { - // buffer 'next' reference, see .deleteFaceVertices() + let vertex = this.unassigned.first(); - var nextVertex = vertex.next; + do { - var maxDistance = this.tolerance; + // buffer 'next' reference, see .deleteFaceVertices() - var maxFace = null; + const nextVertex = vertex.next; - for ( var i = 0; i < newFaces.length; i ++ ) { + let maxDistance = this.tolerance; - var face = newFaces[ i ]; + let maxFace = null; - if ( face.mark === Visible ) { + for ( let i = 0; i < newFaces.length; i ++ ) { - var distance = face.distanceToPoint( vertex.point ); + const face = newFaces[ i ]; - if ( distance > maxDistance ) { + if ( face.mark === Visible ) { - maxDistance = distance; - maxFace = face; + const distance = face.distanceToPoint( vertex.point ); - } + if ( distance > maxDistance ) { - if ( maxDistance > 1000 * this.tolerance ) break; + maxDistance = distance; + maxFace = face; } - } - - // 'maxFace' can be null e.g. if there are identical vertices - - if ( maxFace !== null ) { - - this.addVertexToFace( vertex, maxFace ); + if ( maxDistance > 1000 * this.tolerance ) break; } - vertex = nextVertex; - - } while ( vertex !== null ); - - } - - return this; + } - }, + // 'maxFace' can be null e.g. if there are identical vertices - // Computes the extremes of a simplex which will be the initial hull + if ( maxFace !== null ) { - computeExtremes: function () { + this.addVertexToFace( vertex, maxFace ); - var min = new Vector3(); - var max = new Vector3(); + } - var minVertices = []; - var maxVertices = []; + vertex = nextVertex; - var i, l, j; + } while ( vertex !== null ); - // initially assume that the first vertex is the min/max + } - for ( i = 0; i < 3; i ++ ) { + return this; - minVertices[ i ] = maxVertices[ i ] = this.vertices[ 0 ]; + } - } + // Computes the extremes of a simplex which will be the initial hull - min.copy( this.vertices[ 0 ].point ); - max.copy( this.vertices[ 0 ].point ); + computeExtremes() { - // compute the min/max vertex on all six directions + const min = new Vector3(); + const max = new Vector3(); - for ( i = 0, l = this.vertices.length; i < l; i ++ ) { + const minVertices = []; + const maxVertices = []; - var vertex = this.vertices[ i ]; - var point = vertex.point; + // initially assume that the first vertex is the min/max - // update the min coordinates + for ( let i = 0; i < 3; i ++ ) { - for ( j = 0; j < 3; j ++ ) { + minVertices[ i ] = maxVertices[ i ] = this.vertices[ 0 ]; - if ( point.getComponent( j ) < min.getComponent( j ) ) { + } - min.setComponent( j, point.getComponent( j ) ); - minVertices[ j ] = vertex; + min.copy( this.vertices[ 0 ].point ); + max.copy( this.vertices[ 0 ].point ); - } + // compute the min/max vertex on all six directions - } + for ( let i = 0, l = this.vertices.length; i < l; i ++ ) { - // update the max coordinates + const vertex = this.vertices[ i ]; + const point = vertex.point; - for ( j = 0; j < 3; j ++ ) { + // update the min coordinates - if ( point.getComponent( j ) > max.getComponent( j ) ) { + for ( let j = 0; j < 3; j ++ ) { - max.setComponent( j, point.getComponent( j ) ); - maxVertices[ j ] = vertex; + if ( point.getComponent( j ) < min.getComponent( j ) ) { - } + min.setComponent( j, point.getComponent( j ) ); + minVertices[ j ] = vertex; } } - // use min/max vectors to compute an optimal epsilon + // update the max coordinates - this.tolerance = 3 * Number.EPSILON * ( - Math.max( Math.abs( min.x ), Math.abs( max.x ) ) + - Math.max( Math.abs( min.y ), Math.abs( max.y ) ) + - Math.max( Math.abs( min.z ), Math.abs( max.z ) ) - ); - - return { min: minVertices, max: maxVertices }; + for ( let j = 0; j < 3; j ++ ) { - }, + if ( point.getComponent( j ) > max.getComponent( j ) ) { - // Computes the initial simplex assigning to its faces all the points - // that are candidates to form part of the hull + max.setComponent( j, point.getComponent( j ) ); + maxVertices[ j ] = vertex; - computeInitialHull: function () { + } - var line3, plane, closestPoint; + } - return function computeInitialHull() { + } - if ( line3 === undefined ) { + // use min/max vectors to compute an optimal epsilon - line3 = new Line3(); - plane = new Plane(); - closestPoint = new Vector3(); + this.tolerance = 3 * Number.EPSILON * ( + Math.max( Math.abs( min.x ), Math.abs( max.x ) ) + + Math.max( Math.abs( min.y ), Math.abs( max.y ) ) + + Math.max( Math.abs( min.z ), Math.abs( max.z ) ) + ); - } + return { min: minVertices, max: maxVertices }; - var vertex, vertices = this.vertices; - var extremes = this.computeExtremes(); - var min = extremes.min; - var max = extremes.max; + } - var v0, v1, v2, v3; - var i, l, j; + // Computes the initial simplex assigning to its faces all the points + // that are candidates to form part of the hull - // 1. Find the two vertices 'v0' and 'v1' with the greatest 1d separation - // (max.x - min.x) - // (max.y - min.y) - // (max.z - min.z) + computeInitialHull() { - var distance, maxDistance = 0; - var index = 0; + const vertices = this.vertices; + const extremes = this.computeExtremes(); + const min = extremes.min; + const max = extremes.max; - for ( i = 0; i < 3; i ++ ) { + // 1. Find the two vertices 'v0' and 'v1' with the greatest 1d separation + // (max.x - min.x) + // (max.y - min.y) + // (max.z - min.z) - distance = max[ i ].point.getComponent( i ) - min[ i ].point.getComponent( i ); + let maxDistance = 0; + let index = 0; - if ( distance > maxDistance ) { + for ( let i = 0; i < 3; i ++ ) { - maxDistance = distance; - index = i; + const distance = max[ i ].point.getComponent( i ) - min[ i ].point.getComponent( i ); - } + if ( distance > maxDistance ) { - } + maxDistance = distance; + index = i; - v0 = min[ index ]; - v1 = max[ index ]; + } - // 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1' + } - maxDistance = 0; - line3.set( v0.point, v1.point ); + const v0 = min[ index ]; + const v1 = max[ index ]; + let v2; + let v3; - for ( i = 0, l = this.vertices.length; i < l; i ++ ) { + // 2. The next vertex 'v2' is the one farthest to the line formed by 'v0' and 'v1' - vertex = vertices[ i ]; + maxDistance = 0; + _line3.set( v0.point, v1.point ); - if ( vertex !== v0 && vertex !== v1 ) { + for ( let i = 0, l = this.vertices.length; i < l; i ++ ) { - line3.closestPointToPoint( vertex.point, true, closestPoint ); + const vertex = vertices[ i ]; - distance = closestPoint.distanceToSquared( vertex.point ); + if ( vertex !== v0 && vertex !== v1 ) { - if ( distance > maxDistance ) { + _line3.closestPointToPoint( vertex.point, true, _closestPoint ); - maxDistance = distance; - v2 = vertex; + const distance = _closestPoint.distanceToSquared( vertex.point ); - } + if ( distance > maxDistance ) { - } + maxDistance = distance; + v2 = vertex; } - // 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2' + } - maxDistance = - 1; - plane.setFromCoplanarPoints( v0.point, v1.point, v2.point ); + } - for ( i = 0, l = this.vertices.length; i < l; i ++ ) { + // 3. The next vertex 'v3' is the one farthest to the plane 'v0', 'v1', 'v2' - vertex = vertices[ i ]; + maxDistance = - 1; + _plane.setFromCoplanarPoints( v0.point, v1.point, v2.point ); - if ( vertex !== v0 && vertex !== v1 && vertex !== v2 ) { + for ( let i = 0, l = this.vertices.length; i < l; i ++ ) { - distance = Math.abs( plane.distanceToPoint( vertex.point ) ); + const vertex = vertices[ i ]; - if ( distance > maxDistance ) { + if ( vertex !== v0 && vertex !== v1 && vertex !== v2 ) { - maxDistance = distance; - v3 = vertex; + const distance = Math.abs( _plane.distanceToPoint( vertex.point ) ); - } + if ( distance > maxDistance ) { - } + maxDistance = distance; + v3 = vertex; } - var faces = []; + } - if ( plane.distanceToPoint( v3.point ) < 0 ) { + } - // the face is not able to see the point so 'plane.normal' is pointing outside the tetrahedron + const faces = []; - faces.push( - Face.create( v0, v1, v2 ), - Face.create( v3, v1, v0 ), - Face.create( v3, v2, v1 ), - Face.create( v3, v0, v2 ) - ); + if ( _plane.distanceToPoint( v3.point ) < 0 ) { - // set the twin edge + // the face is not able to see the point so 'plane.normal' is pointing outside the tetrahedron - for ( i = 0; i < 3; i ++ ) { + faces.push( + Face.create( v0, v1, v2 ), + Face.create( v3, v1, v0 ), + Face.create( v3, v2, v1 ), + Face.create( v3, v0, v2 ) + ); - j = ( i + 1 ) % 3; + // set the twin edge - // join face[ i ] i > 0, with the first face + for ( let i = 0; i < 3; i ++ ) { - faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( j ) ); + const j = ( i + 1 ) % 3; - // join face[ i ] with face[ i + 1 ], 1 <= i <= 3 + // join face[ i ] i > 0, with the first face - faces[ i + 1 ].getEdge( 1 ).setTwin( faces[ j + 1 ].getEdge( 0 ) ); + faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( j ) ); - } + // join face[ i ] with face[ i + 1 ], 1 <= i <= 3 - } else { + faces[ i + 1 ].getEdge( 1 ).setTwin( faces[ j + 1 ].getEdge( 0 ) ); - // the face is able to see the point so 'plane.normal' is pointing inside the tetrahedron + } - faces.push( - Face.create( v0, v2, v1 ), - Face.create( v3, v0, v1 ), - Face.create( v3, v1, v2 ), - Face.create( v3, v2, v0 ) - ); + } else { - // set the twin edge + // the face is able to see the point so 'plane.normal' is pointing inside the tetrahedron - for ( i = 0; i < 3; i ++ ) { + faces.push( + Face.create( v0, v2, v1 ), + Face.create( v3, v0, v1 ), + Face.create( v3, v1, v2 ), + Face.create( v3, v2, v0 ) + ); - j = ( i + 1 ) % 3; + // set the twin edge - // join face[ i ] i > 0, with the first face + for ( let i = 0; i < 3; i ++ ) { - faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( ( 3 - i ) % 3 ) ); + const j = ( i + 1 ) % 3; - // join face[ i ] with face[ i + 1 ] + // join face[ i ] i > 0, with the first face - faces[ i + 1 ].getEdge( 0 ).setTwin( faces[ j + 1 ].getEdge( 1 ) ); + faces[ i + 1 ].getEdge( 2 ).setTwin( faces[ 0 ].getEdge( ( 3 - i ) % 3 ) ); - } + // join face[ i ] with face[ i + 1 ] - } + faces[ i + 1 ].getEdge( 0 ).setTwin( faces[ j + 1 ].getEdge( 1 ) ); - // the initial hull is the tetrahedron + } - for ( i = 0; i < 4; i ++ ) { + } - this.faces.push( faces[ i ] ); + // the initial hull is the tetrahedron - } + for ( let i = 0; i < 4; i ++ ) { - // initial assignment of vertices to the faces of the tetrahedron + this.faces.push( faces[ i ] ); - for ( i = 0, l = vertices.length; i < l; i ++ ) { + } - vertex = vertices[ i ]; + // initial assignment of vertices to the faces of the tetrahedron - if ( vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3 ) { + for ( let i = 0, l = vertices.length; i < l; i ++ ) { - maxDistance = this.tolerance; - var maxFace = null; + const vertex = vertices[ i ]; - for ( j = 0; j < 4; j ++ ) { + if ( vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3 ) { - distance = this.faces[ j ].distanceToPoint( vertex.point ); + maxDistance = this.tolerance; + let maxFace = null; - if ( distance > maxDistance ) { + for ( let j = 0; j < 4; j ++ ) { - maxDistance = distance; - maxFace = this.faces[ j ]; + const distance = this.faces[ j ].distanceToPoint( vertex.point ); - } + if ( distance > maxDistance ) { - } + maxDistance = distance; + maxFace = this.faces[ j ]; - if ( maxFace !== null ) { + } - this.addVertexToFace( vertex, maxFace ); + } - } + if ( maxFace !== null ) { - } + this.addVertexToFace( vertex, maxFace ); } - return this; + } - }; + } - }(), + return this; - // Removes inactive faces + } - reindexFaces: function () { + // Removes inactive faces - var activeFaces = []; + reindexFaces() { - for ( var i = 0; i < this.faces.length; i ++ ) { + const activeFaces = []; - var face = this.faces[ i ]; + for ( let i = 0; i < this.faces.length; i ++ ) { - if ( face.mark === Visible ) { + const face = this.faces[ i ]; - activeFaces.push( face ); + if ( face.mark === Visible ) { - } + activeFaces.push( face ); } - this.faces = activeFaces; + } - return this; + this.faces = activeFaces; - }, + return this; - // Finds the next vertex to create faces with the current hull + } - nextVertexToAdd: function () { + // Finds the next vertex to create faces with the current hull - // if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined' + nextVertexToAdd() { - if ( this.assigned.isEmpty() === false ) { + // if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined' - var eyeVertex, maxDistance = 0; + if ( this.assigned.isEmpty() === false ) { - // grap the first available face and start with the first visible vertex of that face + let eyeVertex, maxDistance = 0; - var eyeFace = this.assigned.first().face; - var vertex = eyeFace.outside; + // grap the first available face and start with the first visible vertex of that face - // now calculate the farthest vertex that face can see + const eyeFace = this.assigned.first().face; + let vertex = eyeFace.outside; - do { + // now calculate the farthest vertex that face can see - var distance = eyeFace.distanceToPoint( vertex.point ); + do { - if ( distance > maxDistance ) { + const distance = eyeFace.distanceToPoint( vertex.point ); - maxDistance = distance; - eyeVertex = vertex; + if ( distance > maxDistance ) { - } + maxDistance = distance; + eyeVertex = vertex; - vertex = vertex.next; + } - } while ( vertex !== null && vertex.face === eyeFace ); + vertex = vertex.next; - return eyeVertex; + } while ( vertex !== null && vertex.face === eyeFace ); - } + return eyeVertex; - }, + } - // Computes a chain of half edges in CCW order called the 'horizon'. - // For an edge to be part of the horizon it must join a face that can see - // 'eyePoint' and a face that cannot see 'eyePoint'. + } - computeHorizon: function ( eyePoint, crossEdge, face, horizon ) { + // Computes a chain of half edges in CCW order called the 'horizon'. + // For an edge to be part of the horizon it must join a face that can see + // 'eyePoint' and a face that cannot see 'eyePoint'. - // moves face's vertices to the 'unassigned' vertex list + computeHorizon( eyePoint, crossEdge, face, horizon ) { - this.deleteFaceVertices( face ); + // moves face's vertices to the 'unassigned' vertex list - face.mark = Deleted; + this.deleteFaceVertices( face ); - var edge; + face.mark = Deleted; - if ( crossEdge === null ) { + let edge; - edge = crossEdge = face.getEdge( 0 ); + if ( crossEdge === null ) { - } else { + edge = crossEdge = face.getEdge( 0 ); - // start from the next edge since 'crossEdge' was already analyzed - // (actually 'crossEdge.twin' was the edge who called this method recursively) + } else { - edge = crossEdge.next; + // start from the next edge since 'crossEdge' was already analyzed + // (actually 'crossEdge.twin' was the edge who called this method recursively) - } + edge = crossEdge.next; - do { + } - var twinEdge = edge.twin; - var oppositeFace = twinEdge.face; + do { - if ( oppositeFace.mark === Visible ) { + const twinEdge = edge.twin; + const oppositeFace = twinEdge.face; - if ( oppositeFace.distanceToPoint( eyePoint ) > this.tolerance ) { + if ( oppositeFace.mark === Visible ) { - // the opposite face can see the vertex, so proceed with next edge + if ( oppositeFace.distanceToPoint( eyePoint ) > this.tolerance ) { - this.computeHorizon( eyePoint, twinEdge, oppositeFace, horizon ); + // the opposite face can see the vertex, so proceed with next edge - } else { + this.computeHorizon( eyePoint, twinEdge, oppositeFace, horizon ); - // the opposite face can't see the vertex, so this edge is part of the horizon + } else { - horizon.push( edge ); + // the opposite face can't see the vertex, so this edge is part of the horizon - } + horizon.push( edge ); } - edge = edge.next; - - } while ( edge !== crossEdge ); + } - return this; + edge = edge.next; - }, + } while ( edge !== crossEdge ); - // Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order + return this; - addAdjoiningFace: function ( eyeVertex, horizonEdge ) { + } - // all the half edges are created in ccw order thus the face is always pointing outside the hull + // Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order - var face = Face.create( eyeVertex, horizonEdge.tail(), horizonEdge.head() ); + addAdjoiningFace( eyeVertex, horizonEdge ) { - this.faces.push( face ); + // all the half edges are created in ccw order thus the face is always pointing outside the hull - // join face.getEdge( - 1 ) with the horizon's opposite edge face.getEdge( - 1 ) = face.getEdge( 2 ) + const face = Face.create( eyeVertex, horizonEdge.tail(), horizonEdge.head() ); - face.getEdge( - 1 ).setTwin( horizonEdge.twin ); + this.faces.push( face ); - return face.getEdge( 0 ); // the half edge whose vertex is the eyeVertex + // join face.getEdge( - 1 ) with the horizon's opposite edge face.getEdge( - 1 ) = face.getEdge( 2 ) + face.getEdge( - 1 ).setTwin( horizonEdge.twin ); - }, + return face.getEdge( 0 ); // the half edge whose vertex is the eyeVertex - // Adds 'horizon.length' faces to the hull, each face will be linked with the - // horizon opposite face and the face on the left/right - addNewFaces: function ( eyeVertex, horizon ) { + } - this.newFaces = []; + // Adds 'horizon.length' faces to the hull, each face will be linked with the + // horizon opposite face and the face on the left/right - var firstSideEdge = null; - var previousSideEdge = null; + addNewFaces( eyeVertex, horizon ) { - for ( var i = 0; i < horizon.length; i ++ ) { + this.newFaces = []; - var horizonEdge = horizon[ i ]; + let firstSideEdge = null; + let previousSideEdge = null; - // returns the right side edge + for ( let i = 0; i < horizon.length; i ++ ) { - var sideEdge = this.addAdjoiningFace( eyeVertex, horizonEdge ); + const horizonEdge = horizon[ i ]; - if ( firstSideEdge === null ) { + // returns the right side edge - firstSideEdge = sideEdge; + const sideEdge = this.addAdjoiningFace( eyeVertex, horizonEdge ); - } else { + if ( firstSideEdge === null ) { - // joins face.getEdge( 1 ) with previousFace.getEdge( 0 ) + firstSideEdge = sideEdge; - sideEdge.next.setTwin( previousSideEdge ); + } else { - } + // joins face.getEdge( 1 ) with previousFace.getEdge( 0 ) - this.newFaces.push( sideEdge.face ); - previousSideEdge = sideEdge; + sideEdge.next.setTwin( previousSideEdge ); } - // perform final join of new faces + this.newFaces.push( sideEdge.face ); + previousSideEdge = sideEdge; - firstSideEdge.next.setTwin( previousSideEdge ); + } - return this; + // perform final join of new faces - }, + firstSideEdge.next.setTwin( previousSideEdge ); - // Adds a vertex to the hull + return this; - addVertexToHull: function ( eyeVertex ) { + } - var horizon = []; + // Adds a vertex to the hull - this.unassigned.clear(); + addVertexToHull( eyeVertex ) { - // remove 'eyeVertex' from 'eyeVertex.face' so that it can't be added to the 'unassigned' vertex list + const horizon = []; - this.removeVertexFromFace( eyeVertex, eyeVertex.face ); + this.unassigned.clear(); - this.computeHorizon( eyeVertex.point, null, eyeVertex.face, horizon ); + // remove 'eyeVertex' from 'eyeVertex.face' so that it can't be added to the 'unassigned' vertex list - this.addNewFaces( eyeVertex, horizon ); + this.removeVertexFromFace( eyeVertex, eyeVertex.face ); - // reassign 'unassigned' vertices to the new faces + this.computeHorizon( eyeVertex.point, null, eyeVertex.face, horizon ); - this.resolveUnassignedPoints( this.newFaces ); + this.addNewFaces( eyeVertex, horizon ); - return this; + // reassign 'unassigned' vertices to the new faces - }, + this.resolveUnassignedPoints( this.newFaces ); - cleanup: function () { + return this; - this.assigned.clear(); - this.unassigned.clear(); - this.newFaces = []; + } - return this; + cleanup() { - }, + this.assigned.clear(); + this.unassigned.clear(); + this.newFaces = []; - compute: function () { + return this; - var vertex; + } - this.computeInitialHull(); + compute() { - // add all available vertices gradually to the hull + let vertex; - while ( ( vertex = this.nextVertexToAdd() ) !== undefined ) { + this.computeInitialHull(); - this.addVertexToHull( vertex ); + // add all available vertices gradually to the hull - } + while ( ( vertex = this.nextVertexToAdd() ) !== undefined ) { - this.reindexFaces(); + this.addVertexToHull( vertex ); - this.cleanup(); + } - return this; + this.reindexFaces(); - } + this.cleanup(); + + return this; + + } - } ); +} - // +// - function Face() { +class Face { + + constructor() { this.normal = new Vector3(); this.midpoint = new Vector3(); @@ -951,93 +936,82 @@ var ConvexHull = ( function () { } - Object.assign( Face, { - - create: function ( a, b, c ) { - - var face = new Face(); - - var e0 = new HalfEdge( a, face ); - var e1 = new HalfEdge( b, face ); - var e2 = new HalfEdge( c, face ); + static create( a, b, c ) { - // join edges + const face = new Face(); - e0.next = e2.prev = e1; - e1.next = e0.prev = e2; - e2.next = e1.prev = e0; + const e0 = new HalfEdge( a, face ); + const e1 = new HalfEdge( b, face ); + const e2 = new HalfEdge( c, face ); - // main half edge reference + // join edges - face.edge = e0; - - return face.compute(); - - } + e0.next = e2.prev = e1; + e1.next = e0.prev = e2; + e2.next = e1.prev = e0; - } ); + // main half edge reference - Object.assign( Face.prototype, { + face.edge = e0; - getEdge: function ( i ) { + return face.compute(); - var edge = this.edge; + } - while ( i > 0 ) { + getEdge( i ) { - edge = edge.next; - i --; + let edge = this.edge; - } + while ( i > 0 ) { - while ( i < 0 ) { + edge = edge.next; + i --; - edge = edge.prev; - i ++; + } - } + while ( i < 0 ) { - return edge; + edge = edge.prev; + i ++; - }, + } - compute: function () { + return edge; - var triangle; + } - return function compute() { + compute() { - if ( triangle === undefined ) triangle = new Triangle(); + const a = this.edge.tail(); + const b = this.edge.head(); + const c = this.edge.next.head(); - var a = this.edge.tail(); - var b = this.edge.head(); - var c = this.edge.next.head(); + _triangle.set( a.point, b.point, c.point ); - triangle.set( a.point, b.point, c.point ); + _triangle.getNormal( this.normal ); + _triangle.getMidpoint( this.midpoint ); + this.area = _triangle.getArea(); - triangle.getNormal( this.normal ); - triangle.getMidpoint( this.midpoint ); - this.area = triangle.getArea(); + this.constant = this.normal.dot( this.midpoint ); - this.constant = this.normal.dot( this.midpoint ); + return this; - return this; + } - }; + distanceToPoint( point ) { - }(), + return this.normal.dot( point ) - this.constant; - distanceToPoint: function ( point ) { + } - return this.normal.dot( point ) - this.constant; +} - } +// Entity for a Doubly-Connected Edge List (DCEL). - } ); +class HalfEdge { - // Entity for a Doubly-Connected Edge List (DCEL). - function HalfEdge( vertex, face ) { + constructor( vertex, face ) { this.vertex = vertex; this.prev = null; @@ -1047,64 +1021,64 @@ var ConvexHull = ( function () { } - Object.assign( HalfEdge.prototype, { + head() { - head: function () { + return this.vertex; - return this.vertex; + } - }, + tail() { - tail: function () { + return this.prev ? this.prev.vertex : null; - return this.prev ? this.prev.vertex : null; + } - }, + length() { - length: function () { + const head = this.head(); + const tail = this.tail(); - var head = this.head(); - var tail = this.tail(); + if ( tail !== null ) { - if ( tail !== null ) { + return tail.point.distanceTo( head.point ); - return tail.point.distanceTo( head.point ); + } - } + return - 1; - return - 1; + } - }, + lengthSquared() { - lengthSquared: function () { + const head = this.head(); + const tail = this.tail(); - var head = this.head(); - var tail = this.tail(); + if ( tail !== null ) { - if ( tail !== null ) { + return tail.point.distanceToSquared( head.point ); - return tail.point.distanceToSquared( head.point ); + } - } + return - 1; - return - 1; + } - }, + setTwin( edge ) { - setTwin: function ( edge ) { + this.twin = edge; + edge.twin = this; - this.twin = edge; - edge.twin = this; + return this; - return this; + } - } +} - } ); +// A vertex as a double linked list node. - // A vertex as a double linked list node. +class VertexNode { - function VertexNode( point ) { + constructor( point ) { this.point = point; this.prev = null; @@ -1113,202 +1087,200 @@ var ConvexHull = ( function () { } - // A double linked list that contains vertex nodes. +} - function VertexList() { +// A double linked list that contains vertex nodes. + +class VertexList { + + constructor() { this.head = null; this.tail = null; } - Object.assign( VertexList.prototype, { - - first: function () { + first() { - return this.head; + return this.head; - }, - - last: function () { - - return this.tail; + } - }, + last() { - clear: function () { + return this.tail; - this.head = this.tail = null; + } - return this; + clear() { - }, + this.head = this.tail = null; - // Inserts a vertex before the target vertex + return this; - insertBefore: function ( target, vertex ) { + } - vertex.prev = target.prev; - vertex.next = target; + // Inserts a vertex before the target vertex - if ( vertex.prev === null ) { + insertBefore( target, vertex ) { - this.head = vertex; + vertex.prev = target.prev; + vertex.next = target; - } else { + if ( vertex.prev === null ) { - vertex.prev.next = vertex; + this.head = vertex; - } + } else { - target.prev = vertex; + vertex.prev.next = vertex; - return this; + } - }, + target.prev = vertex; - // Inserts a vertex after the target vertex + return this; - insertAfter: function ( target, vertex ) { + } - vertex.prev = target; - vertex.next = target.next; + // Inserts a vertex after the target vertex - if ( vertex.next === null ) { + insertAfter( target, vertex ) { - this.tail = vertex; + vertex.prev = target; + vertex.next = target.next; - } else { + if ( vertex.next === null ) { - vertex.next.prev = vertex; + this.tail = vertex; - } + } else { - target.next = vertex; + vertex.next.prev = vertex; - return this; + } - }, + target.next = vertex; - // Appends a vertex to the end of the linked list + return this; - append: function ( vertex ) { + } - if ( this.head === null ) { + // Appends a vertex to the end of the linked list - this.head = vertex; + append( vertex ) { - } else { + if ( this.head === null ) { - this.tail.next = vertex; + this.head = vertex; - } + } else { - vertex.prev = this.tail; - vertex.next = null; // the tail has no subsequent vertex + this.tail.next = vertex; - this.tail = vertex; + } - return this; + vertex.prev = this.tail; + vertex.next = null; // the tail has no subsequent vertex - }, + this.tail = vertex; - // Appends a chain of vertices where 'vertex' is the head. + return this; - appendChain: function ( vertex ) { + } - if ( this.head === null ) { + // Appends a chain of vertices where 'vertex' is the head. - this.head = vertex; + appendChain( vertex ) { - } else { + if ( this.head === null ) { - this.tail.next = vertex; + this.head = vertex; - } + } else { - vertex.prev = this.tail; + this.tail.next = vertex; - // ensure that the 'tail' reference points to the last vertex of the chain + } - while ( vertex.next !== null ) { + vertex.prev = this.tail; - vertex = vertex.next; + // ensure that the 'tail' reference points to the last vertex of the chain - } + while ( vertex.next !== null ) { - this.tail = vertex; + vertex = vertex.next; - return this; + } - }, + this.tail = vertex; - // Removes a vertex from the linked list + return this; - remove: function ( vertex ) { + } - if ( vertex.prev === null ) { + // Removes a vertex from the linked list - this.head = vertex.next; + remove( vertex ) { - } else { + if ( vertex.prev === null ) { - vertex.prev.next = vertex.next; + this.head = vertex.next; - } + } else { - if ( vertex.next === null ) { + vertex.prev.next = vertex.next; - this.tail = vertex.prev; + } - } else { + if ( vertex.next === null ) { - vertex.next.prev = vertex.prev; + this.tail = vertex.prev; - } + } else { - return this; + vertex.next.prev = vertex.prev; - }, + } - // Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b + return this; - removeSubList: function ( a, b ) { + } - if ( a.prev === null ) { + // Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b - this.head = b.next; + removeSubList( a, b ) { - } else { + if ( a.prev === null ) { - a.prev.next = b.next; + this.head = b.next; - } + } else { - if ( b.next === null ) { + a.prev.next = b.next; - this.tail = a.prev; + } - } else { + if ( b.next === null ) { - b.next.prev = a.prev; + this.tail = a.prev; - } + } else { - return this; + b.next.prev = a.prev; - }, + } - isEmpty: function () { + return this; - return this.head === null; + } - } + isEmpty() { - } ); + return this.head === null; - return ConvexHull; + } -} )(); +} export { ConvexHull }; diff --git a/examples/jsm/math/ImprovedNoise.js b/examples/jsm/math/ImprovedNoise.js index 1c0f99634122bf..8e197e5f375128 100644 --- a/examples/jsm/math/ImprovedNoise.js +++ b/examples/jsm/math/ImprovedNoise.js @@ -1,74 +1,71 @@ // http://mrl.nyu.edu/~perlin/noise/ -var ImprovedNoise = function () { +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 ]; - var 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 ++ ) { - for ( var i = 0; i < 256; i ++ ) { + _p[ 256 + i ] = _p[ i ]; - p[ 256 + i ] = p[ i ]; +} - } - - function fade( t ) { +function fade( t ) { - return t * t * t * ( t * ( t * 6 - 15 ) + 10 ); + return t * t * t * ( t * ( t * 6 - 15 ) + 10 ); - } +} - function lerp( t, a, b ) { +function lerp( t, a, b ) { - return a + t * ( b - a ); + return a + t * ( b - a ); - } +} - function grad( hash, x, y, z ) { +function grad( hash, x, y, z ) { - var h = hash & 15; - var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; - return ( ( h & 1 ) == 0 ? u : - u ) + ( ( h & 2 ) == 0 ? v : - v ); + const h = hash & 15; + const u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; + return ( ( h & 1 ) == 0 ? u : - u ) + ( ( h & 2 ) == 0 ? v : - v ); - } +} - return { +class ImprovedNoise { - noise: function ( x, y, z ) { + noise( x, y, z ) { - var floorX = Math.floor( x ), floorY = Math.floor( y ), floorZ = Math.floor( z ); + const floorX = Math.floor( x ), floorY = Math.floor( y ), floorZ = Math.floor( z ); - var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255; + const X = floorX & 255, Y = floorY & 255, Z = floorZ & 255; - x -= floorX; - y -= floorY; - z -= floorZ; + x -= floorX; + y -= floorY; + z -= floorZ; - var xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1; + const xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1; - var u = fade( x ), v = fade( y ), w = fade( z ); + const u = fade( x ), v = fade( y ), w = fade( z ); - var A = p[ X ] + Y, AA = p[ A ] + Z, AB = p[ A + 1 ] + Z, B = p[ X + 1 ] + Y, BA = p[ B ] + Z, BB = p[ B + 1 ] + Z; + const A = _p[ X ] + Y, AA = _p[ A ] + Z, AB = _p[ A + 1 ] + Z, B = _p[ X + 1 ] + Y, BA = _p[ B ] + Z, BB = _p[ B + 1 ] + Z; - return lerp( w, lerp( v, lerp( u, grad( p[ AA ], x, y, z ), - grad( p[ BA ], xMinus1, y, z ) ), - lerp( u, grad( p[ AB ], x, yMinus1, z ), - grad( p[ BB ], xMinus1, yMinus1, z ) ) ), - lerp( v, lerp( u, grad( p[ AA + 1 ], x, y, zMinus1 ), - grad( p[ BA + 1 ], xMinus1, y, zMinus1 ) ), - lerp( u, grad( p[ AB + 1 ], x, yMinus1, zMinus1 ), - grad( p[ BB + 1 ], xMinus1, yMinus1, zMinus1 ) ) ) ); + return lerp( w, lerp( v, lerp( u, grad( _p[ AA ], x, y, z ), + grad( _p[ BA ], xMinus1, y, z ) ), + lerp( u, grad( _p[ AB ], x, yMinus1, z ), + grad( _p[ BB ], xMinus1, yMinus1, z ) ) ), + lerp( v, lerp( u, grad( _p[ AA + 1 ], x, y, zMinus1 ), + grad( _p[ BA + 1 ], xMinus1, y, zMinus1 ) ), + lerp( u, grad( _p[ AB + 1 ], x, yMinus1, zMinus1 ), + grad( _p[ BB + 1 ], xMinus1, yMinus1, zMinus1 ) ) ) ); - } - }; + } -}; +} export { ImprovedNoise }; diff --git a/examples/jsm/math/Lut.js b/examples/jsm/math/Lut.js index a59d9572aabe07..7092705bb0aec7 100644 --- a/examples/jsm/math/Lut.js +++ b/examples/jsm/math/Lut.js @@ -2,21 +2,16 @@ import { Color } from '../../../build/three.module.js'; -var Lut = function ( colormap, numberofcolors ) { +class Lut { - this.lut = []; - this.setColorMap( colormap, numberofcolors ); - return this; + constructor( colormap, numberofcolors ) { -}; - -Lut.prototype = { + this.lut = []; + this.setColorMap( colormap, numberofcolors ); - constructor: Lut, - - lut: [], map: [], n: 256, minV: 0, maxV: 1, + } - set: function ( value ) { + set( value ) { if ( value instanceof Lut ) { @@ -26,45 +21,46 @@ Lut.prototype = { return this; - }, + } - setMin: function ( min ) { + setMin( min ) { this.minV = min; return this; - }, + } - setMax: function ( max ) { + setMax( max ) { this.maxV = max; return this; - }, + } - setColorMap: function ( colormap, numberofcolors ) { + setColorMap( colormap, numberofcolors = 32 ) { this.map = ColorMapKeywords[ colormap ] || ColorMapKeywords.rainbow; - this.n = numberofcolors || 32; + this.n = numberofcolors; - var step = 1.0 / this.n; + const step = 1.0 / this.n; this.lut.length = 0; - for ( var i = 0; i <= 1; i += step ) { - for ( var j = 0; j < this.map.length - 1; j ++ ) { + for ( let i = 0; i <= 1; i += step ) { + + for ( let j = 0; j < this.map.length - 1; j ++ ) { if ( i >= this.map[ j ][ 0 ] && i < this.map[ j + 1 ][ 0 ] ) { - var min = this.map[ j ][ 0 ]; - var max = this.map[ j + 1 ][ 0 ]; + const min = this.map[ j ][ 0 ]; + const max = this.map[ j + 1 ][ 0 ]; - var minColor = new Color( this.map[ j ][ 1 ] ); - var maxColor = new Color( this.map[ j + 1 ][ 1 ] ); + const minColor = new Color( this.map[ j ][ 1 ] ); + const maxColor = new Color( this.map[ j + 1 ][ 1 ] ); - var color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) ); + const color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) ); this.lut.push( color ); @@ -76,9 +72,9 @@ Lut.prototype = { return this; - }, + } - copy: function ( lut ) { + copy( lut ) { this.lut = lut.lut; this.map = lut.map; @@ -88,9 +84,9 @@ Lut.prototype = { return this; - }, + } - getColor: function ( alpha ) { + getColor( alpha ) { if ( alpha <= this.minV ) { @@ -104,22 +100,22 @@ Lut.prototype = { alpha = ( alpha - this.minV ) / ( this.maxV - this.minV ); - var colorPosition = Math.round( alpha * this.n ); + let colorPosition = Math.round( alpha * this.n ); colorPosition == this.n ? colorPosition -= 1 : colorPosition; return this.lut[ colorPosition ]; - }, + } - addColorMap: function ( colormapName, arrayOfColors ) { + addColorMap( colormapName, arrayOfColors ) { ColorMapKeywords[ colormapName ] = arrayOfColors; - }, + } - createCanvas: function () { + createCanvas() { - var canvas = document.createElement( 'canvas' ); + const canvas = document.createElement( 'canvas' ); canvas.width = 1; canvas.height = this.n; @@ -127,33 +123,33 @@ Lut.prototype = { return canvas; - }, + } - updateCanvas: function ( canvas ) { + updateCanvas( canvas ) { - var ctx = canvas.getContext( '2d', { alpha: false } ); + const ctx = canvas.getContext( '2d', { alpha: false } ); - var imageData = ctx.getImageData( 0, 0, 1, this.n ); + const imageData = ctx.getImageData( 0, 0, 1, this.n ); - var data = imageData.data; + const data = imageData.data; - var k = 0; + let k = 0; - var step = 1.0 / this.n; + const step = 1.0 / this.n; - for ( var i = 1; i >= 0; i -= step ) { + for ( let i = 1; i >= 0; i -= step ) { - for ( var j = this.map.length - 1; j >= 0; j -- ) { + for ( let j = this.map.length - 1; j >= 0; j -- ) { if ( i < this.map[ j ][ 0 ] && i >= this.map[ j - 1 ][ 0 ] ) { - var min = this.map[ j - 1 ][ 0 ]; - var max = this.map[ j ][ 0 ]; + const min = this.map[ j - 1 ][ 0 ]; + const max = this.map[ j ][ 0 ]; - var minColor = new Color( this.map[ j - 1 ][ 1 ] ); - var maxColor = new Color( this.map[ j ][ 1 ] ); + const minColor = new Color( this.map[ j - 1 ][ 1 ] ); + const maxColor = new Color( this.map[ j ][ 1 ] ); - var color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) ); + const color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) ); data[ k * 4 ] = Math.round( color.r * 255 ); data[ k * 4 + 1 ] = Math.round( color.g * 255 ); @@ -173,9 +169,16 @@ Lut.prototype = { return canvas; } -}; -var ColorMapKeywords = { +} + +Lut.prototype.lut = []; +Lut.prototype.map = []; +Lut.prototype.n = 256; +Lut.prototype.minV = 0; +Lut.prototype.maxV = 1; + +const ColorMapKeywords = { 'rainbow': [[ 0.0, 0x0000FF ], [ 0.2, 0x00FFFF ], [ 0.5, 0x00FF00 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFF0000 ]], 'cooltowarm': [[ 0.0, 0x3C4EC2 ], [ 0.2, 0x9BBCFF ], [ 0.5, 0xDCDCDC ], [ 0.8, 0xF6A385 ], [ 1.0, 0xB40426 ]], diff --git a/examples/jsm/math/MeshSurfaceSampler.js b/examples/jsm/math/MeshSurfaceSampler.js index 2aa03261556963..bc4efc5fbd08e7 100644 --- a/examples/jsm/math/MeshSurfaceSampler.js +++ b/examples/jsm/math/MeshSurfaceSampler.js @@ -13,14 +13,15 @@ import { * - http://www.joesfer.com/?p=84 * - https://stackoverflow.com/a/4322940/1314762 */ -var MeshSurfaceSampler = ( function () { - var _face = new Triangle(); - var _color = new Vector3(); +const _face = new Triangle(); +const _color = new Vector3(); - function MeshSurfaceSampler( mesh ) { +class MeshSurfaceSampler { - var geometry = mesh.geometry; + constructor( mesh ) { + + let geometry = mesh.geometry; if ( ! geometry.isBufferGeometry || geometry.attributes.position.itemSize !== 3 ) { @@ -47,172 +48,164 @@ var MeshSurfaceSampler = ( function () { } - MeshSurfaceSampler.prototype = { - - constructor: MeshSurfaceSampler, + setWeightAttribute( name ) { - setWeightAttribute: function ( name ) { + this.weightAttribute = name ? this.geometry.getAttribute( name ) : null; - this.weightAttribute = name ? this.geometry.getAttribute( name ) : null; + return this; - return this; - - }, + } - build: function () { + build() { - var positionAttribute = this.positionAttribute; - var weightAttribute = this.weightAttribute; + const positionAttribute = this.positionAttribute; + const weightAttribute = this.weightAttribute; - var faceWeights = new Float32Array( positionAttribute.count / 3 ); + const faceWeights = new Float32Array( positionAttribute.count / 3 ); - // Accumulate weights for each mesh face. + // Accumulate weights for each mesh face. - for ( var i = 0; i < positionAttribute.count; i += 3 ) { + for ( let i = 0; i < positionAttribute.count; i += 3 ) { - var faceWeight = 1; + let faceWeight = 1; - if ( weightAttribute ) { + if ( weightAttribute ) { - faceWeight = weightAttribute.getX( i ) - + weightAttribute.getX( i + 1 ) - + weightAttribute.getX( i + 2 ); + faceWeight = weightAttribute.getX( i ) + + weightAttribute.getX( i + 1 ) + + weightAttribute.getX( i + 2 ); - } + } - _face.a.fromBufferAttribute( positionAttribute, i ); - _face.b.fromBufferAttribute( positionAttribute, i + 1 ); - _face.c.fromBufferAttribute( positionAttribute, i + 2 ); - faceWeight *= _face.getArea(); + _face.a.fromBufferAttribute( positionAttribute, i ); + _face.b.fromBufferAttribute( positionAttribute, i + 1 ); + _face.c.fromBufferAttribute( positionAttribute, i + 2 ); + faceWeight *= _face.getArea(); - faceWeights[ i / 3 ] = faceWeight; + faceWeights[ i / 3 ] = faceWeight; - } + } - // Store cumulative total face weights in an array, where weight index - // corresponds to face index. + // Store cumulative total face weights in an array, where weight index + // corresponds to face index. - this.distribution = new Float32Array( positionAttribute.count / 3 ); + this.distribution = new Float32Array( positionAttribute.count / 3 ); - var cumulativeTotal = 0; + let cumulativeTotal = 0; - for ( var i = 0; i < faceWeights.length; i ++ ) { + for ( let i = 0; i < faceWeights.length; i ++ ) { - cumulativeTotal += faceWeights[ i ]; + cumulativeTotal += faceWeights[ i ]; - this.distribution[ i ] = cumulativeTotal; + this.distribution[ i ] = cumulativeTotal; - } - - return this; + } - }, + return this; - setRandomGenerator: function ( randomFunction ) { + } - this.randomFunction = randomFunction; - return this; + setRandomGenerator( randomFunction ) { - }, + this.randomFunction = randomFunction; + return this; - sample: function ( targetPosition, targetNormal, targetColor ) { + } - var cumulativeTotal = this.distribution[ this.distribution.length - 1 ]; + sample( targetPosition, targetNormal, targetColor ) { - var faceIndex = this.binarySearch( this.randomFunction() * cumulativeTotal ); + const cumulativeTotal = this.distribution[ this.distribution.length - 1 ]; - return this.sampleFace( faceIndex, targetPosition, targetNormal, targetColor ); + const faceIndex = this.binarySearch( this.randomFunction() * cumulativeTotal ); - }, + return this.sampleFace( faceIndex, targetPosition, targetNormal, targetColor ); - binarySearch: function ( x ) { + } - var dist = this.distribution; - var start = 0; - var end = dist.length - 1; + binarySearch( x ) { - var index = - 1; + const dist = this.distribution; + let start = 0; + let end = dist.length - 1; - while ( start <= end ) { + let index = - 1; - var mid = Math.ceil( ( start + end ) / 2 ); + while ( start <= end ) { - if ( mid === 0 || dist[ mid - 1 ] <= x && dist[ mid ] > x ) { + const mid = Math.ceil( ( start + end ) / 2 ); - index = mid; + if ( mid === 0 || dist[ mid - 1 ] <= x && dist[ mid ] > x ) { - break; + index = mid; - } else if ( x < dist[ mid ] ) { + break; - end = mid - 1; + } else if ( x < dist[ mid ] ) { - } else { + end = mid - 1; - start = mid + 1; + } else { - } + start = mid + 1; } - return index; - - }, + } - sampleFace: function ( faceIndex, targetPosition, targetNormal, targetColor ) { + return index; - var u = this.randomFunction(); - var v = this.randomFunction(); + } - if ( u + v > 1 ) { + sampleFace( faceIndex, targetPosition, targetNormal, targetColor ) { - u = 1 - u; - v = 1 - v; + let u = this.randomFunction(); + let v = this.randomFunction(); - } + if ( u + v > 1 ) { - _face.a.fromBufferAttribute( this.positionAttribute, faceIndex * 3 ); - _face.b.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 1 ); - _face.c.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 2 ); + u = 1 - u; + v = 1 - v; - targetPosition - .set( 0, 0, 0 ) - .addScaledVector( _face.a, u ) - .addScaledVector( _face.b, v ) - .addScaledVector( _face.c, 1 - ( u + v ) ); + } - if ( targetNormal !== undefined ) { + _face.a.fromBufferAttribute( this.positionAttribute, faceIndex * 3 ); + _face.b.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 1 ); + _face.c.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 2 ); - _face.getNormal( targetNormal ); + targetPosition + .set( 0, 0, 0 ) + .addScaledVector( _face.a, u ) + .addScaledVector( _face.b, v ) + .addScaledVector( _face.c, 1 - ( u + v ) ); - } + if ( targetNormal !== undefined ) { - if ( targetColor !== undefined && this.colorAttribute !== undefined ) { + _face.getNormal( targetNormal ); - _face.a.fromBufferAttribute( this.colorAttribute, faceIndex * 3 ); - _face.b.fromBufferAttribute( this.colorAttribute, faceIndex * 3 + 1 ); - _face.c.fromBufferAttribute( this.colorAttribute, faceIndex * 3 + 2 ); + } - _color - .set( 0, 0, 0 ) - .addScaledVector( _face.a, u ) - .addScaledVector( _face.b, v ) - .addScaledVector( _face.c, 1 - ( u + v ) ); + if ( targetColor !== undefined && this.colorAttribute !== undefined ) { - targetColor.r = _color.x; - targetColor.g = _color.y; - targetColor.b = _color.z; + _face.a.fromBufferAttribute( this.colorAttribute, faceIndex * 3 ); + _face.b.fromBufferAttribute( this.colorAttribute, faceIndex * 3 + 1 ); + _face.c.fromBufferAttribute( this.colorAttribute, faceIndex * 3 + 2 ); - } + _color + .set( 0, 0, 0 ) + .addScaledVector( _face.a, u ) + .addScaledVector( _face.b, v ) + .addScaledVector( _face.c, 1 - ( u + v ) ); - return this; + targetColor.r = _color.x; + targetColor.g = _color.y; + targetColor.b = _color.z; } - }; + return this; - return MeshSurfaceSampler; + } -} )(); +} export { MeshSurfaceSampler }; diff --git a/examples/jsm/math/OBB.js b/examples/jsm/math/OBB.js index eb0b7d04673d38..35d6b48c3b7583 100644 --- a/examples/jsm/math/OBB.js +++ b/examples/jsm/math/OBB.js @@ -9,47 +9,47 @@ import { // module scope helper variables -var a = { +const a = { c: null, // center u: [ new Vector3(), new Vector3(), new Vector3() ], // basis vectors e: [] // half width }; -var b = { +const b = { c: null, // center u: [ new Vector3(), new Vector3(), new Vector3() ], // basis vectors e: [] // half width }; -var R = [[], [], []]; -var AbsR = [[], [], []]; -var t = []; - -var xAxis = new Vector3(); -var yAxis = new Vector3(); -var zAxis = new Vector3(); -var v1 = new Vector3(); -var size = new Vector3(); -var closestPoint = new Vector3(); -var rotationMatrix = new Matrix3(); -var aabb = new Box3(); -var matrix = new Matrix4(); -var inverse = new Matrix4(); -var localRay = new Ray(); +const R = [[], [], []]; +const AbsR = [[], [], []]; +const t = []; + +const xAxis = new Vector3(); +const yAxis = new Vector3(); +const zAxis = new Vector3(); +const v1 = new Vector3(); +const size = new Vector3(); +const closestPoint = new Vector3(); +const rotationMatrix = new Matrix3(); +const aabb = new Box3(); +const matrix = new Matrix4(); +const inverse = new Matrix4(); +const localRay = new Ray(); // OBB -function OBB( center = new Vector3(), halfSize = new Vector3(), rotation = new Matrix3() ) { +class OBB { - this.center = center; - this.halfSize = halfSize; - this.rotation = rotation; + constructor( center = new Vector3(), halfSize = new Vector3(), rotation = new Matrix3() ) { -} + this.center = center; + this.halfSize = halfSize; + this.rotation = rotation; -Object.assign( OBB.prototype, { + } - set: function ( center, halfSize, rotation ) { + set( center, halfSize, rotation ) { this.center = center; this.halfSize = halfSize; @@ -57,9 +57,9 @@ Object.assign( OBB.prototype, { return this; - }, + } - copy: function ( obb ) { + copy( obb ) { this.center.copy( obb.center ); this.halfSize.copy( obb.halfSize ); @@ -67,27 +67,27 @@ Object.assign( OBB.prototype, { return this; - }, + } - clone: function () { + clone() { return new this.constructor().copy( this ); - }, + } - getSize: function ( result ) { + getSize( result ) { return result.copy( this.halfSize ).multiplyScalar( 2 ); - }, + } /** * Reference: Closest Point on OBB to Point in Real-Time Collision Detection * by Christer Ericson (chapter 5.1.4) */ - clampPoint: function ( point, result ) { + clampPoint( point, result ) { - var halfSize = this.halfSize; + const halfSize = this.halfSize; v1.subVectors( point, this.center ); this.rotation.extractBasis( xAxis, yAxis, zAxis ); @@ -98,20 +98,20 @@ Object.assign( OBB.prototype, { // project the target onto the OBB axes and walk towards that point - var x = MathUtils.clamp( v1.dot( xAxis ), - halfSize.x, halfSize.x ); + const x = MathUtils.clamp( v1.dot( xAxis ), - halfSize.x, halfSize.x ); result.add( xAxis.multiplyScalar( x ) ); - var y = MathUtils.clamp( v1.dot( yAxis ), - halfSize.y, halfSize.y ); + const y = MathUtils.clamp( v1.dot( yAxis ), - halfSize.y, halfSize.y ); result.add( yAxis.multiplyScalar( y ) ); - var z = MathUtils.clamp( v1.dot( zAxis ), - halfSize.z, halfSize.z ); + const z = MathUtils.clamp( v1.dot( zAxis ), - halfSize.z, halfSize.z ); result.add( zAxis.multiplyScalar( z ) ); return result; - }, + } - containsPoint: function ( point ) { + containsPoint( point ) { v1.subVectors( point, this.center ); this.rotation.extractBasis( xAxis, yAxis, zAxis ); @@ -122,15 +122,15 @@ Object.assign( OBB.prototype, { Math.abs( v1.dot( yAxis ) ) <= this.halfSize.y && Math.abs( v1.dot( zAxis ) ) <= this.halfSize.z; - }, + } - intersectsBox3: function ( box3 ) { + intersectsBox3( box3 ) { return this.intersectsOBB( obb.fromBox3( box3 ) ); - }, + } - intersectsSphere: function ( sphere ) { + intersectsSphere( sphere ) { // find the point on the OBB closest to the sphere center @@ -140,14 +140,14 @@ Object.assign( OBB.prototype, { return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); - }, + } /** * Reference: OBB-OBB Intersection in Real-Time Collision Detection * by Christer Ericson (chapter 4.4.1) * */ - intersectsOBB: function ( obb, epsilon = Number.EPSILON ) { + intersectsOBB( obb, epsilon = Number.EPSILON ) { // prepare data structures (the code uses the same nomenclature like the reference) @@ -165,9 +165,9 @@ Object.assign( OBB.prototype, { // compute rotation matrix expressing b in a's coordinate frame - for ( var i = 0; i < 3; i ++ ) { + for ( let i = 0; i < 3; i ++ ) { - for ( var j = 0; j < 3; j ++ ) { + for ( let j = 0; j < 3; j ++ ) { R[ i ][ j ] = a.u[ i ].dot( b.u[ j ] ); @@ -189,9 +189,9 @@ Object.assign( OBB.prototype, { // counteract arithmetic errors when two edges are parallel and // their cross product is (near) null - for ( var i = 0; i < 3; i ++ ) { + for ( let i = 0; i < 3; i ++ ) { - for ( var j = 0; j < 3; j ++ ) { + for ( let j = 0; j < 3; j ++ ) { AbsR[ i ][ j ] = Math.abs( R[ i ][ j ] ) + epsilon; @@ -199,11 +199,11 @@ Object.assign( OBB.prototype, { } - var ra, rb; + let ra, rb; // test axes L = A0, L = A1, L = A2 - for ( var i = 0; i < 3; i ++ ) { + for ( let i = 0; i < 3; i ++ ) { ra = a.e[ i ]; rb = b.e[ 0 ] * AbsR[ i ][ 0 ] + b.e[ 1 ] * AbsR[ i ][ 1 ] + b.e[ 2 ] * AbsR[ i ][ 2 ]; @@ -214,7 +214,7 @@ Object.assign( OBB.prototype, { // test axes L = B0, L = B1, L = B2 - for ( var i = 0; i < 3; i ++ ) { + for ( let i = 0; i < 3; i ++ ) { ra = a.e[ 0 ] * AbsR[ 0 ][ i ] + a.e[ 1 ] * AbsR[ 1 ][ i ] + a.e[ 2 ] * AbsR[ 2 ][ i ]; rb = b.e[ i ]; @@ -280,13 +280,13 @@ Object.assign( OBB.prototype, { return true; - }, + } /** * Reference: Testing Box Against Plane in Real-Time Collision Detection * by Christer Ericson (chapter 5.2.3) */ - intersectsPlane: function ( plane ) { + intersectsPlane( plane ) { this.rotation.extractBasis( xAxis, yAxis, zAxis ); @@ -304,13 +304,13 @@ Object.assign( OBB.prototype, { return Math.abs( d ) <= r; - }, + } /** * Performs a ray/OBB intersection test and stores the intersection point * to the given 3D vector. If no intersection is detected, *null* is returned. */ - intersectRay: function ( ray, result ) { + intersectRay( ray, result ) { // the idea is to perform the intersection test in the local space // of the OBB. @@ -320,7 +320,7 @@ Object.assign( OBB.prototype, { // create a 4x4 transformation matrix - matrix4FromRotationMatrix( matrix, this.rotation ); + matrix.setFromMatrix3( this.rotation ); matrix.setPosition( this.center ); // transform ray to the local space of the OBB @@ -342,19 +342,19 @@ Object.assign( OBB.prototype, { } - }, + } /** * Performs a ray/OBB intersection test. Returns either true or false if * there is a intersection or not. */ - intersectsRay: function ( ray ) { + intersectsRay( ray ) { return this.intersectRay( ray, v1 ) !== null; - }, + } - fromBox3: function ( box3 ) { + fromBox3( box3 ) { box3.getCenter( this.center ); @@ -364,32 +364,32 @@ Object.assign( OBB.prototype, { return this; - }, + } - equals: function ( obb ) { + equals( obb ) { return obb.center.equals( this.center ) && obb.halfSize.equals( this.halfSize ) && obb.rotation.equals( this.rotation ); - }, + } - applyMatrix4: function ( matrix ) { + applyMatrix4( matrix ) { - var e = matrix.elements; + const e = matrix.elements; - var sx = v1.set( e[ 0 ], e[ 1 ], e[ 2 ] ).length(); - var sy = v1.set( e[ 4 ], e[ 5 ], e[ 6 ] ).length(); - var sz = v1.set( e[ 8 ], e[ 9 ], e[ 10 ] ).length(); + let sx = v1.set( e[ 0 ], e[ 1 ], e[ 2 ] ).length(); + const sy = v1.set( e[ 4 ], e[ 5 ], e[ 6 ] ).length(); + const sz = v1.set( e[ 8 ], e[ 9 ], e[ 10 ] ).length(); - var det = matrix.determinant(); + const det = matrix.determinant(); if ( det < 0 ) sx = - sx; rotationMatrix.setFromMatrix4( matrix ); - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; rotationMatrix.elements[ 0 ] *= invSX; rotationMatrix.elements[ 1 ] *= invSX; @@ -416,35 +416,8 @@ Object.assign( OBB.prototype, { } -} ); - -function matrix4FromRotationMatrix( matrix4, matrix3 ) { - - var e = matrix4.elements; - var me = matrix3.elements; - - e[ 0 ] = me[ 0 ]; - e[ 1 ] = me[ 1 ]; - e[ 2 ] = me[ 2 ]; - e[ 3 ] = 0; - - e[ 4 ] = me[ 3 ]; - e[ 5 ] = me[ 4 ]; - e[ 6 ] = me[ 5 ]; - e[ 7 ] = 0; - - e[ 8 ] = me[ 6 ]; - e[ 9 ] = me[ 7 ]; - e[ 10 ] = me[ 8 ]; - e[ 11 ] = 0; - - e[ 12 ] = 0; - e[ 13 ] = 0; - e[ 14 ] = 0; - e[ 15 ] = 1; - } -var obb = new OBB(); +const obb = new OBB(); export { OBB }; diff --git a/examples/jsm/math/Octree.js b/examples/jsm/math/Octree.js index f418df6686b729..47140546ad2193 100644 --- a/examples/jsm/math/Octree.js +++ b/examples/jsm/math/Octree.js @@ -9,17 +9,18 @@ import { import { Capsule } from '../math/Capsule.js'; -var Octree = ( function () { +const _v1 = new Vector3(); +const _v2 = new Vector3(); +const _plane = new Plane(); +const _line1 = new Line3(); +const _line2 = new Line3(); +const _sphere = new Sphere(); +const _capsule = new Capsule(); - var _v1 = new Vector3(); - var _v2 = new Vector3(); - var _plane = new Plane(); - var _line1 = new Line3(); - var _line2 = new Line3(); - var _sphere = new Sphere(); - var _capsule = new Capsule(); +class Octree { - function Octree( box ) { + + constructor( box ) { this.triangles = []; this.box = box; @@ -27,443 +28,437 @@ var Octree = ( function () { } - Object.assign( Octree.prototype, { - - addTriangle: function ( triangle ) { - - if ( ! this.bounds ) this.bounds = new Box3(); + addTriangle( triangle ) { - this.bounds.min.x = Math.min( this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x ); - this.bounds.min.y = Math.min( this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y ); - this.bounds.min.z = Math.min( this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z ); - this.bounds.max.x = Math.max( this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x ); - this.bounds.max.y = Math.max( this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y ); - this.bounds.max.z = Math.max( this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z ); + if ( ! this.bounds ) this.bounds = new Box3(); - this.triangles.push( triangle ); + this.bounds.min.x = Math.min( this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x ); + this.bounds.min.y = Math.min( this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y ); + this.bounds.min.z = Math.min( this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z ); + this.bounds.max.x = Math.max( this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x ); + this.bounds.max.y = Math.max( this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y ); + this.bounds.max.z = Math.max( this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z ); - return this; + this.triangles.push( triangle ); - }, + return this; - calcBox: function () { + } - this.box = this.bounds.clone(); + calcBox() { - // offset small ammount to account for regular grid - this.box.min.x -= 0.01; - this.box.min.y -= 0.01; - this.box.min.z -= 0.01; + this.box = this.bounds.clone(); - return this; + // offset small ammount to account for regular grid + this.box.min.x -= 0.01; + this.box.min.y -= 0.01; + this.box.min.z -= 0.01; - }, + return this; - split: function ( level ) { + } - if ( ! this.box ) return; + split( level ) { - var subTrees = [], - halfsize = _v2.copy( this.box.max ).sub( this.box.min ).multiplyScalar( 0.5 ), - box, v, triangle; + if ( ! this.box ) return; - for ( var x = 0; x < 2; x ++ ) { + const subTrees = []; + const halfsize = _v2.copy( this.box.max ).sub( this.box.min ).multiplyScalar( 0.5 ); - for ( var y = 0; y < 2; y ++ ) { + for ( let x = 0; x < 2; x ++ ) { - for ( var z = 0; z < 2; z ++ ) { + for ( let y = 0; y < 2; y ++ ) { - box = new Box3(); - v = _v1.set( x, y, z ); + for ( let z = 0; z < 2; z ++ ) { - box.min.copy( this.box.min ).add( v.multiply( halfsize ) ); - box.max.copy( box.min ).add( halfsize ); + const box = new Box3(); + const v = _v1.set( x, y, z ); - subTrees.push( new Octree( box ) ); + box.min.copy( this.box.min ).add( v.multiply( halfsize ) ); + box.max.copy( box.min ).add( halfsize ); - } + subTrees.push( new Octree( box ) ); } } - while ( triangle = this.triangles.pop() ) { + } + + let triangle; - for ( var i = 0; i < subTrees.length; i ++ ) { + while ( triangle = this.triangles.pop() ) { - if ( subTrees[ i ].box.intersectsTriangle( triangle ) ) { + for ( let i = 0; i < subTrees.length; i ++ ) { - subTrees[ i ].triangles.push( triangle ); + if ( subTrees[ i ].box.intersectsTriangle( triangle ) ) { - } + subTrees[ i ].triangles.push( triangle ); } } - for ( var i = 0; i < subTrees.length; i ++ ) { + } - var len = subTrees[ i ].triangles.length; + for ( let i = 0; i < subTrees.length; i ++ ) { - if ( len > 8 && level < 16 ) { + const len = subTrees[ i ].triangles.length; - subTrees[ i ].split( level + 1 ); + if ( len > 8 && level < 16 ) { - } + subTrees[ i ].split( level + 1 ); - if ( len != 0 ) { + } - this.subTrees.push( subTrees[ i ] ); + if ( len !== 0 ) { - } + this.subTrees.push( subTrees[ i ] ); } - return this; + } - }, + return this; - build: function () { + } - this.calcBox(); - this.split( 0 ); + build() { - return this; + this.calcBox(); + this.split( 0 ); - }, + return this; - getRayTriangles: function ( ray, triangles ) { + } - for ( var i = 0; i < this.subTrees.length; i ++ ) { + getRayTriangles( ray, triangles ) { - var subTree = this.subTrees[ i ]; - if ( ! ray.intersectsBox( subTree.box ) ) continue; + for ( let i = 0; i < this.subTrees.length; i ++ ) { - if ( subTree.triangles.length > 0 ) { + const subTree = this.subTrees[ i ]; + if ( ! ray.intersectsBox( subTree.box ) ) continue; - for ( var j = 0; j < subTree.triangles.length; j ++ ) { + if ( subTree.triangles.length > 0 ) { - if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] ); + for ( let j = 0; j < subTree.triangles.length; j ++ ) { - } + if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] ); - } else { + } - subTree.getRayTriangles( ray, triangles ); + } else { - } + subTree.getRayTriangles( ray, triangles ); } - return triangles; - - }, + } - triangleCapsuleIntersect: function ( capsule, triangle ) { + return triangles; - var point1, point2, line1, line2; + } - triangle.getPlane( _plane ); + triangleCapsuleIntersect( capsule, triangle ) { - var d1 = _plane.distanceToPoint( capsule.start ) - capsule.radius; - var d2 = _plane.distanceToPoint( capsule.end ) - capsule.radius; + triangle.getPlane( _plane ); - if ( ( d1 > 0 && d2 > 0 ) || ( d1 < - capsule.radius && d2 < - capsule.radius ) ) { + const d1 = _plane.distanceToPoint( capsule.start ) - capsule.radius; + const d2 = _plane.distanceToPoint( capsule.end ) - capsule.radius; - return false; + if ( ( d1 > 0 && d2 > 0 ) || ( d1 < - capsule.radius && d2 < - capsule.radius ) ) { - } + return false; - var delta = Math.abs( d1 / ( Math.abs( d1 ) + Math.abs( d2 ) ) ); - var intersectPoint = _v1.copy( capsule.start ).lerp( capsule.end, delta ); + } - if ( triangle.containsPoint( intersectPoint ) ) { + const delta = Math.abs( d1 / ( Math.abs( d1 ) + Math.abs( d2 ) ) ); + const intersectPoint = _v1.copy( capsule.start ).lerp( capsule.end, delta ); - return { normal: _plane.normal.clone(), point: intersectPoint.clone(), depth: Math.abs( Math.min( d1, d2 ) ) }; + if ( triangle.containsPoint( intersectPoint ) ) { - } + return { normal: _plane.normal.clone(), point: intersectPoint.clone(), depth: Math.abs( Math.min( d1, d2 ) ) }; - var r2 = capsule.radius * capsule.radius; + } - line1 = _line1.set( capsule.start, capsule.end ); + const r2 = capsule.radius * capsule.radius; - var lines = [ - [ triangle.a, triangle.b ], - [ triangle.b, triangle.c ], - [ triangle.c, triangle.a ] - ]; + const line1 = _line1.set( capsule.start, capsule.end ); - for ( var i = 0; i < lines.length; i ++ ) { + const lines = [ + [ triangle.a, triangle.b ], + [ triangle.b, triangle.c ], + [ triangle.c, triangle.a ] + ]; - line2 = _line2.set( lines[ i ][ 0 ], lines[ i ][ 1 ] ); + for ( let i = 0; i < lines.length; i ++ ) { - [ point1, point2 ] = capsule.lineLineMinimumPoints( line1, line2 ); + const line2 = _line2.set( lines[ i ][ 0 ], lines[ i ][ 1 ] ); - if ( point1.distanceToSquared( point2 ) < r2 ) { + const [ point1, point2 ] = capsule.lineLineMinimumPoints( line1, line2 ); - return { normal: point1.clone().sub( point2 ).normalize(), point: point2.clone(), depth: capsule.radius - point1.distanceTo( point2 ) }; + if ( point1.distanceToSquared( point2 ) < r2 ) { - } + return { normal: point1.clone().sub( point2 ).normalize(), point: point2.clone(), depth: capsule.radius - point1.distanceTo( point2 ) }; } - return false; + } - }, + return false; - triangleSphereIntersect: function ( sphere, triangle ) { + } - triangle.getPlane( _plane ); + triangleSphereIntersect( sphere, triangle ) { - if ( ! sphere.intersectsPlane( _plane ) ) return false; + triangle.getPlane( _plane ); - var depth = Math.abs( _plane.distanceToSphere( sphere ) ); - var r2 = sphere.radius * sphere.radius - depth * depth; + if ( ! sphere.intersectsPlane( _plane ) ) return false; - var plainPoint = _plane.projectPoint( sphere.center, _v1 ); + const depth = Math.abs( _plane.distanceToSphere( sphere ) ); + const r2 = sphere.radius * sphere.radius - depth * depth; - if ( triangle.containsPoint( sphere.center ) ) { + const plainPoint = _plane.projectPoint( sphere.center, _v1 ); - return { normal: _plane.normal.clone(), point: plainPoint.clone(), depth: Math.abs( _plane.distanceToSphere( sphere ) ) }; + if ( triangle.containsPoint( sphere.center ) ) { - } + return { normal: _plane.normal.clone(), point: plainPoint.clone(), depth: Math.abs( _plane.distanceToSphere( sphere ) ) }; - var lines = [ - [ triangle.a, triangle.b ], - [ triangle.b, triangle.c ], - [ triangle.c, triangle.a ] - ]; + } - for ( var i = 0; i < lines.length; i ++ ) { + const lines = [ + [ triangle.a, triangle.b ], + [ triangle.b, triangle.c ], + [ triangle.c, triangle.a ] + ]; - _line1.set( lines[ i ][ 0 ], lines[ i ][ 1 ] ); - _line1.closestPointToPoint( plainPoint, true, _v2 ); + for ( let i = 0; i < lines.length; i ++ ) { - var d = _v2.distanceToSquared( sphere.center ); + _line1.set( lines[ i ][ 0 ], lines[ i ][ 1 ] ); + _line1.closestPointToPoint( plainPoint, true, _v2 ); - if ( d < r2 ) { + const d = _v2.distanceToSquared( sphere.center ); - return { normal: sphere.center.clone().sub( _v2 ).normalize(), point: _v2.clone(), depth: sphere.radius - Math.sqrt( d ) }; + if ( d < r2 ) { - } + return { normal: sphere.center.clone().sub( _v2 ).normalize(), point: _v2.clone(), depth: sphere.radius - Math.sqrt( d ) }; } - return false; + } - }, + return false; - getSphereTriangles: function ( sphere, triangles ) { + } - for ( var i = 0; i < this.subTrees.length; i ++ ) { + getSphereTriangles( sphere, triangles ) { - var subTree = this.subTrees[ i ]; + for ( let i = 0; i < this.subTrees.length; i ++ ) { - if ( ! sphere.intersectsBox( subTree.box ) ) continue; + const subTree = this.subTrees[ i ]; - if ( subTree.triangles.length > 0 ) { + if ( ! sphere.intersectsBox( subTree.box ) ) continue; - for ( var j = 0; j < subTree.triangles.length; j ++ ) { + if ( subTree.triangles.length > 0 ) { - if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] ); + for ( let j = 0; j < subTree.triangles.length; j ++ ) { - } + if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] ); - } else { + } - subTree.getSphereTriangles( sphere, triangles ); + } else { - } + subTree.getSphereTriangles( sphere, triangles ); } - }, + } - getCapsuleTriangles: function ( capsule, triangles ) { + } - for ( var i = 0; i < this.subTrees.length; i ++ ) { + getCapsuleTriangles( capsule, triangles ) { - var subTree = this.subTrees[ i ]; + for ( let i = 0; i < this.subTrees.length; i ++ ) { - if ( ! capsule.intersectsBox( subTree.box ) ) continue; + const subTree = this.subTrees[ i ]; - if ( subTree.triangles.length > 0 ) { + if ( ! capsule.intersectsBox( subTree.box ) ) continue; - for ( var j = 0; j < subTree.triangles.length; j ++ ) { + if ( subTree.triangles.length > 0 ) { - if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] ); + for ( let j = 0; j < subTree.triangles.length; j ++ ) { - } + if ( triangles.indexOf( subTree.triangles[ j ] ) === - 1 ) triangles.push( subTree.triangles[ j ] ); - } else { + } - subTree.getCapsuleTriangles( capsule, triangles ); + } else { - } + subTree.getCapsuleTriangles( capsule, triangles ); } - }, + } - sphereIntersect( sphere ) { + } - _sphere.copy( sphere ); + sphereIntersect( sphere ) { - var triangles = [], result, hit = false; + _sphere.copy( sphere ); - this.getSphereTriangles( sphere, triangles ); + const triangles = []; + let result, hit = false; - for ( var i = 0; i < triangles.length; i ++ ) { + this.getSphereTriangles( sphere, triangles ); - if ( result = this.triangleSphereIntersect( _sphere, triangles[ i ] ) ) { + for ( let i = 0; i < triangles.length; i ++ ) { - hit = true; + if ( result = this.triangleSphereIntersect( _sphere, triangles[ i ] ) ) { - _sphere.center.add( result.normal.multiplyScalar( result.depth ) ); + hit = true; - } + _sphere.center.add( result.normal.multiplyScalar( result.depth ) ); } - if ( hit ) { + } - var collisionVector = _sphere.center.clone().sub( sphere.center ); - var depth = collisionVector.length(); + if ( hit ) { - return { normal: collisionVector.normalize(), depth: depth }; + const collisionVector = _sphere.center.clone().sub( sphere.center ); + const depth = collisionVector.length(); - } + return { normal: collisionVector.normalize(), depth: depth }; - return false; + } - }, + return false; - capsuleIntersect: function ( capsule ) { + } - _capsule.copy( capsule ); + capsuleIntersect( capsule ) { - var triangles = [], result, hit = false; + _capsule.copy( capsule ); - this.getCapsuleTriangles( _capsule, triangles ); + const triangles = []; + let result, hit = false; - for ( var i = 0; i < triangles.length; i ++ ) { + this.getCapsuleTriangles( _capsule, triangles ); - if ( result = this.triangleCapsuleIntersect( _capsule, triangles[ i ] ) ) { + for ( let i = 0; i < triangles.length; i ++ ) { - hit = true; + if ( result = this.triangleCapsuleIntersect( _capsule, triangles[ i ] ) ) { - _capsule.translate( result.normal.multiplyScalar( result.depth ) ); + hit = true; - } + _capsule.translate( result.normal.multiplyScalar( result.depth ) ); } - if ( hit ) { + } - var collisionVector = _capsule.getCenter( new Vector3() ).sub( capsule.getCenter( _v1 ) ); - var depth = collisionVector.length(); + if ( hit ) { - return { normal: collisionVector.normalize(), depth: depth }; + const collisionVector = _capsule.getCenter( new Vector3() ).sub( capsule.getCenter( _v1 ) ); + const depth = collisionVector.length(); - } + return { normal: collisionVector.normalize(), depth: depth }; - return false; + } - }, + return false; - rayIntersect: function ( ray ) { + } - if ( ray.direction.length() === 0 ) return; + rayIntersect( ray ) { - var triangles = [], triangle, position, - distance = 1e100, - result; + if ( ray.direction.length() === 0 ) return; - this.getRayTriangles( ray, triangles ); + const triangles = []; + let triangle, position, distance = 1e100; - for ( var i = 0; i < triangles.length; i ++ ) { + this.getRayTriangles( ray, triangles ); - result = ray.intersectTriangle( triangles[ i ].a, triangles[ i ].b, triangles[ i ].c, true, _v1 ); + for ( let i = 0; i < triangles.length; i ++ ) { - if ( result ) { + const result = ray.intersectTriangle( triangles[ i ].a, triangles[ i ].b, triangles[ i ].c, true, _v1 ); - var newdistance = result.sub( ray.origin ).length(); + if ( result ) { - if ( distance > newdistance ) { + const newdistance = result.sub( ray.origin ).length(); - position = result.clone().add( ray.origin ); - distance = newdistance; - triangle = triangles[ i ]; + if ( distance > newdistance ) { - } + position = result.clone().add( ray.origin ); + distance = newdistance; + triangle = triangles[ i ]; } } - return distance < 1e100 ? { distance: distance, triangle: triangle, position: position } : false; + } - }, + return distance < 1e100 ? { distance: distance, triangle: triangle, position: position } : false; - fromGraphNode: function ( group ) { + } - group.traverse( ( obj ) => { + fromGraphNode( group ) { - if ( obj.type === 'Mesh' ) { + group.traverse( ( obj ) => { - obj.updateMatrix(); - obj.updateWorldMatrix(); + if ( obj.type === 'Mesh' ) { - var geometry, isTemp = false; + obj.updateMatrix(); + obj.updateWorldMatrix(); - if ( obj.geometry.index ) { + let geometry, isTemp = false; - isTemp = true; - geometry = obj.geometry.clone().toNonIndexed(); + if ( obj.geometry.index ) { - } else { + isTemp = true; + geometry = obj.geometry.clone().toNonIndexed(); - geometry = obj.geometry; + } else { - } + geometry = obj.geometry; - var positions = geometry.attributes.position.array; - var transform = obj.matrixWorld; + } - for ( var i = 0; i < positions.length; i += 9 ) { + const positions = geometry.attributes.position.array; + const transform = obj.matrixWorld; - var v1 = new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ); - var v2 = new Vector3( positions[ i + 3 ], positions[ i + 4 ], positions[ i + 5 ] ); - var v3 = new Vector3( positions[ i + 6 ], positions[ i + 7 ], positions[ i + 8 ] ); + for ( let i = 0; i < positions.length; i += 9 ) { - v1.applyMatrix4( transform ); - v2.applyMatrix4( transform ); - v3.applyMatrix4( transform ); + const v1 = new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ); + const v2 = new Vector3( positions[ i + 3 ], positions[ i + 4 ], positions[ i + 5 ] ); + const v3 = new Vector3( positions[ i + 6 ], positions[ i + 7 ], positions[ i + 8 ] ); - this.addTriangle( new Triangle( v1, v2, v3 ) ); + v1.applyMatrix4( transform ); + v2.applyMatrix4( transform ); + v3.applyMatrix4( transform ); - } + this.addTriangle( new Triangle( v1, v2, v3 ) ); - if ( isTemp ) { + } - geometry.dispose(); + if ( isTemp ) { - } + geometry.dispose(); } - } ); - - this.build(); + } - return this; + } ); - } + this.build(); - } ); + return this; - return Octree; + } -} )(); +} export { Octree }; diff --git a/examples/jsm/math/SimplexNoise.js b/examples/jsm/math/SimplexNoise.js index e0c615ef545475..8ba26942ce9051 100644 --- a/examples/jsm/math/SimplexNoise.js +++ b/examples/jsm/math/SimplexNoise.js @@ -10,415 +10,435 @@ * You can pass in a random number generator object if you like. * It is assumed to have a random() method. */ -var SimplexNoise = function ( r ) { +class SimplexNoise { - if ( r == undefined ) r = Math; - this.grad3 = [[ 1, 1, 0 ], [ - 1, 1, 0 ], [ 1, - 1, 0 ], [ - 1, - 1, 0 ], - [ 1, 0, 1 ], [ - 1, 0, 1 ], [ 1, 0, - 1 ], [ - 1, 0, - 1 ], - [ 0, 1, 1 ], [ 0, - 1, 1 ], [ 0, 1, - 1 ], [ 0, - 1, - 1 ]]; + constructor( r = Math ) { - this.grad4 = [[ 0, 1, 1, 1 ], [ 0, 1, 1, - 1 ], [ 0, 1, - 1, 1 ], [ 0, 1, - 1, - 1 ], - [ 0, - 1, 1, 1 ], [ 0, - 1, 1, - 1 ], [ 0, - 1, - 1, 1 ], [ 0, - 1, - 1, - 1 ], - [ 1, 0, 1, 1 ], [ 1, 0, 1, - 1 ], [ 1, 0, - 1, 1 ], [ 1, 0, - 1, - 1 ], - [ - 1, 0, 1, 1 ], [ - 1, 0, 1, - 1 ], [ - 1, 0, - 1, 1 ], [ - 1, 0, - 1, - 1 ], - [ 1, 1, 0, 1 ], [ 1, 1, 0, - 1 ], [ 1, - 1, 0, 1 ], [ 1, - 1, 0, - 1 ], - [ - 1, 1, 0, 1 ], [ - 1, 1, 0, - 1 ], [ - 1, - 1, 0, 1 ], [ - 1, - 1, 0, - 1 ], - [ 1, 1, 1, 0 ], [ 1, 1, - 1, 0 ], [ 1, - 1, 1, 0 ], [ 1, - 1, - 1, 0 ], - [ - 1, 1, 1, 0 ], [ - 1, 1, - 1, 0 ], [ - 1, - 1, 1, 0 ], [ - 1, - 1, - 1, 0 ]]; + this.grad3 = [[ 1, 1, 0 ], [ - 1, 1, 0 ], [ 1, - 1, 0 ], [ - 1, - 1, 0 ], + [ 1, 0, 1 ], [ - 1, 0, 1 ], [ 1, 0, - 1 ], [ - 1, 0, - 1 ], + [ 0, 1, 1 ], [ 0, - 1, 1 ], [ 0, 1, - 1 ], [ 0, - 1, - 1 ]]; - this.p = []; + this.grad4 = [[ 0, 1, 1, 1 ], [ 0, 1, 1, - 1 ], [ 0, 1, - 1, 1 ], [ 0, 1, - 1, - 1 ], + [ 0, - 1, 1, 1 ], [ 0, - 1, 1, - 1 ], [ 0, - 1, - 1, 1 ], [ 0, - 1, - 1, - 1 ], + [ 1, 0, 1, 1 ], [ 1, 0, 1, - 1 ], [ 1, 0, - 1, 1 ], [ 1, 0, - 1, - 1 ], + [ - 1, 0, 1, 1 ], [ - 1, 0, 1, - 1 ], [ - 1, 0, - 1, 1 ], [ - 1, 0, - 1, - 1 ], + [ 1, 1, 0, 1 ], [ 1, 1, 0, - 1 ], [ 1, - 1, 0, 1 ], [ 1, - 1, 0, - 1 ], + [ - 1, 1, 0, 1 ], [ - 1, 1, 0, - 1 ], [ - 1, - 1, 0, 1 ], [ - 1, - 1, 0, - 1 ], + [ 1, 1, 1, 0 ], [ 1, 1, - 1, 0 ], [ 1, - 1, 1, 0 ], [ 1, - 1, - 1, 0 ], + [ - 1, 1, 1, 0 ], [ - 1, 1, - 1, 0 ], [ - 1, - 1, 1, 0 ], [ - 1, - 1, - 1, 0 ]]; - for ( var i = 0; i < 256; i ++ ) { + this.p = []; - this.p[ i ] = Math.floor( r.random() * 256 ); + for ( let i = 0; i < 256; i ++ ) { - } - - // To remove the need for index wrapping, double the permutation table length - this.perm = []; - - for ( var i = 0; i < 512; i ++ ) { + this.p[ i ] = Math.floor( r.random() * 256 ); - this.perm[ i ] = this.p[ i & 255 ]; + } - } - - // A lookup table to traverse the simplex around a given point in 4D. - // Details can be found where this table is used, in the 4D noise method. - this.simplex = [ - [ 0, 1, 2, 3 ], [ 0, 1, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 2, 3, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 2, 3, 0 ], - [ 0, 2, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 3, 1, 2 ], [ 0, 3, 2, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 3, 2, 0 ], - [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], - [ 1, 2, 0, 3 ], [ 0, 0, 0, 0 ], [ 1, 3, 0, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 3, 0, 1 ], [ 2, 3, 1, 0 ], - [ 1, 0, 2, 3 ], [ 1, 0, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 0, 3, 1 ], [ 0, 0, 0, 0 ], [ 2, 1, 3, 0 ], - [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], - [ 2, 0, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 0, 1, 2 ], [ 3, 0, 2, 1 ], [ 0, 0, 0, 0 ], [ 3, 1, 2, 0 ], - [ 2, 1, 0, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 1, 0, 2 ], [ 0, 0, 0, 0 ], [ 3, 2, 0, 1 ], [ 3, 2, 1, 0 ]]; + // To remove the need for index wrapping, double the permutation table length + this.perm = []; -}; + for ( let i = 0; i < 512; i ++ ) { -SimplexNoise.prototype.dot = function ( g, x, y ) { + this.perm[ i ] = this.p[ i & 255 ]; - return g[ 0 ] * x + g[ 1 ] * y; + } -}; + // A lookup table to traverse the simplex around a given point in 4D. + // Details can be found where this table is used, in the 4D noise method. + this.simplex = [ + [ 0, 1, 2, 3 ], [ 0, 1, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 2, 3, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 2, 3, 0 ], + [ 0, 2, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 3, 1, 2 ], [ 0, 3, 2, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 3, 2, 0 ], + [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], + [ 1, 2, 0, 3 ], [ 0, 0, 0, 0 ], [ 1, 3, 0, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 3, 0, 1 ], [ 2, 3, 1, 0 ], + [ 1, 0, 2, 3 ], [ 1, 0, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 0, 3, 1 ], [ 0, 0, 0, 0 ], [ 2, 1, 3, 0 ], + [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], + [ 2, 0, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 0, 1, 2 ], [ 3, 0, 2, 1 ], [ 0, 0, 0, 0 ], [ 3, 1, 2, 0 ], + [ 2, 1, 0, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 1, 0, 2 ], [ 0, 0, 0, 0 ], [ 3, 2, 0, 1 ], [ 3, 2, 1, 0 ]]; -SimplexNoise.prototype.dot3 = function ( g, x, y, z ) { + } - return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z; + dot( g, x, y ) { -}; + return g[ 0 ] * x + g[ 1 ] * y; -SimplexNoise.prototype.dot4 = function ( g, x, y, z, w ) { + } - return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z + g[ 3 ] * w; + dot3( g, x, y, z ) { -}; + return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z; -SimplexNoise.prototype.noise = function ( xin, yin ) { + } - var n0, n1, n2; // Noise contributions from the three corners - // Skew the input space to determine which simplex cell we're in - var F2 = 0.5 * ( Math.sqrt( 3.0 ) - 1.0 ); - var s = ( xin + yin ) * F2; // Hairy factor for 2D - var i = Math.floor( xin + s ); - var j = Math.floor( yin + s ); - var G2 = ( 3.0 - Math.sqrt( 3.0 ) ) / 6.0; - var t = ( i + j ) * G2; - var X0 = i - t; // Unskew the cell origin back to (x,y) space - var Y0 = j - t; - var x0 = xin - X0; // The x,y distances from the cell origin - var y0 = yin - Y0; - // For the 2D case, the simplex shape is an equilateral triangle. - // Determine which simplex we are in. - var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords - if ( x0 > y0 ) { + dot4( g, x, y, z, w ) { - i1 = 1; j1 = 0; + return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z + g[ 3 ] * w; - // lower triangle, XY order: (0,0)->(1,0)->(1,1) + } - } else { + noise( xin, yin ) { - i1 = 0; j1 = 1; + let n0; // Noise contributions from the three corners + let n1; + let n2; + // Skew the input space to determine which simplex cell we're in + const F2 = 0.5 * ( Math.sqrt( 3.0 ) - 1.0 ); + const s = ( xin + yin ) * F2; // Hairy factor for 2D + const i = Math.floor( xin + s ); + const j = Math.floor( yin + s ); + const G2 = ( 3.0 - Math.sqrt( 3.0 ) ) / 6.0; + const t = ( i + j ) * G2; + const X0 = i - t; // Unskew the cell origin back to (x,y) space + const Y0 = j - t; + const x0 = xin - X0; // The x,y distances from the cell origin + const y0 = yin - Y0; - } // upper triangle, YX order: (0,0)->(0,1)->(1,1) + // For the 2D case, the simplex shape is an equilateral triangle. + // Determine which simplex we are in. + let i1; // Offsets for second (middle) corner of simplex in (i,j) coords - // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and - // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where - // c = (3-sqrt(3))/6 - var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords - var y1 = y0 - j1 + G2; - var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords - var y2 = y0 - 1.0 + 2.0 * G2; - // Work out the hashed gradient indices of the three simplex corners - var ii = i & 255; - var jj = j & 255; - var gi0 = this.perm[ ii + this.perm[ jj ] ] % 12; - var gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 ] ] % 12; - var gi2 = this.perm[ ii + 1 + this.perm[ jj + 1 ] ] % 12; - // Calculate the contribution from the three corners - var t0 = 0.5 - x0 * x0 - y0 * y0; - if ( t0 < 0 ) n0 = 0.0; - else { + let j1; + if ( x0 > y0 ) { - t0 *= t0; - n0 = t0 * t0 * this.dot( this.grad3[ gi0 ], x0, y0 ); // (x,y) of grad3 used for 2D gradient + i1 = 1; j1 = 0; - } + // lower triangle, XY order: (0,0)->(1,0)->(1,1) - var t1 = 0.5 - x1 * x1 - y1 * y1; - if ( t1 < 0 ) n1 = 0.0; - else { + } else { - t1 *= t1; - n1 = t1 * t1 * this.dot( this.grad3[ gi1 ], x1, y1 ); + i1 = 0; j1 = 1; - } + } // upper triangle, YX order: (0,0)->(0,1)->(1,1) - var t2 = 0.5 - x2 * x2 - y2 * y2; - if ( t2 < 0 ) n2 = 0.0; - else { + // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and + // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where + // c = (3-sqrt(3))/6 + const x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords + const y1 = y0 - j1 + G2; + const x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords + const y2 = y0 - 1.0 + 2.0 * G2; + // Work out the hashed gradient indices of the three simplex corners + const ii = i & 255; + const jj = j & 255; + const gi0 = this.perm[ ii + this.perm[ jj ] ] % 12; + const gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 ] ] % 12; + const gi2 = this.perm[ ii + 1 + this.perm[ jj + 1 ] ] % 12; + // Calculate the contribution from the three corners + let t0 = 0.5 - x0 * x0 - y0 * y0; + if ( t0 < 0 ) n0 = 0.0; + else { - t2 *= t2; - n2 = t2 * t2 * this.dot( this.grad3[ gi2 ], x2, y2 ); + t0 *= t0; + n0 = t0 * t0 * this.dot( this.grad3[ gi0 ], x0, y0 ); // (x,y) of grad3 used for 2D gradient - } + } - // Add contributions from each corner to get the final noise value. - // The result is scaled to return values in the interval [-1,1]. - return 70.0 * ( n0 + n1 + n2 ); + let t1 = 0.5 - x1 * x1 - y1 * y1; + if ( t1 < 0 ) n1 = 0.0; + else { -}; + t1 *= t1; + n1 = t1 * t1 * this.dot( this.grad3[ gi1 ], x1, y1 ); -// 3D simplex noise -SimplexNoise.prototype.noise3d = function ( xin, yin, zin ) { + } - var n0, n1, n2, n3; // Noise contributions from the four corners - // Skew the input space to determine which simplex cell we're in - var F3 = 1.0 / 3.0; - var s = ( xin + yin + zin ) * F3; // Very nice and simple skew factor for 3D - var i = Math.floor( xin + s ); - var j = Math.floor( yin + s ); - var k = Math.floor( zin + s ); - var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too - var t = ( i + j + k ) * G3; - var X0 = i - t; // Unskew the cell origin back to (x,y,z) space - var Y0 = j - t; - var Z0 = k - t; - var x0 = xin - X0; // The x,y,z distances from the cell origin - var y0 = yin - Y0; - var z0 = zin - Z0; - // For the 3D case, the simplex shape is a slightly irregular tetrahedron. - // Determine which simplex we are in. - var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords - var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords - if ( x0 >= y0 ) { + let t2 = 0.5 - x2 * x2 - y2 * y2; + if ( t2 < 0 ) n2 = 0.0; + else { - if ( y0 >= z0 ) { + t2 *= t2; + n2 = t2 * t2 * this.dot( this.grad3[ gi2 ], x2, y2 ); - i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; + } - // X Y Z order + // Add contributions from each corner to get the final noise value. + // The result is scaled to return values in the interval [-1,1]. + return 70.0 * ( n0 + n1 + n2 ); - } else if ( x0 >= z0 ) { + } - i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; + // 3D simplex noise + noise3d( xin, yin, zin ) { - // X Z Y order + let n0; // Noise contributions from the four corners + let n1; + let n2; + let n3; + // Skew the input space to determine which simplex cell we're in + const F3 = 1.0 / 3.0; + const s = ( xin + yin + zin ) * F3; // Very nice and simple skew factor for 3D + const i = Math.floor( xin + s ); + const j = Math.floor( yin + s ); + const k = Math.floor( zin + s ); + const G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too + const t = ( i + j + k ) * G3; + const X0 = i - t; // Unskew the cell origin back to (x,y,z) space + const Y0 = j - t; + const Z0 = k - t; + const x0 = xin - X0; // The x,y,z distances from the cell origin + const y0 = yin - Y0; + const z0 = zin - Z0; - } else { + // For the 3D case, the simplex shape is a slightly irregular tetrahedron. + // Determine which simplex we are in. + let i1; // Offsets for second corner of simplex in (i,j,k) coords - i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; + let j1; + let k1; + let i2; // Offsets for third corner of simplex in (i,j,k) coords + let j2; + let k2; + if ( x0 >= y0 ) { - } // Z X Y order + if ( y0 >= z0 ) { - } else { // x0= z0 ) { - // Z Y X order + i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; - } else if ( x0 < z0 ) { + // X Z Y order - i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; + } else { - // Y Z X order + i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; - } else { + } // Z X Y order - i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; + } else { // x0 y0 ) ? 32 : 0; - var c2 = ( x0 > z0 ) ? 16 : 0; - var c3 = ( y0 > z0 ) ? 8 : 0; - var c4 = ( x0 > w0 ) ? 4 : 0; - var c5 = ( y0 > w0 ) ? 2 : 0; - var c6 = ( z0 > w0 ) ? 1 : 0; - var c = c1 + c2 + c3 + c4 + c5 + c6; - var i1, j1, k1, l1; // The integer offsets for the second simplex corner - var i2, j2, k2, l2; // The integer offsets for the third simplex corner - var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner - // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. - // Many values of c will never occur, since e.g. x>y>z>w makes x= 3 ? 1 : 0; - j1 = simplex[ c ][ 1 ] >= 3 ? 1 : 0; - k1 = simplex[ c ][ 2 ] >= 3 ? 1 : 0; - l1 = simplex[ c ][ 3 ] >= 3 ? 1 : 0; - // The number 2 in the "simplex" array is at the second largest coordinate. - i2 = simplex[ c ][ 0 ] >= 2 ? 1 : 0; - j2 = simplex[ c ][ 1 ] >= 2 ? 1 : 0; k2 = simplex[ c ][ 2 ] >= 2 ? 1 : 0; - l2 = simplex[ c ][ 3 ] >= 2 ? 1 : 0; - // The number 1 in the "simplex" array is at the second smallest coordinate. - i3 = simplex[ c ][ 0 ] >= 1 ? 1 : 0; - j3 = simplex[ c ][ 1 ] >= 1 ? 1 : 0; - k3 = simplex[ c ][ 2 ] >= 1 ? 1 : 0; - l3 = simplex[ c ][ 3 ] >= 1 ? 1 : 0; - // The fifth corner has all coordinate offsets = 1, so no need to look that up. - var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords - var y1 = y0 - j1 + G4; - var z1 = z0 - k1 + G4; - var w1 = w0 - l1 + G4; - var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords - var y2 = y0 - j2 + 2.0 * G4; - var z2 = z0 - k2 + 2.0 * G4; - var w2 = w0 - l2 + 2.0 * G4; - var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords - var y3 = y0 - j3 + 3.0 * G4; - var z3 = z0 - k3 + 3.0 * G4; - var w3 = w0 - l3 + 3.0 * G4; - var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords - var y4 = y0 - 1.0 + 4.0 * G4; - var z4 = z0 - 1.0 + 4.0 * G4; - var w4 = w0 - 1.0 + 4.0 * G4; - // Work out the hashed gradient indices of the five simplex corners - var ii = i & 255; - var jj = j & 255; - var kk = k & 255; - var ll = l & 255; - var gi0 = perm[ ii + perm[ jj + perm[ kk + perm[ ll ] ] ] ] % 32; - var gi1 = perm[ ii + i1 + perm[ jj + j1 + perm[ kk + k1 + perm[ ll + l1 ] ] ] ] % 32; - var gi2 = perm[ ii + i2 + perm[ jj + j2 + perm[ kk + k2 + perm[ ll + l2 ] ] ] ] % 32; - var gi3 = perm[ ii + i3 + perm[ jj + j3 + perm[ kk + k3 + perm[ ll + l3 ] ] ] ] % 32; - var gi4 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 + perm[ ll + 1 ] ] ] ] % 32; - // Calculate the contribution from the five corners - var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; - if ( t0 < 0 ) n0 = 0.0; - else { - - t0 *= t0; - n0 = t0 * t0 * this.dot4( grad4[ gi0 ], x0, y0, z0, w0 ); + let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; + if ( t1 < 0 ) n1 = 0.0; + else { - } + t1 *= t1; + n1 = t1 * t1 * this.dot3( this.grad3[ gi1 ], x1, y1, z1 ); - var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; - if ( t1 < 0 ) n1 = 0.0; - else { + } - t1 *= t1; - n1 = t1 * t1 * this.dot4( grad4[ gi1 ], x1, y1, z1, w1 ); + let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; + if ( t2 < 0 ) n2 = 0.0; + else { - } + t2 *= t2; + n2 = t2 * t2 * this.dot3( this.grad3[ gi2 ], x2, y2, z2 ); - var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; - if ( t2 < 0 ) n2 = 0.0; - else { + } - t2 *= t2; - n2 = t2 * t2 * this.dot4( grad4[ gi2 ], x2, y2, z2, w2 ); + let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; + if ( t3 < 0 ) n3 = 0.0; + else { - } + t3 *= t3; + n3 = t3 * t3 * this.dot3( this.grad3[ gi3 ], x3, y3, z3 ); - var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; - if ( t3 < 0 ) n3 = 0.0; - else { + } - t3 *= t3; - n3 = t3 * t3 * this.dot4( grad4[ gi3 ], x3, y3, z3, w3 ); + // Add contributions from each corner to get the final noise value. + // The result is scaled to stay just inside [-1,1] + return 32.0 * ( n0 + n1 + n2 + n3 ); } - var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; - if ( t4 < 0 ) n4 = 0.0; - else { - - t4 *= t4; - n4 = t4 * t4 * this.dot4( grad4[ gi4 ], x4, y4, z4, w4 ); + // 4D simplex noise + noise4d( x, y, z, w ) { + + // For faster and easier lookups + const grad4 = this.grad4; + const simplex = this.simplex; + const perm = this.perm; + + // The skewing and unskewing factors are hairy again for the 4D case + const F4 = ( Math.sqrt( 5.0 ) - 1.0 ) / 4.0; + const G4 = ( 5.0 - Math.sqrt( 5.0 ) ) / 20.0; + let n0; // Noise contributions from the five corners + let n1; + let n2; + let n3; + let n4; + // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in + const s = ( x + y + z + w ) * F4; // Factor for 4D skewing + const i = Math.floor( x + s ); + const j = Math.floor( y + s ); + const k = Math.floor( z + s ); + const l = Math.floor( w + s ); + const t = ( i + j + k + l ) * G4; // Factor for 4D unskewing + const X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space + const Y0 = j - t; + const Z0 = k - t; + const W0 = l - t; + const x0 = x - X0; // The x,y,z,w distances from the cell origin + const y0 = y - Y0; + const z0 = z - Z0; + const w0 = w - W0; + + // For the 4D case, the simplex is a 4D shape I won't even try to describe. + // To find out which of the 24 possible simplices we're in, we need to + // determine the magnitude ordering of x0, y0, z0 and w0. + // The method below is a good way of finding the ordering of x,y,z,w and + // then find the correct traversal order for the simplex we’re in. + // First, six pair-wise comparisons are performed between each possible pair + // of the four coordinates, and the results are used to add up binary bits + // for an integer index. + const c1 = ( x0 > y0 ) ? 32 : 0; + const c2 = ( x0 > z0 ) ? 16 : 0; + const c3 = ( y0 > z0 ) ? 8 : 0; + const c4 = ( x0 > w0 ) ? 4 : 0; + const c5 = ( y0 > w0 ) ? 2 : 0; + const c6 = ( z0 > w0 ) ? 1 : 0; + const c = c1 + c2 + c3 + c4 + c5 + c6; + + // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. + // Many values of c will never occur, since e.g. x>y>z>w makes x= 3 ? 1 : 0; + const j1 = simplex[ c ][ 1 ] >= 3 ? 1 : 0; + const k1 = simplex[ c ][ 2 ] >= 3 ? 1 : 0; + const l1 = simplex[ c ][ 3 ] >= 3 ? 1 : 0; + // The number 2 in the "simplex" array is at the second largest coordinate. + const i2 = simplex[ c ][ 0 ] >= 2 ? 1 : 0; + const j2 = simplex[ c ][ 1 ] >= 2 ? 1 : 0; + const k2 = simplex[ c ][ 2 ] >= 2 ? 1 : 0; + const l2 = simplex[ c ][ 3 ] >= 2 ? 1 : 0; + // The number 1 in the "simplex" array is at the second smallest coordinate. + const i3 = simplex[ c ][ 0 ] >= 1 ? 1 : 0; + const j3 = simplex[ c ][ 1 ] >= 1 ? 1 : 0; + const k3 = simplex[ c ][ 2 ] >= 1 ? 1 : 0; + const l3 = simplex[ c ][ 3 ] >= 1 ? 1 : 0; + // The fifth corner has all coordinate offsets = 1, so no need to look that up. + const x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords + const y1 = y0 - j1 + G4; + const z1 = z0 - k1 + G4; + const w1 = w0 - l1 + G4; + const x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords + const y2 = y0 - j2 + 2.0 * G4; + const z2 = z0 - k2 + 2.0 * G4; + const w2 = w0 - l2 + 2.0 * G4; + const x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords + const y3 = y0 - j3 + 3.0 * G4; + const z3 = z0 - k3 + 3.0 * G4; + const w3 = w0 - l3 + 3.0 * G4; + const x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords + const y4 = y0 - 1.0 + 4.0 * G4; + const z4 = z0 - 1.0 + 4.0 * G4; + const w4 = w0 - 1.0 + 4.0 * G4; + // Work out the hashed gradient indices of the five simplex corners + const ii = i & 255; + const jj = j & 255; + const kk = k & 255; + const ll = l & 255; + const gi0 = perm[ ii + perm[ jj + perm[ kk + perm[ ll ] ] ] ] % 32; + const gi1 = perm[ ii + i1 + perm[ jj + j1 + perm[ kk + k1 + perm[ ll + l1 ] ] ] ] % 32; + const gi2 = perm[ ii + i2 + perm[ jj + j2 + perm[ kk + k2 + perm[ ll + l2 ] ] ] ] % 32; + const gi3 = perm[ ii + i3 + perm[ jj + j3 + perm[ kk + k3 + perm[ ll + l3 ] ] ] ] % 32; + const gi4 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 + perm[ ll + 1 ] ] ] ] % 32; + // Calculate the contribution from the five corners + let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; + if ( t0 < 0 ) n0 = 0.0; + else { + + t0 *= t0; + n0 = t0 * t0 * this.dot4( grad4[ gi0 ], x0, y0, z0, w0 ); + + } + + let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; + if ( t1 < 0 ) n1 = 0.0; + else { + + t1 *= t1; + n1 = t1 * t1 * this.dot4( grad4[ gi1 ], x1, y1, z1, w1 ); + + } + + let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; + if ( t2 < 0 ) n2 = 0.0; + else { + + t2 *= t2; + n2 = t2 * t2 * this.dot4( grad4[ gi2 ], x2, y2, z2, w2 ); + + } + + let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; + if ( t3 < 0 ) n3 = 0.0; + else { + + t3 *= t3; + n3 = t3 * t3 * this.dot4( grad4[ gi3 ], x3, y3, z3, w3 ); + + } + + let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; + if ( t4 < 0 ) n4 = 0.0; + else { + + t4 *= t4; + n4 = t4 * t4 * this.dot4( grad4[ gi4 ], x4, y4, z4, w4 ); + + } + + // Sum up and scale the result to cover the range [-1,1] + return 27.0 * ( n0 + n1 + n2 + n3 + n4 ); } - // Sum up and scale the result to cover the range [-1,1] - return 27.0 * ( n0 + n1 + n2 + n3 + n4 ); - -}; +} export { SimplexNoise }; diff --git a/examples/jsm/misc/ConvexObjectBreaker.js b/examples/jsm/misc/ConvexObjectBreaker.js index 1acdfb0bcbf246..d262bcf830b244 100644 --- a/examples/jsm/misc/ConvexObjectBreaker.js +++ b/examples/jsm/misc/ConvexObjectBreaker.js @@ -35,40 +35,40 @@ import { ConvexGeometry } from '../geometries/ConvexGeometry.js'; * */ -var ConvexObjectBreaker = function ( minSizeForBreak, smallDelta ) { +const _v1 = new Vector3(); + +class ConvexObjectBreaker { + + constructor( minSizeForBreak = 1.4, smallDelta = 0.0001 ) { + + this.minSizeForBreak = minSizeForBreak; + this.smallDelta = smallDelta; + + this.tempLine1 = new Line3(); + this.tempPlane1 = new Plane(); + this.tempPlane2 = new Plane(); + this.tempPlane_Cut = new Plane(); + this.tempCM1 = new Vector3(); + this.tempCM2 = new Vector3(); + this.tempVector3 = new Vector3(); + this.tempVector3_2 = new Vector3(); + this.tempVector3_3 = new Vector3(); + this.tempVector3_P0 = new Vector3(); + this.tempVector3_P1 = new Vector3(); + this.tempVector3_P2 = new Vector3(); + this.tempVector3_N0 = new Vector3(); + this.tempVector3_N1 = new Vector3(); + this.tempVector3_AB = new Vector3(); + this.tempVector3_CB = new Vector3(); + this.tempResultObjects = { object1: null, object2: null }; + + this.segments = []; + const n = 30 * 30; + for ( let i = 0; i < n; i ++ ) this.segments[ i ] = false; - this.minSizeForBreak = minSizeForBreak || 1.4; - this.smallDelta = smallDelta || 0.0001; - - this.tempLine1 = new Line3(); - this.tempPlane1 = new Plane(); - this.tempPlane2 = new Plane(); - this.tempPlane_Cut = new Plane(); - this.tempCM1 = new Vector3(); - this.tempCM2 = new Vector3(); - this.tempVector3 = new Vector3(); - this.tempVector3_2 = new Vector3(); - this.tempVector3_3 = new Vector3(); - this.tempVector3_P0 = new Vector3(); - this.tempVector3_P1 = new Vector3(); - this.tempVector3_P2 = new Vector3(); - this.tempVector3_N0 = new Vector3(); - this.tempVector3_N1 = new Vector3(); - this.tempVector3_AB = new Vector3(); - this.tempVector3_CB = new Vector3(); - this.tempResultObjects = { object1: null, object2: null }; - - this.segments = []; - var n = 30 * 30; - for ( var i = 0; i < n; i ++ ) this.segments[ i ] = false; - -}; - -ConvexObjectBreaker.prototype = { - - constructor: ConvexObjectBreaker, + } - prepareBreakableObject: function ( object, mass, velocity, angularVelocity, breakable ) { + prepareBreakableObject( object, mass, velocity, angularVelocity, breakable ) { // object is a Object3d (normally a Mesh), must have a BufferGeometry, and it must be convex. // Its material property is propagated to its children (sub-pieces) @@ -80,13 +80,13 @@ ConvexObjectBreaker.prototype = { } - var userData = object.userData; + const userData = object.userData; userData.mass = mass; userData.velocity = velocity.clone(); userData.angularVelocity = angularVelocity.clone(); userData.breakable = breakable; - }, + } /* * @param {int} maxRadialIterations Iterations for radial cuts. @@ -94,19 +94,19 @@ ConvexObjectBreaker.prototype = { * * Returns the array of pieces */ - subdivideByImpact: function ( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) { + subdivideByImpact( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) { - var debris = []; + const debris = []; - var tempPlane1 = this.tempPlane1; - var tempPlane2 = this.tempPlane2; + const tempPlane1 = this.tempPlane1; + const tempPlane2 = this.tempPlane2; this.tempVector3.addVectors( pointOfImpact, normal ); tempPlane1.setFromCoplanarPoints( pointOfImpact, object.position, this.tempVector3 ); - var maxTotalIterations = maxRandomIterations + maxRadialIterations; + const maxTotalIterations = maxRandomIterations + maxRadialIterations; - var scope = this; + const scope = this; function subdivideRadial( subObject, startAngle, endAngle, numIterations ) { @@ -118,7 +118,7 @@ ConvexObjectBreaker.prototype = { } - var angle = Math.PI; + let angle = Math.PI; if ( numIterations === 0 ) { @@ -151,8 +151,8 @@ ConvexObjectBreaker.prototype = { // Perform the cut scope.cutByPlane( subObject, tempPlane2, scope.tempResultObjects ); - var obj1 = scope.tempResultObjects.object1; - var obj2 = scope.tempResultObjects.object2; + const obj1 = scope.tempResultObjects.object1; + const obj2 = scope.tempResultObjects.object2; if ( obj1 ) { @@ -172,23 +172,23 @@ ConvexObjectBreaker.prototype = { return debris; - }, + } - cutByPlane: function ( object, plane, output ) { + cutByPlane( object, plane, output ) { // Returns breakable objects in output.object1 and output.object2 members, the resulting 2 pieces of the cut. // object2 can be null if the plane doesn't cut the object. // object1 can be null only in case of internal error // Returned value is number of pieces, 0 for error. - var geometry = object.geometry; - var coords = geometry.attributes.position.array; - var normals = geometry.attributes.normal.array; + const geometry = object.geometry; + const coords = geometry.attributes.position.array; + const normals = geometry.attributes.normal.array; - var numPoints = coords.length / 3; - var numFaces = numPoints / 3; + const numPoints = coords.length / 3; + let numFaces = numPoints / 3; - var indices = geometry.getIndex(); + let indices = geometry.getIndex(); if ( indices ) { @@ -201,46 +201,46 @@ ConvexObjectBreaker.prototype = { // vert = 0, 1 or 2. - var idx = faceIdx * 3 + vert; + const idx = faceIdx * 3 + vert; return indices ? indices[ idx ] : idx; } - var points1 = []; - var points2 = []; + const points1 = []; + const points2 = []; - var delta = this.smallDelta; + const delta = this.smallDelta; // Reset segments mark - var numPointPairs = numPoints * numPoints; - for ( var i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false; + const numPointPairs = numPoints * numPoints; + for ( let i = 0; i < numPointPairs; i ++ ) this.segments[ i ] = false; - var p0 = this.tempVector3_P0; - var p1 = this.tempVector3_P1; - var n0 = this.tempVector3_N0; - var n1 = this.tempVector3_N1; + const p0 = this.tempVector3_P0; + const p1 = this.tempVector3_P1; + const n0 = this.tempVector3_N0; + const n1 = this.tempVector3_N1; // Iterate through the faces to mark edges shared by coplanar faces - for ( var i = 0; i < numFaces - 1; i ++ ) { + for ( let i = 0; i < numFaces - 1; i ++ ) { - var a1 = getVertexIndex( i, 0 ); - var b1 = getVertexIndex( i, 1 ); - var c1 = getVertexIndex( i, 2 ); + const a1 = getVertexIndex( i, 0 ); + const b1 = getVertexIndex( i, 1 ); + const c1 = getVertexIndex( i, 2 ); // Assuming all 3 vertices have the same normal n0.set( normals[ a1 ], normals[ a1 ] + 1, normals[ a1 ] + 2 ); - for ( var j = i + 1; j < numFaces; j ++ ) { + for ( let j = i + 1; j < numFaces; j ++ ) { - var a2 = getVertexIndex( j, 0 ); - var b2 = getVertexIndex( j, 1 ); - var c2 = getVertexIndex( j, 2 ); + const a2 = getVertexIndex( j, 0 ); + const b2 = getVertexIndex( j, 1 ); + const c2 = getVertexIndex( j, 2 ); // Assuming all 3 vertices have the same normal n1.set( normals[ a2 ], normals[ a2 ] + 1, normals[ a2 ] + 2 ); - var coplanar = 1 - n0.dot( n1 ) < delta; + const coplanar = 1 - n0.dot( n1 ) < delta; if ( coplanar ) { @@ -272,23 +272,23 @@ ConvexObjectBreaker.prototype = { } // Transform the plane to object local space - var localPlane = this.tempPlane_Cut; + const localPlane = this.tempPlane_Cut; object.updateMatrix(); ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane ); // Iterate through the faces adding points to both pieces - for ( var i = 0; i < numFaces; i ++ ) { + for ( let i = 0; i < numFaces; i ++ ) { - var va = getVertexIndex( i, 0 ); - var vb = getVertexIndex( i, 1 ); - var vc = getVertexIndex( i, 2 ); + const va = getVertexIndex( i, 0 ); + const vb = getVertexIndex( i, 1 ); + const vc = getVertexIndex( i, 2 ); - for ( var segment = 0; segment < 3; segment ++ ) { + for ( let segment = 0; segment < 3; segment ++ ) { - var i0 = segment === 0 ? va : ( segment === 1 ? vb : vc ); - var i1 = segment === 0 ? vb : ( segment === 1 ? vc : va ); + const i0 = segment === 0 ? va : ( segment === 1 ? vb : vc ); + const i1 = segment === 0 ? vb : ( segment === 1 ? vc : va ); - var segmentState = this.segments[ i0 * numPoints + i1 ]; + const segmentState = this.segments[ i0 * numPoints + i1 ]; if ( segmentState ) continue; // The segment already has been processed in another face @@ -300,9 +300,9 @@ ConvexObjectBreaker.prototype = { p1.set( coords[ 3 * i1 ], coords[ 3 * i1 + 1 ], coords[ 3 * i1 + 2 ] ); // mark: 1 for negative side, 2 for positive side, 3 for coplanar point - var mark0 = 0; + let mark0 = 0; - var d = localPlane.distanceToPoint( p0 ); + let d = localPlane.distanceToPoint( p0 ); if ( d > delta ) { @@ -323,9 +323,9 @@ ConvexObjectBreaker.prototype = { } // mark: 1 for negative side, 2 for positive side, 3 for coplanar point - var mark1 = 0; + let mark1 = 0; - var d = localPlane.distanceToPoint( p1 ); + d = localPlane.distanceToPoint( p1 ); if ( d > delta ) { @@ -352,7 +352,7 @@ ConvexObjectBreaker.prototype = { this.tempLine1.start.copy( p0 ); this.tempLine1.end.copy( p1 ); - var intersection = new Vector3(); + let intersection = new Vector3(); intersection = localPlane.intersectLine( this.tempLine1, intersection ); if ( intersection === null ) { @@ -375,21 +375,21 @@ ConvexObjectBreaker.prototype = { } // Calculate debris mass (very fast and imprecise): - var newMass = object.userData.mass * 0.5; + const newMass = object.userData.mass * 0.5; // Calculate debris Center of Mass (again fast and imprecise) this.tempCM1.set( 0, 0, 0 ); - var radius1 = 0; - var numPoints1 = points1.length; + let radius1 = 0; + const numPoints1 = points1.length; if ( numPoints1 > 0 ) { - for ( var i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] ); + for ( let i = 0; i < numPoints1; i ++ ) this.tempCM1.add( points1[ i ] ); this.tempCM1.divideScalar( numPoints1 ); - for ( var i = 0; i < numPoints1; i ++ ) { + for ( let i = 0; i < numPoints1; i ++ ) { - var p = points1[ i ]; + const p = points1[ i ]; p.sub( this.tempCM1 ); radius1 = Math.max( radius1, p.x, p.y, p.z ); @@ -400,16 +400,16 @@ ConvexObjectBreaker.prototype = { } this.tempCM2.set( 0, 0, 0 ); - var radius2 = 0; - var numPoints2 = points2.length; + let radius2 = 0; + const numPoints2 = points2.length; if ( numPoints2 > 0 ) { - for ( var i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] ); + for ( let i = 0; i < numPoints2; i ++ ) this.tempCM2.add( points2[ i ] ); this.tempCM2.divideScalar( numPoints2 ); - for ( var i = 0; i < numPoints2; i ++ ) { + for ( let i = 0; i < numPoints2; i ++ ) { - var p = points2[ i ]; + const p = points2[ i ]; p.sub( this.tempCM2 ); radius2 = Math.max( radius2, p.x, p.y, p.z ); @@ -419,10 +419,10 @@ ConvexObjectBreaker.prototype = { } - var object1 = null; - var object2 = null; + let object1 = null; + let object2 = null; - var numObjects = 0; + let numObjects = 0; if ( numPoints1 > 4 ) { @@ -455,78 +455,71 @@ ConvexObjectBreaker.prototype = { } -}; + static transformFreeVector( v, m ) { -ConvexObjectBreaker.transformFreeVector = function ( v, m ) { + // input: + // vector interpreted as a free vector + // THREE.Matrix4 orthogonal matrix (matrix without scale) - // input: - // vector interpreted as a free vector - // THREE.Matrix4 orthogonal matrix (matrix without scale) + const x = v.x, y = v.y, z = v.z; + const e = m.elements; - var x = v.x, y = v.y, z = v.z; - var e = m.elements; + v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; + return v; - return v; - -}; - -ConvexObjectBreaker.transformFreeVectorInverse = function ( v, m ) { - - // input: - // vector interpreted as a free vector - // THREE.Matrix4 orthogonal matrix (matrix without scale) + } - var x = v.x, y = v.y, z = v.z; - var e = m.elements; + static transformFreeVectorInverse( v, m ) { - v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z; - v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z; - v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z; + // input: + // vector interpreted as a free vector + // THREE.Matrix4 orthogonal matrix (matrix without scale) - return v; + const x = v.x, y = v.y, z = v.z; + const e = m.elements; -}; + v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z; + v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z; + v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z; -ConvexObjectBreaker.transformTiedVectorInverse = function ( v, m ) { + return v; - // input: - // vector interpreted as a tied (ordinary) vector - // THREE.Matrix4 orthogonal matrix (matrix without scale) + } - var x = v.x, y = v.y, z = v.z; - var e = m.elements; + static transformTiedVectorInverse( v, m ) { - v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z - e[ 12 ]; - v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z - e[ 13 ]; - v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ]; + // input: + // vector interpreted as a tied (ordinary) vector + // THREE.Matrix4 orthogonal matrix (matrix without scale) - return v; + const x = v.x, y = v.y, z = v.z; + const e = m.elements; -}; + v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ] * z - e[ 12 ]; + v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ] * z - e[ 13 ]; + v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ]; -ConvexObjectBreaker.transformPlaneToLocalSpace = function () { + return v; - var v1 = new Vector3(); + } - return function transformPlaneToLocalSpace( plane, m, resultPlane ) { + static transformPlaneToLocalSpace( plane, m, resultPlane ) { resultPlane.normal.copy( plane.normal ); resultPlane.constant = plane.constant; - var referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( v1 ), m ); + const referencePoint = ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( _v1 ), m ); ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m ); // recalculate constant (like in setFromNormalAndCoplanarPoint) resultPlane.constant = - referencePoint.dot( resultPlane.normal ); + } - }; - -}(); +} export { ConvexObjectBreaker }; diff --git a/examples/jsm/misc/GPUComputationRenderer.js b/examples/jsm/misc/GPUComputationRenderer.js index 7bc4f4cca6bf47..32764ac2390552 100644 --- a/examples/jsm/misc/GPUComputationRenderer.js +++ b/examples/jsm/misc/GPUComputationRenderer.js @@ -40,16 +40,16 @@ import { * // Initialization... * * // Create computation renderer - * var gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer ); + * const gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer ); * * // Create initial state float textures - * var pos0 = gpuCompute.createTexture(); - * var vel0 = gpuCompute.createTexture(); + * const pos0 = gpuCompute.createTexture(); + * const vel0 = gpuCompute.createTexture(); * // and fill in here the texture data... * * // Add texture variables - * var velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 ); - * var posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 ); + * const velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 ); + * const posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 ); * * // Add variable dependencies * gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] ); @@ -59,7 +59,7 @@ import { * velVar.material.uniforms.time = { value: 0.0 }; * * // Check for completeness - * var error = gpuCompute.init(); + * const error = gpuCompute.init(); * if ( error !== null ) { * console.error( error ); * } @@ -81,19 +81,19 @@ import { * Also, you can use utility functions to create ShaderMaterial and perform computations (rendering between textures) * Note that the shaders can have multiple input textures. * - * var myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } ); - * var myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } ); + * const myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } ); + * const myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } ); * - * var inputTexture = gpuCompute.createTexture(); + * const inputTexture = gpuCompute.createTexture(); * * // Fill in here inputTexture... * * myFilter1.uniforms.theTexture.value = inputTexture; * - * var myRenderTarget = gpuCompute.createRenderTarget(); + * const myRenderTarget = gpuCompute.createRenderTarget(); * myFilter2.uniforms.theTexture.value = myRenderTarget.texture; * - * var outputRenderTarget = gpuCompute.createRenderTarget(); + * const outputRenderTarget = gpuCompute.createRenderTarget(); * * // Now use the output texture where you want: * myMaterial.uniforms.map.value = outputRenderTarget.texture; @@ -109,295 +109,301 @@ import { * @param {WebGLRenderer} renderer The renderer */ -var GPUComputationRenderer = function ( sizeX, sizeY, renderer ) { +class GPUComputationRenderer { - this.variables = []; + constructor( sizeX, sizeY, renderer ) { - this.currentTextureIndex = 0; + this.variables = []; - var dataType = FloatType; + this.currentTextureIndex = 0; - var scene = new Scene(); + let dataType = FloatType; - var camera = new Camera(); - camera.position.z = 1; + const scene = new Scene(); - var passThruUniforms = { - passThruTexture: { value: null } - }; + const camera = new Camera(); + camera.position.z = 1; - var passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms ); + const passThruUniforms = { + passThruTexture: { value: null } + }; - var mesh = new Mesh( new PlaneGeometry( 2, 2 ), passThruShader ); - scene.add( mesh ); + const passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms ); + const mesh = new Mesh( new PlaneGeometry( 2, 2 ), passThruShader ); + scene.add( mesh ); - this.setDataType = function ( type ) { - dataType = type; - return this; + this.setDataType = function ( type ) { - }; + dataType = type; + return this; - this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) { + }; - var material = this.createShaderMaterial( computeFragmentShader ); + this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) { - var variable = { - name: variableName, - initialValueTexture: initialValueTexture, - material: material, - dependencies: null, - renderTargets: [], - wrapS: null, - wrapT: null, - minFilter: NearestFilter, - magFilter: NearestFilter - }; + const material = this.createShaderMaterial( computeFragmentShader ); + + const variable = { + name: variableName, + initialValueTexture: initialValueTexture, + material: material, + dependencies: null, + renderTargets: [], + wrapS: null, + wrapT: null, + minFilter: NearestFilter, + magFilter: NearestFilter + }; - this.variables.push( variable ); + this.variables.push( variable ); - return variable; + return variable; - }; + }; - this.setVariableDependencies = function ( variable, dependencies ) { + this.setVariableDependencies = function ( variable, dependencies ) { - variable.dependencies = dependencies; + variable.dependencies = dependencies; - }; + }; - this.init = function () { + this.init = function () { - if ( renderer.capabilities.isWebGL2 === false && renderer.extensions.has( 'OES_texture_float' ) === false ) { + if ( renderer.capabilities.isWebGL2 === false && renderer.extensions.has( 'OES_texture_float' ) === false ) { - return 'No OES_texture_float support for float textures.'; + return 'No OES_texture_float support for float textures.'; - } + } - if ( renderer.capabilities.maxVertexTextures === 0 ) { + if ( renderer.capabilities.maxVertexTextures === 0 ) { - return 'No support for vertex shader textures.'; + return 'No support for vertex shader textures.'; - } + } + + for ( let i = 0; i < this.variables.length; i ++ ) { + + const variable = this.variables[ i ]; - for ( var i = 0; i < this.variables.length; i ++ ) { + // Creates rendertargets and initialize them with input texture + variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter ); + variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter ); + this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] ); + this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] ); - var variable = this.variables[ i ]; + // Adds dependencies uniforms to the ShaderMaterial + const material = variable.material; + const uniforms = material.uniforms; - // Creates rendertargets and initialize them with input texture - variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter ); - variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter ); - this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] ); - this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] ); + if ( variable.dependencies !== null ) { - // Adds dependencies uniforms to the ShaderMaterial - var material = variable.material; - var uniforms = material.uniforms; + for ( let d = 0; d < variable.dependencies.length; d ++ ) { - if ( variable.dependencies !== null ) { + const depVar = variable.dependencies[ d ]; - for ( var d = 0; d < variable.dependencies.length; d ++ ) { + if ( depVar.name !== variable.name ) { - var depVar = variable.dependencies[ d ]; + // Checks if variable exists + let found = false; - if ( depVar.name !== variable.name ) { + for ( let j = 0; j < this.variables.length; j ++ ) { - // Checks if variable exists - var found = false; - for ( var j = 0; j < this.variables.length; j ++ ) { + if ( depVar.name === this.variables[ j ].name ) { - if ( depVar.name === this.variables[ j ].name ) { + found = true; + break; - found = true; - break; + } } - } + if ( ! found ) { - if ( ! found ) { + return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name; - return 'Variable dependency not found. Variable=' + variable.name + ', dependency=' + depVar.name; + } } - } + uniforms[ depVar.name ] = { value: null }; - uniforms[ depVar.name ] = { value: null }; + material.fragmentShader = '\nuniform sampler2D ' + depVar.name + ';\n' + material.fragmentShader; - material.fragmentShader = '\nuniform sampler2D ' + depVar.name + ';\n' + material.fragmentShader; + } } } - } + this.currentTextureIndex = 0; - this.currentTextureIndex = 0; + return null; - return null; + }; - }; + this.compute = function () { - this.compute = function () { + const currentTextureIndex = this.currentTextureIndex; + const nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0; - var currentTextureIndex = this.currentTextureIndex; - var nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0; + for ( let i = 0, il = this.variables.length; i < il; i ++ ) { - for ( var i = 0, il = this.variables.length; i < il; i ++ ) { + const variable = this.variables[ i ]; - var variable = this.variables[ i ]; + // Sets texture dependencies uniforms + if ( variable.dependencies !== null ) { - // Sets texture dependencies uniforms - if ( variable.dependencies !== null ) { + const uniforms = variable.material.uniforms; - var uniforms = variable.material.uniforms; - for ( var d = 0, dl = variable.dependencies.length; d < dl; d ++ ) { + for ( let d = 0, dl = variable.dependencies.length; d < dl; d ++ ) { - var depVar = variable.dependencies[ d ]; + const depVar = variable.dependencies[ d ]; - uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture; + uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture; + + } } - } + // Performs the computation for this variable + this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] ); - // Performs the computation for this variable - this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] ); + } - } + this.currentTextureIndex = nextTextureIndex; - this.currentTextureIndex = nextTextureIndex; + }; - }; + this.getCurrentRenderTarget = function ( variable ) { - this.getCurrentRenderTarget = function ( variable ) { + return variable.renderTargets[ this.currentTextureIndex ]; - return variable.renderTargets[ this.currentTextureIndex ]; + }; - }; + this.getAlternateRenderTarget = function ( variable ) { - this.getAlternateRenderTarget = function ( variable ) { + return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ]; - return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ]; + }; - }; + function addResolutionDefine( materialShader ) { - function addResolutionDefine( materialShader ) { + materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )'; - materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )'; + } - } + this.addResolutionDefine = addResolutionDefine; - this.addResolutionDefine = addResolutionDefine; + // The following functions can be used to compute things manually - // The following functions can be used to compute things manually + function createShaderMaterial( computeFragmentShader, uniforms ) { - function createShaderMaterial( computeFragmentShader, uniforms ) { + uniforms = uniforms || {}; - uniforms = uniforms || {}; + const material = new ShaderMaterial( { + uniforms: uniforms, + vertexShader: getPassThroughVertexShader(), + fragmentShader: computeFragmentShader + } ); - var material = new ShaderMaterial( { - uniforms: uniforms, - vertexShader: getPassThroughVertexShader(), - fragmentShader: computeFragmentShader - } ); + addResolutionDefine( material ); - addResolutionDefine( material ); + return material; - return material; + } - } + this.createShaderMaterial = createShaderMaterial; - this.createShaderMaterial = createShaderMaterial; + this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) { - this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) { + sizeXTexture = sizeXTexture || sizeX; + sizeYTexture = sizeYTexture || sizeY; - sizeXTexture = sizeXTexture || sizeX; - sizeYTexture = sizeYTexture || sizeY; + wrapS = wrapS || ClampToEdgeWrapping; + wrapT = wrapT || ClampToEdgeWrapping; - wrapS = wrapS || ClampToEdgeWrapping; - wrapT = wrapT || ClampToEdgeWrapping; + minFilter = minFilter || NearestFilter; + magFilter = magFilter || NearestFilter; - minFilter = minFilter || NearestFilter; - magFilter = magFilter || NearestFilter; + const renderTarget = new WebGLRenderTarget( sizeXTexture, sizeYTexture, { + wrapS: wrapS, + wrapT: wrapT, + minFilter: minFilter, + magFilter: magFilter, + format: RGBAFormat, + type: dataType, + depthBuffer: false + } ); - var renderTarget = new WebGLRenderTarget( sizeXTexture, sizeYTexture, { - wrapS: wrapS, - wrapT: wrapT, - minFilter: minFilter, - magFilter: magFilter, - format: RGBAFormat, - type: dataType, - depthBuffer: false - } ); + return renderTarget; - return renderTarget; + }; - }; + this.createTexture = function () { - this.createTexture = function () { + const data = new Float32Array( sizeX * sizeY * 4 ); + return new DataTexture( data, sizeX, sizeY, RGBAFormat, FloatType ); - var data = new Float32Array( sizeX * sizeY * 4 ); - return new DataTexture( data, sizeX, sizeY, RGBAFormat, FloatType ); + }; - }; + this.renderTexture = function ( input, output ) { - this.renderTexture = function ( input, output ) { + // Takes a texture, and render out in rendertarget + // input = Texture + // output = RenderTarget - // Takes a texture, and render out in rendertarget - // input = Texture - // output = RenderTarget + passThruUniforms.passThruTexture.value = input; - passThruUniforms.passThruTexture.value = input; + this.doRenderTarget( passThruShader, output ); - this.doRenderTarget( passThruShader, output ); + passThruUniforms.passThruTexture.value = null; - passThruUniforms.passThruTexture.value = null; + }; - }; + this.doRenderTarget = function ( material, output ) { - this.doRenderTarget = function ( material, output ) { + const currentRenderTarget = renderer.getRenderTarget(); - var currentRenderTarget = renderer.getRenderTarget(); + mesh.material = material; + renderer.setRenderTarget( output ); + renderer.render( scene, camera ); + mesh.material = passThruShader; - mesh.material = material; - renderer.setRenderTarget( output ); - renderer.render( scene, camera ); - mesh.material = passThruShader; + renderer.setRenderTarget( currentRenderTarget ); - renderer.setRenderTarget( currentRenderTarget ); + }; - }; + // Shaders - // Shaders + function getPassThroughVertexShader() { - function getPassThroughVertexShader() { + return 'void main() {\n' + + '\n' + + ' gl_Position = vec4( position, 1.0 );\n' + + '\n' + + '}\n'; - return 'void main() {\n' + - '\n' + - ' gl_Position = vec4( position, 1.0 );\n' + - '\n' + - '}\n'; + } - } + function getPassThroughFragmentShader() { - function getPassThroughFragmentShader() { + return 'uniform sampler2D passThruTexture;\n' + + '\n' + + 'void main() {\n' + + '\n' + + ' vec2 uv = gl_FragCoord.xy / resolution.xy;\n' + + '\n' + + ' gl_FragColor = texture2D( passThruTexture, uv );\n' + + '\n' + + '}\n'; - return 'uniform sampler2D passThruTexture;\n' + - '\n' + - 'void main() {\n' + - '\n' + - ' vec2 uv = gl_FragCoord.xy / resolution.xy;\n' + - '\n' + - ' gl_FragColor = texture2D( passThruTexture, uv );\n' + - '\n' + - '}\n'; + } } -}; +} export { GPUComputationRenderer }; diff --git a/examples/jsm/misc/Gyroscope.js b/examples/jsm/misc/Gyroscope.js index 6d9eb59180bba4..7d81948ea56fd0 100644 --- a/examples/jsm/misc/Gyroscope.js +++ b/examples/jsm/misc/Gyroscope.js @@ -4,26 +4,23 @@ import { Vector3 } from '../../../build/three.module.js'; -var Gyroscope = function () { +const _translationObject = new Vector3(); +const _quaternionObject = new Quaternion(); +const _scaleObject = new Vector3(); - Object3D.call( this ); +const _translationWorld = new Vector3(); +const _quaternionWorld = new Quaternion(); +const _scaleWorld = new Vector3(); -}; +class Gyroscope extends Object3D { -Gyroscope.prototype = Object.create( Object3D.prototype ); -Gyroscope.prototype.constructor = Gyroscope; + constructor() { -Gyroscope.prototype.updateMatrixWorld = ( function () { + super(); - var translationObject = new Vector3(); - var quaternionObject = new Quaternion(); - var scaleObject = new Vector3(); + } - var translationWorld = new Vector3(); - var quaternionWorld = new Quaternion(); - var scaleWorld = new Vector3(); - - return function updateMatrixWorld( force ) { + updateMatrixWorld( force ) { this.matrixAutoUpdate && this.updateMatrix(); @@ -35,10 +32,10 @@ Gyroscope.prototype.updateMatrixWorld = ( function () { this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - this.matrixWorld.decompose( translationWorld, quaternionWorld, scaleWorld ); - this.matrix.decompose( translationObject, quaternionObject, scaleObject ); + this.matrixWorld.decompose( _translationWorld, _quaternionWorld, _scaleWorld ); + this.matrix.decompose( _translationObject, _quaternionObject, _scaleObject ); - this.matrixWorld.compose( translationWorld, quaternionObject, scaleWorld ); + this.matrixWorld.compose( _translationWorld, _quaternionObject, _scaleWorld ); } else { @@ -56,14 +53,14 @@ Gyroscope.prototype.updateMatrixWorld = ( function () { // update children - for ( var i = 0, l = this.children.length; i < l; i ++ ) { + for ( let i = 0, l = this.children.length; i < l; i ++ ) { this.children[ i ].updateMatrixWorld( force ); } - }; + } -}() ); +} export { Gyroscope }; diff --git a/examples/jsm/misc/MD2Character.js b/examples/jsm/misc/MD2Character.js index 9398481e0029c6..e9756a3e4f5a85 100644 --- a/examples/jsm/misc/MD2Character.js +++ b/examples/jsm/misc/MD2Character.js @@ -10,37 +10,89 @@ import { } from '../../../build/three.module.js'; import { MD2Loader } from '../loaders/MD2Loader.js'; -var MD2Character = function () { +class MD2Character { - var scope = this; + constructor() { - this.scale = 1; - this.animationFPS = 6; + this.scale = 1; + this.animationFPS = 6; - this.root = new Object3D(); + this.root = new Object3D(); - this.meshBody = null; - this.meshWeapon = null; + this.meshBody = null; + this.meshWeapon = null; - this.skinsBody = []; - this.skinsWeapon = []; + this.skinsBody = []; + this.skinsWeapon = []; - this.weapons = []; + this.weapons = []; - this.activeAnimation = null; + this.activeAnimation = null; - this.mixer = null; + this.mixer = null; - this.onLoadComplete = function () {}; + this.onLoadComplete = function () {}; - this.loadCounter = 0; + this.loadCounter = 0; - this.loadParts = function ( config ) { + } + + loadParts( config ) { + + const scope = this; + + function createPart( geometry, skinMap ) { + + const materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } ); + const materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } ); + + // + + const mesh = new Mesh( geometry, materialTexture ); + mesh.rotation.y = - Math.PI / 2; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + // + + mesh.materialTexture = materialTexture; + mesh.materialWireframe = materialWireframe; + + return mesh; + + } + + function loadTextures( baseUrl, textureUrls ) { + + const textureLoader = new TextureLoader(); + const textures = []; + + for ( let i = 0; i < textureUrls.length; i ++ ) { + + textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete ); + textures[ i ].mapping = UVMapping; + textures[ i ].name = textureUrls[ i ]; + textures[ i ].encoding = sRGBEncoding; + + } + + return textures; + + } + + function checkLoadingComplete() { + + scope.loadCounter -= 1; + + if ( scope.loadCounter === 0 ) scope.onLoadComplete(); + + } this.loadCounter = config.weapons.length * 2 + config.skins.length + 1; - var weaponsTextures = []; - for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; + const weaponsTextures = []; + for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS this.skinsBody = loadTextures( config.baseUrl + 'skins/', config.skins ); @@ -48,16 +100,16 @@ var MD2Character = function () { // BODY - var loader = new MD2Loader(); + const loader = new MD2Loader(); loader.load( config.baseUrl + config.body, function ( geo ) { - var boundingBox = new Box3(); + const boundingBox = new Box3(); boundingBox.setFromBufferAttribute( geo.attributes.position ); scope.root.position.y = - scope.scale * boundingBox.min.y; - var mesh = createPart( geo, scope.skinsBody[ 0 ] ); + const mesh = createPart( geo, scope.skinsBody[ 0 ] ); mesh.scale.set( scope.scale, scope.scale, scope.scale ); scope.root.add( mesh ); @@ -75,11 +127,11 @@ var MD2Character = function () { // WEAPONS - var generateCallback = function ( index, name ) { + const generateCallback = function ( index, name ) { return function ( geo ) { - var mesh = createPart( geo, scope.skinsWeapon[ index ] ); + const mesh = createPart( geo, scope.skinsWeapon[ index ] ); mesh.scale.set( scope.scale, scope.scale, scope.scale ); mesh.visible = false; @@ -96,15 +148,15 @@ var MD2Character = function () { }; - for ( var i = 0; i < config.weapons.length; i ++ ) { + for ( let i = 0; i < config.weapons.length; i ++ ) { loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) ); } - }; + } - this.setPlaybackRate = function ( rate ) { + setPlaybackRate( rate ) { if ( rate !== 0 ) { @@ -116,9 +168,9 @@ var MD2Character = function () { } - }; + } - this.setWireframe = function ( wireframeEnabled ) { + setWireframe( wireframeEnabled ) { if ( wireframeEnabled ) { @@ -132,9 +184,9 @@ var MD2Character = function () { } - }; + } - this.setSkin = function ( index ) { + setSkin( index ) { if ( this.meshBody && this.meshBody.material.wireframe === false ) { @@ -142,26 +194,26 @@ var MD2Character = function () { } - }; + } - this.setWeapon = function ( index ) { + setWeapon( index ) { - for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false; + for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false; - var activeWeapon = this.weapons[ index ]; + const activeWeapon = this.weapons[ index ]; if ( activeWeapon ) { activeWeapon.visible = true; this.meshWeapon = activeWeapon; - scope.syncWeaponAnimation(); + this.syncWeaponAnimation(); } - }; + } - this.setAnimation = function ( clipName ) { + setAnimation( clipName ) { if ( this.meshBody ) { @@ -172,7 +224,7 @@ var MD2Character = function () { } - var action = this.mixer.clipAction( clipName, this.meshBody ); + const action = this.mixer.clipAction( clipName, this.meshBody ); if ( action ) { @@ -182,17 +234,17 @@ var MD2Character = function () { } - scope.activeClipName = clipName; + this.activeClipName = clipName; - scope.syncWeaponAnimation(); + this.syncWeaponAnimation(); - }; + } - this.syncWeaponAnimation = function () { + syncWeaponAnimation() { - var clipName = scope.activeClipName; + const clipName = this.activeClipName; - if ( scope.meshWeapon ) { + if ( this.meshWeapon ) { if ( this.meshWeapon.activeAction ) { @@ -201,7 +253,7 @@ var MD2Character = function () { } - var action = this.mixer.clipAction( clipName, this.meshWeapon ); + const action = this.mixer.clipAction( clipName, this.meshWeapon ); if ( action ) { @@ -211,62 +263,14 @@ var MD2Character = function () { } - }; - - this.update = function ( delta ) { - - if ( this.mixer ) this.mixer.update( delta ); - - }; - - function loadTextures( baseUrl, textureUrls ) { - - var textureLoader = new TextureLoader(); - var textures = []; - - for ( var i = 0; i < textureUrls.length; i ++ ) { - - textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete ); - textures[ i ].mapping = UVMapping; - textures[ i ].name = textureUrls[ i ]; - textures[ i ].encoding = sRGBEncoding; - - } - - return textures; - - } - - function createPart( geometry, skinMap ) { - - var materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } ); - var materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } ); - - // - - var mesh = new Mesh( geometry, materialTexture ); - mesh.rotation.y = - Math.PI / 2; - - mesh.castShadow = true; - mesh.receiveShadow = true; - - // - - mesh.materialTexture = materialTexture; - mesh.materialWireframe = materialWireframe; - - return mesh; - } - function checkLoadingComplete() { - - scope.loadCounter -= 1; + update( delta ) { - if ( scope.loadCounter === 0 ) scope.onLoadComplete(); + if ( this.mixer ) this.mixer.update( delta ); } -}; +} export { MD2Character }; diff --git a/examples/jsm/misc/MD2CharacterComplex.js b/examples/jsm/misc/MD2CharacterComplex.js index 95eb389edecd99..7b4c51829562ac 100644 --- a/examples/jsm/misc/MD2CharacterComplex.js +++ b/examples/jsm/misc/MD2CharacterComplex.js @@ -10,97 +10,98 @@ import { import { MD2Loader } from '../loaders/MD2Loader.js'; import { MorphBlendMesh } from '../misc/MorphBlendMesh.js'; -var MD2CharacterComplex = function () { +class MD2CharacterComplex { - var scope = this; + constructor() { - this.scale = 1; + this.scale = 1; - // animation parameters + // animation parameters - this.animationFPS = 6; - this.transitionFrames = 15; + this.animationFPS = 6; + this.transitionFrames = 15; - // movement model parameters + // movement model parameters - this.maxSpeed = 275; - this.maxReverseSpeed = - 275; + this.maxSpeed = 275; + this.maxReverseSpeed = - 275; - this.frontAcceleration = 600; - this.backAcceleration = 600; + this.frontAcceleration = 600; + this.backAcceleration = 600; - this.frontDecceleration = 600; + this.frontDecceleration = 600; - this.angularSpeed = 2.5; + this.angularSpeed = 2.5; - // rig + // rig - this.root = new Object3D(); + this.root = new Object3D(); - this.meshBody = null; - this.meshWeapon = null; + this.meshBody = null; + this.meshWeapon = null; - this.controls = null; + this.controls = null; - // skins + // skins - this.skinsBody = []; - this.skinsWeapon = []; + this.skinsBody = []; + this.skinsWeapon = []; - this.weapons = []; + this.weapons = []; - this.currentSkin = undefined; + this.currentSkin = undefined; - // + // + + this.onLoadComplete = function () {}; - this.onLoadComplete = function () {}; + // internals - // internals + this.meshes = []; + this.animations = {}; - this.meshes = []; - this.animations = {}; + this.loadCounter = 0; - this.loadCounter = 0; + // internal movement control variables - // internal movement control variables + this.speed = 0; + this.bodyOrientation = 0; - this.speed = 0; - this.bodyOrientation = 0; + this.walkSpeed = this.maxSpeed; + this.crouchSpeed = this.maxSpeed * 0.5; - this.walkSpeed = this.maxSpeed; - this.crouchSpeed = this.maxSpeed * 0.5; + // internal animation parameters - // internal animation parameters + this.activeAnimation = null; + this.oldAnimation = null; - this.activeAnimation = null; - this.oldAnimation = null; + // API - // API + } - this.enableShadows = function ( enable ) { + enableShadows( enable ) { - for ( var i = 0; i < this.meshes.length; i ++ ) { + for ( let i = 0; i < this.meshes.length; i ++ ) { this.meshes[ i ].castShadow = enable; this.meshes[ i ].receiveShadow = enable; } - }; + } - this.setVisible = function ( enable ) { + setVisible( enable ) { - for ( var i = 0; i < this.meshes.length; i ++ ) { + for ( let i = 0; i < this.meshes.length; i ++ ) { this.meshes[ i ].visible = enable; this.meshes[ i ].visible = enable; } - }; - + } - this.shareParts = function ( original ) { + shareParts( original ) { this.animations = original.animations; this.walkSpeed = original.walkSpeed; @@ -111,7 +112,7 @@ var MD2CharacterComplex = function () { // BODY - var mesh = createPart( original.meshBody.geometry, this.skinsBody[ 0 ] ); + const mesh = this._createPart( original.meshBody.geometry, this.skinsBody[ 0 ] ); mesh.scale.set( this.scale, this.scale, this.scale ); this.root.position.y = original.root.position.y; @@ -123,9 +124,9 @@ var MD2CharacterComplex = function () { // WEAPONS - for ( var i = 0; i < original.weapons.length; i ++ ) { + for ( let i = 0; i < original.weapons.length; i ++ ) { - var meshWeapon = createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] ); + const meshWeapon = this._createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] ); meshWeapon.scale.set( this.scale, this.scale, this.scale ); meshWeapon.visible = false; @@ -140,9 +141,36 @@ var MD2CharacterComplex = function () { } - }; + } + + loadParts( config ) { + + const scope = this; + + function loadTextures( baseUrl, textureUrls ) { + + const textureLoader = new TextureLoader(); + const textures = []; + + for ( let i = 0; i < textureUrls.length; i ++ ) { + + textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete ); + textures[ i ].mapping = UVMapping; + textures[ i ].name = textureUrls[ i ]; + textures[ i ].encoding = sRGBEncoding; + + } + + return textures; + + } + + function checkLoadingComplete() { - this.loadParts = function ( config ) { + scope.loadCounter -= 1; + if ( scope.loadCounter === 0 ) scope.onLoadComplete(); + + } this.animations = config.animations; this.walkSpeed = config.walkSpeed; @@ -150,8 +178,8 @@ var MD2CharacterComplex = function () { this.loadCounter = config.weapons.length * 2 + config.skins.length + 1; - var weaponsTextures = []; - for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; + const weaponsTextures = []; + for ( let i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ]; // SKINS @@ -160,16 +188,16 @@ var MD2CharacterComplex = function () { // BODY - var loader = new MD2Loader(); + const loader = new MD2Loader(); loader.load( config.baseUrl + config.body, function ( geo ) { - var boundingBox = new Box3(); + const boundingBox = new Box3(); boundingBox.setFromBufferAttribute( geo.attributes.position ); scope.root.position.y = - scope.scale * boundingBox.min.y; - var mesh = createPart( geo, scope.skinsBody[ 0 ] ); + const mesh = scope._createPart( geo, scope.skinsBody[ 0 ] ); mesh.scale.set( scope.scale, scope.scale, scope.scale ); scope.root.add( mesh ); @@ -183,11 +211,11 @@ var MD2CharacterComplex = function () { // WEAPONS - var generateCallback = function ( index, name ) { + const generateCallback = function ( index, name ) { return function ( geo ) { - var mesh = createPart( geo, scope.skinsWeapon[ index ] ); + const mesh = scope._createPart( geo, scope.skinsWeapon[ index ] ); mesh.scale.set( scope.scale, scope.scale, scope.scale ); mesh.visible = false; @@ -205,22 +233,22 @@ var MD2CharacterComplex = function () { }; - for ( var i = 0; i < config.weapons.length; i ++ ) { + for ( let i = 0; i < config.weapons.length; i ++ ) { loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) ); } - }; + } - this.setPlaybackRate = function ( rate ) { + setPlaybackRate( rate ) { if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate; if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate; - }; + } - this.setWireframe = function ( wireframeEnabled ) { + setWireframe( wireframeEnabled ) { if ( wireframeEnabled ) { @@ -234,9 +262,9 @@ var MD2CharacterComplex = function () { } - }; + } - this.setSkin = function ( index ) { + setSkin( index ) { if ( this.meshBody && this.meshBody.material.wireframe === false ) { @@ -245,13 +273,13 @@ var MD2CharacterComplex = function () { } - }; + } - this.setWeapon = function ( index ) { + setWeapon( index ) { - for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false; + for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false; - var activeWeapon = this.weapons[ index ]; + const activeWeapon = this.weapons[ index ]; if ( activeWeapon ) { @@ -267,9 +295,9 @@ var MD2CharacterComplex = function () { } - }; + } - this.setAnimation = function ( animationName ) { + setAnimation( animationName ) { if ( animationName === this.activeAnimation || ! animationName ) return; @@ -293,9 +321,9 @@ var MD2CharacterComplex = function () { } - }; + } - this.update = function ( delta ) { + update( delta ) { if ( this.controls ) this.updateMovementModel( delta ); @@ -306,11 +334,11 @@ var MD2CharacterComplex = function () { } - }; + } - this.updateAnimations = function ( delta ) { + updateAnimations( delta ) { - var mix = 1; + let mix = 1; if ( this.blendCounter > 0 ) { @@ -337,14 +365,14 @@ var MD2CharacterComplex = function () { } - }; + } - this.updateBehaviors = function () { + updateBehaviors() { - var controls = this.controls; - var animations = this.animations; + const controls = this.controls; + const animations = this.animations; - var moveAnimation, idleAnimation; + let moveAnimation, idleAnimation; // crouch vs stand @@ -446,11 +474,17 @@ var MD2CharacterComplex = function () { } - }; + } - this.updateMovementModel = function ( delta ) { + updateMovementModel( delta ) { - var controls = this.controls; + function exponentialEaseOut( k ) { + + return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1; + + } + + const controls = this.controls; // speed based on controls @@ -465,7 +499,7 @@ var MD2CharacterComplex = function () { // orientation based on controls // (don't just stand while turning) - var dir = 1; + const dir = 1; if ( controls.moveLeft ) { @@ -487,12 +521,12 @@ var MD2CharacterComplex = function () { if ( this.speed > 0 ) { - var k = exponentialEaseOut( this.speed / this.maxSpeed ); + const k = exponentialEaseOut( this.speed / this.maxSpeed ); this.speed = MathUtils.clamp( this.speed - k * delta * this.frontDecceleration, 0, this.maxSpeed ); } else { - var k = exponentialEaseOut( this.speed / this.maxReverseSpeed ); + const k = exponentialEaseOut( this.speed / this.maxReverseSpeed ); this.speed = MathUtils.clamp( this.speed + k * delta * this.backAcceleration, this.maxReverseSpeed, 0 ); } @@ -501,7 +535,7 @@ var MD2CharacterComplex = function () { // displacement - var forwardDelta = this.speed * delta; + const forwardDelta = this.speed * delta; this.root.position.x += Math.sin( this.bodyOrientation ) * forwardDelta; this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta; @@ -510,36 +544,18 @@ var MD2CharacterComplex = function () { this.root.rotation.y = this.bodyOrientation; - }; - - // internal helpers - - function loadTextures( baseUrl, textureUrls ) { - - var textureLoader = new TextureLoader(); - var textures = []; - - for ( var i = 0; i < textureUrls.length; i ++ ) { - - textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete ); - textures[ i ].mapping = UVMapping; - textures[ i ].name = textureUrls[ i ]; - textures[ i ].encoding = sRGBEncoding; - - } - - return textures; - } - function createPart( geometry, skinMap ) { + // internal - var materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } ); - var materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } ); + _createPart( geometry, skinMap ) { + + const materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } ); + const materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } ); // - var mesh = new MorphBlendMesh( geometry, materialTexture ); + const mesh = new MorphBlendMesh( geometry, materialTexture ); mesh.rotation.y = - Math.PI / 2; // @@ -549,25 +565,12 @@ var MD2CharacterComplex = function () { // - mesh.autoCreateAnimations( scope.animationFPS ); + mesh.autoCreateAnimations( this.animationFPS ); return mesh; } - function checkLoadingComplete() { - - scope.loadCounter -= 1; - if ( scope.loadCounter === 0 ) scope.onLoadComplete(); - - } - - function exponentialEaseOut( k ) { - - return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1; - - } - -}; +} export { MD2CharacterComplex }; diff --git a/examples/jsm/misc/MorphAnimMesh.js b/examples/jsm/misc/MorphAnimMesh.js index 03d520bd575ffb..b14aceba698e59 100644 --- a/examples/jsm/misc/MorphAnimMesh.js +++ b/examples/jsm/misc/MorphAnimMesh.js @@ -4,71 +4,72 @@ import { Mesh } from '../../../build/three.module.js'; -var MorphAnimMesh = function ( geometry, material ) { +class MorphAnimMesh extends Mesh { - Mesh.call( this, geometry, material ); + constructor( geometry, material ) { - this.type = 'MorphAnimMesh'; + super( geometry, material ); - this.mixer = new AnimationMixer( this ); - this.activeAction = null; + this.type = 'MorphAnimMesh'; -}; + this.mixer = new AnimationMixer( this ); + this.activeAction = null; -MorphAnimMesh.prototype = Object.create( Mesh.prototype ); -MorphAnimMesh.prototype.constructor = MorphAnimMesh; + } -MorphAnimMesh.prototype.setDirectionForward = function () { + setDirectionForward() { - this.mixer.timeScale = 1.0; + this.mixer.timeScale = 1.0; -}; + } -MorphAnimMesh.prototype.setDirectionBackward = function () { + setDirectionBackward() { - this.mixer.timeScale = - 1.0; + this.mixer.timeScale = - 1.0; -}; + } -MorphAnimMesh.prototype.playAnimation = function ( label, fps ) { + playAnimation( label, fps ) { - if ( this.activeAction ) { + if ( this.activeAction ) { - this.activeAction.stop(); - this.activeAction = null; + this.activeAction.stop(); + this.activeAction = null; - } + } + + const clip = AnimationClip.findByName( this, label ); - var clip = AnimationClip.findByName( this, label ); + if ( clip ) { - if ( clip ) { + const action = this.mixer.clipAction( clip ); + action.timeScale = ( clip.tracks.length * fps ) / clip.duration; + this.activeAction = action.play(); - var action = this.mixer.clipAction( clip ); - action.timeScale = ( clip.tracks.length * fps ) / clip.duration; - this.activeAction = action.play(); + } else { - } else { + throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' ); - throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' ); + } } -}; + updateAnimation( delta ) { -MorphAnimMesh.prototype.updateAnimation = function ( delta ) { + this.mixer.update( delta ); - this.mixer.update( delta ); + } -}; + copy( source ) { -MorphAnimMesh.prototype.copy = function ( source ) { + super.copy( source ); - Mesh.prototype.copy.call( this, source ); + this.mixer = new AnimationMixer( this ); - this.mixer = new AnimationMixer( this ); + return this; - return this; + } -}; +} export { MorphAnimMesh }; diff --git a/examples/jsm/misc/MorphBlendMesh.js b/examples/jsm/misc/MorphBlendMesh.js index 90bf99df75cb1c..784b2395634172 100644 --- a/examples/jsm/misc/MorphBlendMesh.js +++ b/examples/jsm/misc/MorphBlendMesh.js @@ -3,37 +3,35 @@ import { Mesh } from '../../../build/three.module.js'; -var MorphBlendMesh = function ( geometry, material ) { +class MorphBlendMesh extends Mesh { - Mesh.call( this, geometry, material ); + constructor( geometry, material ) { - this.animationsMap = {}; - this.animationsList = []; + super( geometry, material ); - // prepare default animation - // (all frames played together in 1 second) + this.animationsMap = {}; + this.animationsList = []; - var numFrames = Object.keys( this.morphTargetDictionary ).length; + // prepare default animation + // (all frames played together in 1 second) - var name = '__default'; + const numFrames = Object.keys( this.morphTargetDictionary ).length; - var startFrame = 0; - var endFrame = numFrames - 1; + const name = '__default'; - var fps = numFrames / 1; + const startFrame = 0; + const endFrame = numFrames - 1; - this.createAnimation( name, startFrame, endFrame, fps ); - this.setAnimationWeight( name, 1 ); + const fps = numFrames / 1; -}; + this.createAnimation( name, startFrame, endFrame, fps ); + this.setAnimationWeight( name, 1 ); -MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { - - constructor: MorphBlendMesh, + } - createAnimation: function ( name, start, end, fps ) { + createAnimation( name, start, end, fps ) { - var animation = { + const animation = { start: start, end: end, @@ -60,27 +58,29 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { this.animationsMap[ name ] = animation; this.animationsList.push( animation ); - }, + } + + autoCreateAnimations( fps ) { - autoCreateAnimations: function ( fps ) { + const pattern = /([a-z]+)_?(\d+)/i; - var pattern = /([a-z]+)_?(\d+)/i; + let firstAnimation; - var firstAnimation, frameRanges = {}; + const frameRanges = {}; - var i = 0; + let i = 0; - for ( var key in this.morphTargetDictionary ) { + for ( const key in this.morphTargetDictionary ) { - var chunks = key.match( pattern ); + const chunks = key.match( pattern ); if ( chunks && chunks.length > 1 ) { - var name = chunks[ 1 ]; + const name = chunks[ 1 ]; if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity }; - var range = frameRanges[ name ]; + const range = frameRanges[ name ]; if ( i < range.start ) range.start = i; if ( i > range.end ) range.end = i; @@ -93,20 +93,20 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - for ( var name in frameRanges ) { + for ( const name in frameRanges ) { - var range = frameRanges[ name ]; + const range = frameRanges[ name ]; this.createAnimation( name, range.start, range.end, fps ); } this.firstAnimation = firstAnimation; - }, + } - setAnimationDirectionForward: function ( name ) { + setAnimationDirectionForward( name ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -115,11 +115,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - setAnimationDirectionBackward: function ( name ) { + setAnimationDirectionBackward( name ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -128,11 +128,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - setAnimationFPS: function ( name, fps ) { + setAnimationFPS( name, fps ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -141,11 +141,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - setAnimationDuration: function ( name, duration ) { + setAnimationDuration( name, duration ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -154,11 +154,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - setAnimationWeight: function ( name, weight ) { + setAnimationWeight( name, weight ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -166,11 +166,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - setAnimationTime: function ( name, time ) { + setAnimationTime( name, time ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -178,13 +178,13 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - getAnimationTime: function ( name ) { + getAnimationTime( name ) { - var time = 0; + let time = 0; - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -194,13 +194,13 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { return time; - }, + } - getAnimationDuration: function ( name ) { + getAnimationDuration( name ) { - var duration = - 1; + let duration = - 1; - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -210,11 +210,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { return duration; - }, + } - playAnimation: function ( name ) { + playAnimation( name ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -227,11 +227,11 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - stopAnimation: function ( name ) { + stopAnimation( name ) { - var animation = this.animationsMap[ name ]; + const animation = this.animationsMap[ name ]; if ( animation ) { @@ -239,17 +239,17 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - }, + } - update: function ( delta ) { + update( delta ) { - for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) { + for ( let i = 0, il = this.animationsList.length; i < il; i ++ ) { - var animation = this.animationsList[ i ]; + const animation = this.animationsList[ i ]; if ( ! animation.active ) continue; - var frameTime = animation.duration / animation.length; + const frameTime = animation.duration / animation.length; animation.time += animation.direction * delta; @@ -283,8 +283,8 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - var keyframe = animation.start + MathUtils.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 ); - var weight = animation.weight; + const keyframe = animation.start + MathUtils.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 ); + const weight = animation.weight; if ( keyframe !== animation.currentFrame ) { @@ -298,7 +298,7 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } - var mix = ( animation.time % frameTime ) / frameTime; + let mix = ( animation.time % frameTime ) / frameTime; if ( animation.directionBackwards ) mix = 1 - mix; @@ -317,6 +317,6 @@ MorphBlendMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { } -} ); +} export { MorphBlendMesh }; diff --git a/examples/jsm/misc/RollerCoaster.js b/examples/jsm/misc/RollerCoaster.js index 897bf810b62857..42288083e60b69 100644 --- a/examples/jsm/misc/RollerCoaster.js +++ b/examples/jsm/misc/RollerCoaster.js @@ -6,545 +6,555 @@ import { Vector3 } from '../../../build/three.module.js'; -var RollerCoasterGeometry = function ( curve, divisions ) { +class RollerCoasterGeometry extends BufferGeometry { - BufferGeometry.call( this ); + constructor( curve, divisions ) { - var vertices = []; - var normals = []; - var colors = []; + super(); - var color1 = [ 1, 1, 1 ]; - var color2 = [ 1, 1, 0 ]; + const vertices = []; + const normals = []; + const colors = []; - var up = new Vector3( 0, 1, 0 ); - var forward = new Vector3(); - var right = new Vector3(); + const color1 = [ 1, 1, 1 ]; + const color2 = [ 1, 1, 0 ]; - var quaternion = new Quaternion(); - var prevQuaternion = new Quaternion(); - prevQuaternion.setFromAxisAngle( up, Math.PI / 2 ); + const up = new Vector3( 0, 1, 0 ); + const forward = new Vector3(); + const right = new Vector3(); - var point = new Vector3(); - var prevPoint = new Vector3(); - prevPoint.copy( curve.getPointAt( 0 ) ); + const quaternion = new Quaternion(); + const prevQuaternion = new Quaternion(); + prevQuaternion.setFromAxisAngle( up, Math.PI / 2 ); - // shapes + const point = new Vector3(); + const prevPoint = new Vector3(); + prevPoint.copy( curve.getPointAt( 0 ) ); - var step = [ - new Vector3( - 0.225, 0, 0 ), - new Vector3( 0, - 0.050, 0 ), - new Vector3( 0, - 0.175, 0 ), + // shapes - new Vector3( 0, - 0.050, 0 ), - new Vector3( 0.225, 0, 0 ), - new Vector3( 0, - 0.175, 0 ) - ]; + const step = [ + new Vector3( - 0.225, 0, 0 ), + new Vector3( 0, - 0.050, 0 ), + new Vector3( 0, - 0.175, 0 ), - var PI2 = Math.PI * 2; + new Vector3( 0, - 0.050, 0 ), + new Vector3( 0.225, 0, 0 ), + new Vector3( 0, - 0.175, 0 ) + ]; - var sides = 5; - var tube1 = []; + const PI2 = Math.PI * 2; - for ( var i = 0; i < sides; i ++ ) { + let sides = 5; + const tube1 = []; - var angle = ( i / sides ) * PI2; - tube1.push( new Vector3( Math.sin( angle ) * 0.06, Math.cos( angle ) * 0.06, 0 ) ); + for ( let i = 0; i < sides; i ++ ) { - } + const angle = ( i / sides ) * PI2; + tube1.push( new Vector3( Math.sin( angle ) * 0.06, Math.cos( angle ) * 0.06, 0 ) ); + + } - var sides = 6; - var tube2 = []; + sides = 6; + const tube2 = []; - for ( var i = 0; i < sides; i ++ ) { + for ( let i = 0; i < sides; i ++ ) { - var angle = ( i / sides ) * PI2; - tube2.push( new Vector3( Math.sin( angle ) * 0.025, Math.cos( angle ) * 0.025, 0 ) ); + const angle = ( i / sides ) * PI2; + tube2.push( new Vector3( Math.sin( angle ) * 0.025, Math.cos( angle ) * 0.025, 0 ) ); - } + } - var vector = new Vector3(); - var normal = new Vector3(); + const vector = new Vector3(); + const normal = new Vector3(); - function drawShape( shape, color ) { + function drawShape( shape, color ) { - normal.set( 0, 0, - 1 ).applyQuaternion( quaternion ); + normal.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - for ( var j = 0; j < shape.length; j ++ ) { + for ( let j = 0; j < shape.length; j ++ ) { - vector.copy( shape[ j ] ); - vector.applyQuaternion( quaternion ); - vector.add( point ); + vector.copy( shape[ j ] ); + vector.applyQuaternion( quaternion ); + vector.add( point ); - vertices.push( vector.x, vector.y, vector.z ); - normals.push( normal.x, normal.y, normal.z ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + vertices.push( vector.x, vector.y, vector.z ); + normals.push( normal.x, normal.y, normal.z ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - } + } - normal.set( 0, 0, 1 ).applyQuaternion( quaternion ); + normal.set( 0, 0, 1 ).applyQuaternion( quaternion ); - for ( var j = shape.length - 1; j >= 0; j -- ) { + for ( let j = shape.length - 1; j >= 0; j -- ) { - vector.copy( shape[ j ] ); - vector.applyQuaternion( quaternion ); - vector.add( point ); + vector.copy( shape[ j ] ); + vector.applyQuaternion( quaternion ); + vector.add( point ); - vertices.push( vector.x, vector.y, vector.z ); - normals.push( normal.x, normal.y, normal.z ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + vertices.push( vector.x, vector.y, vector.z ); + normals.push( normal.x, normal.y, normal.z ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + + } } - } + const vector1 = new Vector3(); + const vector2 = new Vector3(); + const vector3 = new Vector3(); + const vector4 = new Vector3(); - var vector1 = new Vector3(); - var vector2 = new Vector3(); - var vector3 = new Vector3(); - var vector4 = new Vector3(); + const normal1 = new Vector3(); + const normal2 = new Vector3(); + const normal3 = new Vector3(); + const normal4 = new Vector3(); - var normal1 = new Vector3(); - var normal2 = new Vector3(); - var normal3 = new Vector3(); - var normal4 = new Vector3(); + function extrudeShape( shape, offset, color ) { - function extrudeShape( shape, offset, color ) { + for ( let j = 0, jl = shape.length; j < jl; j ++ ) { - for ( var j = 0, jl = shape.length; j < jl; j ++ ) { + const point1 = shape[ j ]; + const point2 = shape[ ( j + 1 ) % jl ]; - var point1 = shape[ j ]; - var point2 = shape[ ( j + 1 ) % jl ]; + vector1.copy( point1 ).add( offset ); + vector1.applyQuaternion( quaternion ); + vector1.add( point ); - vector1.copy( point1 ).add( offset ); - vector1.applyQuaternion( quaternion ); - vector1.add( point ); + vector2.copy( point2 ).add( offset ); + vector2.applyQuaternion( quaternion ); + vector2.add( point ); - vector2.copy( point2 ).add( offset ); - vector2.applyQuaternion( quaternion ); - vector2.add( point ); + vector3.copy( point2 ).add( offset ); + vector3.applyQuaternion( prevQuaternion ); + vector3.add( prevPoint ); - vector3.copy( point2 ).add( offset ); - vector3.applyQuaternion( prevQuaternion ); - vector3.add( prevPoint ); + vector4.copy( point1 ).add( offset ); + vector4.applyQuaternion( prevQuaternion ); + vector4.add( prevPoint ); - vector4.copy( point1 ).add( offset ); - vector4.applyQuaternion( prevQuaternion ); - vector4.add( prevPoint ); + vertices.push( vector1.x, vector1.y, vector1.z ); + vertices.push( vector2.x, vector2.y, vector2.z ); + vertices.push( vector4.x, vector4.y, vector4.z ); - vertices.push( vector1.x, vector1.y, vector1.z ); - vertices.push( vector2.x, vector2.y, vector2.z ); - vertices.push( vector4.x, vector4.y, vector4.z ); + vertices.push( vector2.x, vector2.y, vector2.z ); + vertices.push( vector3.x, vector3.y, vector3.z ); + vertices.push( vector4.x, vector4.y, vector4.z ); - vertices.push( vector2.x, vector2.y, vector2.z ); - vertices.push( vector3.x, vector3.y, vector3.z ); - vertices.push( vector4.x, vector4.y, vector4.z ); + // - // + normal1.copy( point1 ); + normal1.applyQuaternion( quaternion ); + normal1.normalize(); - normal1.copy( point1 ); - normal1.applyQuaternion( quaternion ); - normal1.normalize(); + normal2.copy( point2 ); + normal2.applyQuaternion( quaternion ); + normal2.normalize(); - normal2.copy( point2 ); - normal2.applyQuaternion( quaternion ); - normal2.normalize(); + normal3.copy( point2 ); + normal3.applyQuaternion( prevQuaternion ); + normal3.normalize(); - normal3.copy( point2 ); - normal3.applyQuaternion( prevQuaternion ); - normal3.normalize(); + normal4.copy( point1 ); + normal4.applyQuaternion( prevQuaternion ); + normal4.normalize(); - normal4.copy( point1 ); - normal4.applyQuaternion( prevQuaternion ); - normal4.normalize(); + normals.push( normal1.x, normal1.y, normal1.z ); + normals.push( normal2.x, normal2.y, normal2.z ); + normals.push( normal4.x, normal4.y, normal4.z ); - normals.push( normal1.x, normal1.y, normal1.z ); - normals.push( normal2.x, normal2.y, normal2.z ); - normals.push( normal4.x, normal4.y, normal4.z ); + normals.push( normal2.x, normal2.y, normal2.z ); + normals.push( normal3.x, normal3.y, normal3.z ); + normals.push( normal4.x, normal4.y, normal4.z ); - normals.push( normal2.x, normal2.y, normal2.z ); - normals.push( normal3.x, normal3.y, normal3.z ); - normals.push( normal4.x, normal4.y, normal4.z ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); - colors.push( color[ 0 ], color[ 1 ], color[ 2 ] ); + } } - } + const offset = new Vector3(); - var offset = new Vector3(); + for ( let i = 1; i <= divisions; i ++ ) { - for ( var i = 1; i <= divisions; i ++ ) { + point.copy( curve.getPointAt( i / divisions ) ); - point.copy( curve.getPointAt( i / divisions ) ); + up.set( 0, 1, 0 ); - up.set( 0, 1, 0 ); + forward.subVectors( point, prevPoint ).normalize(); + right.crossVectors( up, forward ).normalize(); + up.crossVectors( forward, right ); - forward.subVectors( point, prevPoint ).normalize(); - right.crossVectors( up, forward ).normalize(); - up.crossVectors( forward, right ); + const angle = Math.atan2( forward.x, forward.z ); - var angle = Math.atan2( forward.x, forward.z ); + quaternion.setFromAxisAngle( up, angle ); - quaternion.setFromAxisAngle( up, angle ); + if ( i % 2 === 0 ) { - if ( i % 2 === 0 ) { + drawShape( step, color2 ); - drawShape( step, color2 ); + } + + extrudeShape( tube1, offset.set( 0, - 0.125, 0 ), color2 ); + extrudeShape( tube2, offset.set( 0.2, 0, 0 ), color1 ); + extrudeShape( tube2, offset.set( - 0.2, 0, 0 ), color1 ); + + prevPoint.copy( point ); + prevQuaternion.copy( quaternion ); } - extrudeShape( tube1, offset.set( 0, - 0.125, 0 ), color2 ); - extrudeShape( tube2, offset.set( 0.2, 0, 0 ), color1 ); - extrudeShape( tube2, offset.set( - 0.2, 0, 0 ), color1 ); + // console.log( vertices.length ); - prevPoint.copy( point ); - prevQuaternion.copy( quaternion ); + this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); + this.setAttribute( 'normal', new BufferAttribute( new Float32Array( normals ), 3 ) ); + this.setAttribute( 'color', new BufferAttribute( new Float32Array( colors ), 3 ) ); } - // console.log( vertices.length ); +} - this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); - this.setAttribute( 'normal', new BufferAttribute( new Float32Array( normals ), 3 ) ); - this.setAttribute( 'color', new BufferAttribute( new Float32Array( colors ), 3 ) ); +class RollerCoasterLiftersGeometry extends BufferGeometry { -}; + constructor( curve, divisions ) { -RollerCoasterGeometry.prototype = Object.create( BufferGeometry.prototype ); + super(); -var RollerCoasterLiftersGeometry = function ( curve, divisions ) { + const vertices = []; + const normals = []; - BufferGeometry.call( this ); + const quaternion = new Quaternion(); - var vertices = []; - var normals = []; + const up = new Vector3( 0, 1, 0 ); - var quaternion = new Quaternion(); + const point = new Vector3(); + const tangent = new Vector3(); - var up = new Vector3( 0, 1, 0 ); + // shapes - var point = new Vector3(); - var tangent = new Vector3(); + const tube1 = [ + new Vector3( 0, 0.05, - 0.05 ), + new Vector3( 0, 0.05, 0.05 ), + new Vector3( 0, - 0.05, 0 ) + ]; - // shapes + const tube2 = [ + new Vector3( - 0.05, 0, 0.05 ), + new Vector3( - 0.05, 0, - 0.05 ), + new Vector3( 0.05, 0, 0 ) + ]; - var tube1 = [ - new Vector3( 0, 0.05, - 0.05 ), - new Vector3( 0, 0.05, 0.05 ), - new Vector3( 0, - 0.05, 0 ) - ]; + const tube3 = [ + new Vector3( 0.05, 0, - 0.05 ), + new Vector3( 0.05, 0, 0.05 ), + new Vector3( - 0.05, 0, 0 ) + ]; - var tube2 = [ - new Vector3( - 0.05, 0, 0.05 ), - new Vector3( - 0.05, 0, - 0.05 ), - new Vector3( 0.05, 0, 0 ) - ]; + const vector1 = new Vector3(); + const vector2 = new Vector3(); + const vector3 = new Vector3(); + const vector4 = new Vector3(); - var tube3 = [ - new Vector3( 0.05, 0, - 0.05 ), - new Vector3( 0.05, 0, 0.05 ), - new Vector3( - 0.05, 0, 0 ) - ]; + const normal1 = new Vector3(); + const normal2 = new Vector3(); + const normal3 = new Vector3(); + const normal4 = new Vector3(); - var vector1 = new Vector3(); - var vector2 = new Vector3(); - var vector3 = new Vector3(); - var vector4 = new Vector3(); + function extrudeShape( shape, fromPoint, toPoint ) { - var normal1 = new Vector3(); - var normal2 = new Vector3(); - var normal3 = new Vector3(); - var normal4 = new Vector3(); + for ( let j = 0, jl = shape.length; j < jl; j ++ ) { - function extrudeShape( shape, fromPoint, toPoint ) { + const point1 = shape[ j ]; + const point2 = shape[ ( j + 1 ) % jl ]; - for ( var j = 0, jl = shape.length; j < jl; j ++ ) { + vector1.copy( point1 ); + vector1.applyQuaternion( quaternion ); + vector1.add( fromPoint ); - var point1 = shape[ j ]; - var point2 = shape[ ( j + 1 ) % jl ]; + vector2.copy( point2 ); + vector2.applyQuaternion( quaternion ); + vector2.add( fromPoint ); - vector1.copy( point1 ); - vector1.applyQuaternion( quaternion ); - vector1.add( fromPoint ); + vector3.copy( point2 ); + vector3.applyQuaternion( quaternion ); + vector3.add( toPoint ); - vector2.copy( point2 ); - vector2.applyQuaternion( quaternion ); - vector2.add( fromPoint ); + vector4.copy( point1 ); + vector4.applyQuaternion( quaternion ); + vector4.add( toPoint ); - vector3.copy( point2 ); - vector3.applyQuaternion( quaternion ); - vector3.add( toPoint ); + vertices.push( vector1.x, vector1.y, vector1.z ); + vertices.push( vector2.x, vector2.y, vector2.z ); + vertices.push( vector4.x, vector4.y, vector4.z ); - vector4.copy( point1 ); - vector4.applyQuaternion( quaternion ); - vector4.add( toPoint ); - - vertices.push( vector1.x, vector1.y, vector1.z ); - vertices.push( vector2.x, vector2.y, vector2.z ); - vertices.push( vector4.x, vector4.y, vector4.z ); + vertices.push( vector2.x, vector2.y, vector2.z ); + vertices.push( vector3.x, vector3.y, vector3.z ); + vertices.push( vector4.x, vector4.y, vector4.z ); - vertices.push( vector2.x, vector2.y, vector2.z ); - vertices.push( vector3.x, vector3.y, vector3.z ); - vertices.push( vector4.x, vector4.y, vector4.z ); + // - // + normal1.copy( point1 ); + normal1.applyQuaternion( quaternion ); + normal1.normalize(); - normal1.copy( point1 ); - normal1.applyQuaternion( quaternion ); - normal1.normalize(); + normal2.copy( point2 ); + normal2.applyQuaternion( quaternion ); + normal2.normalize(); - normal2.copy( point2 ); - normal2.applyQuaternion( quaternion ); - normal2.normalize(); + normal3.copy( point2 ); + normal3.applyQuaternion( quaternion ); + normal3.normalize(); - normal3.copy( point2 ); - normal3.applyQuaternion( quaternion ); - normal3.normalize(); + normal4.copy( point1 ); + normal4.applyQuaternion( quaternion ); + normal4.normalize(); - normal4.copy( point1 ); - normal4.applyQuaternion( quaternion ); - normal4.normalize(); + normals.push( normal1.x, normal1.y, normal1.z ); + normals.push( normal2.x, normal2.y, normal2.z ); + normals.push( normal4.x, normal4.y, normal4.z ); - normals.push( normal1.x, normal1.y, normal1.z ); - normals.push( normal2.x, normal2.y, normal2.z ); - normals.push( normal4.x, normal4.y, normal4.z ); + normals.push( normal2.x, normal2.y, normal2.z ); + normals.push( normal3.x, normal3.y, normal3.z ); + normals.push( normal4.x, normal4.y, normal4.z ); - normals.push( normal2.x, normal2.y, normal2.z ); - normals.push( normal3.x, normal3.y, normal3.z ); - normals.push( normal4.x, normal4.y, normal4.z ); + } } - } + const fromPoint = new Vector3(); + const toPoint = new Vector3(); - var fromPoint = new Vector3(); - var toPoint = new Vector3(); + for ( let i = 1; i <= divisions; i ++ ) { - for ( var i = 1; i <= divisions; i ++ ) { + point.copy( curve.getPointAt( i / divisions ) ); + tangent.copy( curve.getTangentAt( i / divisions ) ); - point.copy( curve.getPointAt( i / divisions ) ); - tangent.copy( curve.getTangentAt( i / divisions ) ); + const angle = Math.atan2( tangent.x, tangent.z ); - var angle = Math.atan2( tangent.x, tangent.z ); + quaternion.setFromAxisAngle( up, angle ); - quaternion.setFromAxisAngle( up, angle ); + // - // + if ( point.y > 10 ) { - if ( point.y > 10 ) { + fromPoint.set( - 0.75, - 0.35, 0 ); + fromPoint.applyQuaternion( quaternion ); + fromPoint.add( point ); - fromPoint.set( - 0.75, - 0.35, 0 ); - fromPoint.applyQuaternion( quaternion ); - fromPoint.add( point ); + toPoint.set( 0.75, - 0.35, 0 ); + toPoint.applyQuaternion( quaternion ); + toPoint.add( point ); - toPoint.set( 0.75, - 0.35, 0 ); - toPoint.applyQuaternion( quaternion ); - toPoint.add( point ); + extrudeShape( tube1, fromPoint, toPoint ); - extrudeShape( tube1, fromPoint, toPoint ); + fromPoint.set( - 0.7, - 0.3, 0 ); + fromPoint.applyQuaternion( quaternion ); + fromPoint.add( point ); - fromPoint.set( - 0.7, - 0.3, 0 ); - fromPoint.applyQuaternion( quaternion ); - fromPoint.add( point ); + toPoint.set( - 0.7, - point.y, 0 ); + toPoint.applyQuaternion( quaternion ); + toPoint.add( point ); - toPoint.set( - 0.7, - point.y, 0 ); - toPoint.applyQuaternion( quaternion ); - toPoint.add( point ); + extrudeShape( tube2, fromPoint, toPoint ); - extrudeShape( tube2, fromPoint, toPoint ); + fromPoint.set( 0.7, - 0.3, 0 ); + fromPoint.applyQuaternion( quaternion ); + fromPoint.add( point ); - fromPoint.set( 0.7, - 0.3, 0 ); - fromPoint.applyQuaternion( quaternion ); - fromPoint.add( point ); + toPoint.set( 0.7, - point.y, 0 ); + toPoint.applyQuaternion( quaternion ); + toPoint.add( point ); - toPoint.set( 0.7, - point.y, 0 ); - toPoint.applyQuaternion( quaternion ); - toPoint.add( point ); + extrudeShape( tube3, fromPoint, toPoint ); - extrudeShape( tube3, fromPoint, toPoint ); + } else { - } else { + fromPoint.set( 0, - 0.2, 0 ); + fromPoint.applyQuaternion( quaternion ); + fromPoint.add( point ); - fromPoint.set( 0, - 0.2, 0 ); - fromPoint.applyQuaternion( quaternion ); - fromPoint.add( point ); + toPoint.set( 0, - point.y, 0 ); + toPoint.applyQuaternion( quaternion ); + toPoint.add( point ); - toPoint.set( 0, - point.y, 0 ); - toPoint.applyQuaternion( quaternion ); - toPoint.add( point ); + extrudeShape( tube3, fromPoint, toPoint ); - extrudeShape( tube3, fromPoint, toPoint ); + } } + this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); + this.setAttribute( 'normal', new BufferAttribute( new Float32Array( normals ), 3 ) ); + } - this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); - this.setAttribute( 'normal', new BufferAttribute( new Float32Array( normals ), 3 ) ); +} -}; +class RollerCoasterShadowGeometry extends BufferGeometry { -RollerCoasterLiftersGeometry.prototype = Object.create( BufferGeometry.prototype ); + constructor( curve, divisions ) { -var RollerCoasterShadowGeometry = function ( curve, divisions ) { + super(); - BufferGeometry.call( this ); + const vertices = []; - var vertices = []; + const up = new Vector3( 0, 1, 0 ); + const forward = new Vector3(); - var up = new Vector3( 0, 1, 0 ); - var forward = new Vector3(); + const quaternion = new Quaternion(); + const prevQuaternion = new Quaternion(); + prevQuaternion.setFromAxisAngle( up, Math.PI / 2 ); - var quaternion = new Quaternion(); - var prevQuaternion = new Quaternion(); - prevQuaternion.setFromAxisAngle( up, Math.PI / 2 ); + const point = new Vector3(); - var point = new Vector3(); + const prevPoint = new Vector3(); + prevPoint.copy( curve.getPointAt( 0 ) ); + prevPoint.y = 0; - var prevPoint = new Vector3(); - prevPoint.copy( curve.getPointAt( 0 ) ); - prevPoint.y = 0; + const vector1 = new Vector3(); + const vector2 = new Vector3(); + const vector3 = new Vector3(); + const vector4 = new Vector3(); - var vector1 = new Vector3(); - var vector2 = new Vector3(); - var vector3 = new Vector3(); - var vector4 = new Vector3(); + for ( let i = 1; i <= divisions; i ++ ) { - for ( var i = 1; i <= divisions; i ++ ) { + point.copy( curve.getPointAt( i / divisions ) ); + point.y = 0; - point.copy( curve.getPointAt( i / divisions ) ); - point.y = 0; + forward.subVectors( point, prevPoint ); - forward.subVectors( point, prevPoint ); + const angle = Math.atan2( forward.x, forward.z ); - var angle = Math.atan2( forward.x, forward.z ); + quaternion.setFromAxisAngle( up, angle ); - quaternion.setFromAxisAngle( up, angle ); + vector1.set( - 0.3, 0, 0 ); + vector1.applyQuaternion( quaternion ); + vector1.add( point ); - vector1.set( - 0.3, 0, 0 ); - vector1.applyQuaternion( quaternion ); - vector1.add( point ); + vector2.set( 0.3, 0, 0 ); + vector2.applyQuaternion( quaternion ); + vector2.add( point ); - vector2.set( 0.3, 0, 0 ); - vector2.applyQuaternion( quaternion ); - vector2.add( point ); + vector3.set( 0.3, 0, 0 ); + vector3.applyQuaternion( prevQuaternion ); + vector3.add( prevPoint ); - vector3.set( 0.3, 0, 0 ); - vector3.applyQuaternion( prevQuaternion ); - vector3.add( prevPoint ); + vector4.set( - 0.3, 0, 0 ); + vector4.applyQuaternion( prevQuaternion ); + vector4.add( prevPoint ); - vector4.set( - 0.3, 0, 0 ); - vector4.applyQuaternion( prevQuaternion ); - vector4.add( prevPoint ); + vertices.push( vector1.x, vector1.y, vector1.z ); + vertices.push( vector2.x, vector2.y, vector2.z ); + vertices.push( vector4.x, vector4.y, vector4.z ); + + vertices.push( vector2.x, vector2.y, vector2.z ); + vertices.push( vector3.x, vector3.y, vector3.z ); + vertices.push( vector4.x, vector4.y, vector4.z ); - vertices.push( vector1.x, vector1.y, vector1.z ); - vertices.push( vector2.x, vector2.y, vector2.z ); - vertices.push( vector4.x, vector4.y, vector4.z ); + prevPoint.copy( point ); + prevQuaternion.copy( quaternion ); - vertices.push( vector2.x, vector2.y, vector2.z ); - vertices.push( vector3.x, vector3.y, vector3.z ); - vertices.push( vector4.x, vector4.y, vector4.z ); + } - prevPoint.copy( point ); - prevQuaternion.copy( quaternion ); + this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); } - this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); +} -}; +class SkyGeometry extends BufferGeometry { -RollerCoasterShadowGeometry.prototype = Object.create( BufferGeometry.prototype ); + constructor() { -var SkyGeometry = function () { + super(); - BufferGeometry.call( this ); + const vertices = []; - var vertices = []; + for ( let i = 0; i < 100; i ++ ) { - for ( var i = 0; i < 100; i ++ ) { + const x = Math.random() * 800 - 400; + const y = Math.random() * 50 + 50; + const z = Math.random() * 800 - 400; - var x = Math.random() * 800 - 400; - var y = Math.random() * 50 + 50; - var z = Math.random() * 800 - 400; + const size = Math.random() * 40 + 20; - var size = Math.random() * 40 + 20; + vertices.push( x - size, y, z - size ); + vertices.push( x + size, y, z - size ); + vertices.push( x - size, y, z + size ); - vertices.push( x - size, y, z - size ); - vertices.push( x + size, y, z - size ); - vertices.push( x - size, y, z + size ); + vertices.push( x + size, y, z - size ); + vertices.push( x + size, y, z + size ); + vertices.push( x - size, y, z + size ); - vertices.push( x + size, y, z - size ); - vertices.push( x + size, y, z + size ); - vertices.push( x - size, y, z + size ); + } - } + this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); - this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); + } -}; +} -SkyGeometry.prototype = Object.create( BufferGeometry.prototype ); +class TreesGeometry extends BufferGeometry { -var TreesGeometry = function ( landscape ) { + constructor( landscape ) { - BufferGeometry.call( this ); + super(); - var vertices = []; - var colors = []; + const vertices = []; + const colors = []; - var raycaster = new Raycaster(); - raycaster.ray.direction.set( 0, - 1, 0 ); + const raycaster = new Raycaster(); + raycaster.ray.direction.set( 0, - 1, 0 ); - for ( var i = 0; i < 2000; i ++ ) { + for ( let i = 0; i < 2000; i ++ ) { - var x = Math.random() * 500 - 250; - var z = Math.random() * 500 - 250; + const x = Math.random() * 500 - 250; + const z = Math.random() * 500 - 250; - raycaster.ray.origin.set( x, 50, z ); + raycaster.ray.origin.set( x, 50, z ); - var intersections = raycaster.intersectObject( landscape ); + const intersections = raycaster.intersectObject( landscape ); - if ( intersections.length === 0 ) continue; + if ( intersections.length === 0 ) continue; - var y = intersections[ 0 ].point.y; + const y = intersections[ 0 ].point.y; - var height = Math.random() * 5 + 0.5; + const height = Math.random() * 5 + 0.5; - var angle = Math.random() * Math.PI * 2; + let angle = Math.random() * Math.PI * 2; - vertices.push( x + Math.sin( angle ), y, z + Math.cos( angle ) ); - vertices.push( x, y + height, z ); - vertices.push( x + Math.sin( angle + Math.PI ), y, z + Math.cos( angle + Math.PI ) ); + vertices.push( x + Math.sin( angle ), y, z + Math.cos( angle ) ); + vertices.push( x, y + height, z ); + vertices.push( x + Math.sin( angle + Math.PI ), y, z + Math.cos( angle + Math.PI ) ); - angle += Math.PI / 2; + angle += Math.PI / 2; - vertices.push( x + Math.sin( angle ), y, z + Math.cos( angle ) ); - vertices.push( x, y + height, z ); - vertices.push( x + Math.sin( angle + Math.PI ), y, z + Math.cos( angle + Math.PI ) ); + vertices.push( x + Math.sin( angle ), y, z + Math.cos( angle ) ); + vertices.push( x, y + height, z ); + vertices.push( x + Math.sin( angle + Math.PI ), y, z + Math.cos( angle + Math.PI ) ); - var random = Math.random() * 0.1; + const random = Math.random() * 0.1; - for ( var j = 0; j < 6; j ++ ) { + for ( let j = 0; j < 6; j ++ ) { - colors.push( 0.2 + random, 0.4 + random, 0 ); + colors.push( 0.2 + random, 0.4 + random, 0 ); - } + } - } + } - this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); - this.setAttribute( 'color', new BufferAttribute( new Float32Array( colors ), 3 ) ); + this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); + this.setAttribute( 'color', new BufferAttribute( new Float32Array( colors ), 3 ) ); -}; + } -TreesGeometry.prototype = Object.create( BufferGeometry.prototype ); +} export { RollerCoasterGeometry, RollerCoasterLiftersGeometry, RollerCoasterShadowGeometry, SkyGeometry, TreesGeometry }; diff --git a/examples/jsm/modifiers/EdgeSplitModifier.js b/examples/jsm/modifiers/EdgeSplitModifier.js index 4fadbb9ede8072..4f02c9bf3f5fcf 100644 --- a/examples/jsm/modifiers/EdgeSplitModifier.js +++ b/examples/jsm/modifiers/EdgeSplitModifier.js @@ -5,161 +5,154 @@ import { } from '../../../build/three.module.js'; import { BufferGeometryUtils } from '../utils/BufferGeometryUtils.js'; -var EdgeSplitModifier = function () { +const _A = new Vector3(); +const _B = new Vector3(); +const _C = new Vector3(); - var A = new Vector3(); - var B = new Vector3(); - var C = new Vector3(); +class EdgeSplitModifier { - var positions, normals; - var indexes; - var pointToIndexMap, splitIndexes; - let oldNormals; + modify( geometry, cutOffAngle, tryKeepNormals = true ) { + function computeNormals() { - function computeNormals() { + normals = new Float32Array( indexes.length * 3 ); - normals = new Float32Array( indexes.length * 3 ); + for ( let i = 0; i < indexes.length; i += 3 ) { - for ( var i = 0; i < indexes.length; i += 3 ) { + let index = indexes[ i ]; - var index = indexes[ i ]; + _A.set( + positions[ 3 * index ], + positions[ 3 * index + 1 ], + positions[ 3 * index + 2 ] ); - A.set( - positions[ 3 * index ], - positions[ 3 * index + 1 ], - positions[ 3 * index + 2 ] ); + index = indexes[ i + 1 ]; + _B.set( + positions[ 3 * index ], + positions[ 3 * index + 1 ], + positions[ 3 * index + 2 ] ); - index = indexes[ i + 1 ]; - B.set( - positions[ 3 * index ], - positions[ 3 * index + 1 ], - positions[ 3 * index + 2 ] ); + index = indexes[ i + 2 ]; + _C.set( + positions[ 3 * index ], + positions[ 3 * index + 1 ], + positions[ 3 * index + 2 ] ); - index = indexes[ i + 2 ]; - C.set( - positions[ 3 * index ], - positions[ 3 * index + 1 ], - positions[ 3 * index + 2 ] ); + _C.sub( _B ); + _A.sub( _B ); - C.sub( B ); - A.sub( B ); + const normal = _C.cross( _A ).normalize(); - var normal = C.cross( A ).normalize(); + for ( let j = 0; j < 3; j ++ ) { - for ( var j = 0; j < 3; j ++ ) { + normals[ 3 * ( i + j ) ] = normal.x; + normals[ 3 * ( i + j ) + 1 ] = normal.y; + normals[ 3 * ( i + j ) + 2 ] = normal.z; - normals[ 3 * ( i + j ) ] = normal.x; - normals[ 3 * ( i + j ) + 1 ] = normal.y; - normals[ 3 * ( i + j ) + 2 ] = normal.z; + } } } - } + function mapPositionsToIndexes() { - function mapPositionsToIndexes() { + pointToIndexMap = Array( positions.length / 3 ); - pointToIndexMap = Array( positions.length / 3 ); + for ( let i = 0; i < indexes.length; i ++ ) { - for ( var i = 0; i < indexes.length; i ++ ) { + const index = indexes[ i ]; - var index = indexes[ i ]; + if ( pointToIndexMap[ index ] == null ) { - if ( pointToIndexMap[ index ] == null ) { + pointToIndexMap[ index ] = []; - pointToIndexMap[ index ] = []; + } - } + pointToIndexMap[ index ].push( i ); - pointToIndexMap[ index ].push( i ); + } } - } + function edgeSplitToGroups( indexes, cutOff, firstIndex ) { - function edgeSplitToGroups( indexes, cutOff, firstIndex ) { + _A.set( normals[ 3 * firstIndex ], normals[ 3 * firstIndex + 1 ], normals[ 3 * firstIndex + 2 ] ).normalize(); - A.set( normals[ 3 * firstIndex ], normals[ 3 * firstIndex + 1 ], normals[ 3 * firstIndex + 2 ] ).normalize(); + const result = { + splitGroup: [], + currentGroup: [ firstIndex ] + }; - var result = { - splitGroup: [], - currentGroup: [ firstIndex ] - }; + for ( const j of indexes ) { - for ( var j of indexes ) { + if ( j !== firstIndex ) { - if ( j !== firstIndex ) { + _B.set( normals[ 3 * j ], normals[ 3 * j + 1 ], normals[ 3 * j + 2 ] ).normalize(); - B.set( normals[ 3 * j ], normals[ 3 * j + 1 ], normals[ 3 * j + 2 ] ).normalize(); + if ( _B.dot( _A ) < cutOff ) { - if ( B.dot( A ) < cutOff ) { + result.splitGroup.push( j ); - result.splitGroup.push( j ); + } else { - } else { + result.currentGroup.push( j ); - result.currentGroup.push( j ); + } } } - } + return result; - return result; + } - } + function edgeSplit( indexes, cutOff, original = null ) { - function edgeSplit( indexes, cutOff, original = null ) { + if ( indexes.length === 0 ) return; - if ( indexes.length === 0 ) return; + const groupResults = []; - var groupResults = []; + for ( const index of indexes ) { - for ( var index of indexes ) { + groupResults.push( edgeSplitToGroups( indexes, cutOff, index ) ); - groupResults.push( edgeSplitToGroups( indexes, cutOff, index ) ); + } - } + let result = groupResults[ 0 ]; - var result = groupResults[ 0 ]; + for ( const groupResult of groupResults ) { - for ( var groupResult of groupResults ) { + if ( groupResult.currentGroup.length > result.currentGroup.length ) { - if ( groupResult.currentGroup.length > result.currentGroup.length ) { + result = groupResult; - result = groupResult; + } } - } + if ( original != null ) { - if ( original != null ) { + splitIndexes.push( { + original: original, + indexes: result.currentGroup + } ); - splitIndexes.push( { - original: original, - indexes: result.currentGroup - } ); + } - } + if ( result.splitGroup.length ) { - if ( result.splitGroup.length ) { + edgeSplit( result.splitGroup, cutOff, original || result.currentGroup[ 0 ] ); - edgeSplit( result.splitGroup, cutOff, original || result.currentGroup[ 0 ] ); + } } - } - - - this.modify = function ( geometry, cutOffAngle, tryKeepNormals = true ) { - if ( geometry.isGeometry === true ) { console.error( 'THREE.EdgeSplitModifier no longer supports THREE.Geometry. Use BufferGeometry instead.' ); @@ -168,7 +161,7 @@ var EdgeSplitModifier = function () { } let hadNormals = false; - oldNormals = null; + let oldNormals = null; if ( geometry.attributes.normal ) { @@ -198,15 +191,18 @@ var EdgeSplitModifier = function () { } - indexes = geometry.index.array; - positions = geometry.getAttribute( 'position' ).array; + const indexes = geometry.index.array; + const positions = geometry.getAttribute( 'position' ).array; + + let normals; + let pointToIndexMap; computeNormals(); mapPositionsToIndexes(); - splitIndexes = []; + const splitIndexes = []; - for ( var vertexIndexes of pointToIndexMap ) { + for ( const vertexIndexes of pointToIndexMap ) { edgeSplit( vertexIndexes, Math.cos( cutOffAngle ) - 0.001 ); @@ -222,13 +218,13 @@ var EdgeSplitModifier = function () { } - var newIndexes = new Uint32Array( indexes.length ); + const newIndexes = new Uint32Array( indexes.length ); newIndexes.set( indexes ); - for ( var i = 0; i < splitIndexes.length; i ++ ) { + for ( let i = 0; i < splitIndexes.length; i ++ ) { - var split = splitIndexes[ i ]; - var index = indexes[ split.original ]; + const split = splitIndexes[ i ]; + const index = indexes[ split.original ]; for ( const attribute of Object.values( newAttributes ) ) { @@ -241,7 +237,7 @@ var EdgeSplitModifier = function () { } - for ( var j of split.indexes ) { + for ( const j of split.indexes ) { newIndexes[ j ] = indexes.length + i; @@ -287,8 +283,10 @@ var EdgeSplitModifier = function () { return geometry; - }; + } + +} + -}; export { EdgeSplitModifier }; diff --git a/examples/jsm/modifiers/SimplifyModifier.js b/examples/jsm/modifiers/SimplifyModifier.js index b5790e41279b81..d1a200987138bb 100644 --- a/examples/jsm/modifiers/SimplifyModifier.js +++ b/examples/jsm/modifiers/SimplifyModifier.js @@ -13,524 +13,533 @@ import { BufferGeometryUtils } from '../utils/BufferGeometryUtils.js'; * - http://www.melax.com/polychop/ */ -var SimplifyModifier = function () { +const _cb = new Vector3(), _ab = new Vector3(); - if ( BufferGeometryUtils === undefined ) { +class SimplifyModifier { - throw 'THREE.SimplifyModifier relies on BufferGeometryUtils'; + constructor() { - } + if ( BufferGeometryUtils === undefined ) { -}; + throw 'THREE.SimplifyModifier relies on BufferGeometryUtils'; -( function () { + } - var cb = new Vector3(), ab = new Vector3(); + } - function pushIfUnique( array, object ) { + modify( geometry, count ) { - if ( array.indexOf( object ) === - 1 ) array.push( object ); + if ( geometry.isGeometry === true ) { - } + console.error( 'THREE.SimplifyModifier no longer supports Geometry. Use BufferGeometry instead.' ); + return; - function removeFromArray( array, object ) { + } - var k = array.indexOf( object ); - if ( k > - 1 ) array.splice( k, 1 ); + geometry = geometry.clone(); + const attributes = geometry.attributes; - } + // this modifier can only process indexed and non-indexed geomtries with a position attribute + + for ( const name in attributes ) { - function computeEdgeCollapseCost( u, v ) { + if ( name !== 'position' ) geometry.deleteAttribute( name ); + + } - // if we collapse edge uv by moving u to v then how - // much different will the model change, i.e. the "error". + geometry = BufferGeometryUtils.mergeVertices( geometry ); - var edgelength = v.position.distanceTo( u.position ); - var curvature = 0; + // + // put data of original geometry in different data structures + // - var sideFaces = []; - var i, il = u.faces.length, face, sideFace; + const vertices = []; + const faces = []; - // find the "sides" triangles that are on the edge uv - for ( i = 0; i < il; i ++ ) { + // add vertices - face = u.faces[ i ]; + const positionAttribute = geometry.getAttribute( 'position' ); - if ( face.hasVertex( v ) ) { + for ( let i = 0; i < positionAttribute.count; i ++ ) { - sideFaces.push( face ); + const v = new Vector3().fromBufferAttribute( positionAttribute, i ); - } + const vertex = new Vertex( v, i ); + vertices.push( vertex ); } - // use the triangle facing most away from the sides - // to determine our curvature term - for ( i = 0; i < il; i ++ ) { + // add faces - var minCurvature = 1; - face = u.faces[ i ]; + let index = geometry.getIndex(); - for ( var j = 0; j < sideFaces.length; j ++ ) { + if ( index !== null ) { + + for ( let i = 0; i < index.count; i += 3 ) { - sideFace = sideFaces[ j ]; - // use dot product of face normals. - var dotProd = face.normal.dot( sideFace.normal ); - minCurvature = Math.min( minCurvature, ( 1.001 - dotProd ) / 2 ); + const a = index.getX( i ); + const b = index.getX( i + 1 ); + const c = index.getX( i + 2 ); + + const triangle = new Triangle( vertices[ a ], vertices[ b ], vertices[ c ], a, b, c ); + faces.push( triangle ); } - curvature = Math.max( curvature, minCurvature ); + } else { - } + for ( let i = 0; i < positionAttribute.count; i += 3 ) { + + const a = i; + const b = i + 1; + const c = i + 2; - // crude approach in attempt to preserve borders - // though it seems not to be totally correct - var borders = 0; - if ( sideFaces.length < 2 ) { + const triangle = new Triangle( vertices[ a ], vertices[ b ], vertices[ c ], a, b, c ); + faces.push( triangle ); - // we add some arbitrary cost for borders, - // borders += 10; - curvature = 1; + } } - var amt = edgelength * curvature + borders; + // compute all edge collapse costs - return amt; + for ( let i = 0, il = vertices.length; i < il; i ++ ) { - } + computeEdgeCostAtVertex( vertices[ i ] ); - function computeEdgeCostAtVertex( v ) { + } - // compute the edge collapse cost for all edges that start - // from vertex v. Since we are only interested in reducing - // the object by selecting the min cost edge at each step, we - // only cache the cost of the least cost edge at this vertex - // (in member variable collapse) as well as the value of the - // cost (in member variable collapseCost). + let nextVertex; - if ( v.neighbors.length === 0 ) { + let z = count; - // collapse if no neighbors. - v.collapseNeighbor = null; - v.collapseCost = - 0.01; + while ( z -- ) { - return; + nextVertex = minimumCostEdge( vertices ); - } + if ( ! nextVertex ) { - v.collapseCost = 100000; - v.collapseNeighbor = null; + console.log( 'THREE.SimplifyModifier: No next vertex' ); + break; - // search all neighboring edges for "least cost" edge - for ( var i = 0; i < v.neighbors.length; i ++ ) { + } - var collapseCost = computeEdgeCollapseCost( v, v.neighbors[ i ] ); + collapse( vertices, faces, nextVertex, nextVertex.collapseNeighbor ); - if ( ! v.collapseNeighbor ) { + } - v.collapseNeighbor = v.neighbors[ i ]; - v.collapseCost = collapseCost; - v.minCost = collapseCost; - v.totalCost = 0; - v.costCount = 0; + // - } + const simplifiedGeometry = new BufferGeometry(); + const position = []; - v.costCount ++; - v.totalCost += collapseCost; + index = []; - if ( collapseCost < v.minCost ) { + // - v.collapseNeighbor = v.neighbors[ i ]; - v.minCost = collapseCost; + for ( let i = 0; i < vertices.length; i ++ ) { - } + const vertex = vertices[ i ].position; + position.push( vertex.x, vertex.y, vertex.z ); } - // we average the cost of collapsing at this vertex - v.collapseCost = v.totalCost / v.costCount; - // v.collapseCost = v.minCost; - - } + // - function removeVertex( v, vertices ) { + for ( let i = 0; i < faces.length; i ++ ) { - console.assert( v.faces.length === 0 ); + const face = faces[ i ]; - while ( v.neighbors.length ) { + const a = vertices.indexOf( face.v1 ); + const b = vertices.indexOf( face.v2 ); + const c = vertices.indexOf( face.v3 ); - var n = v.neighbors.pop(); - removeFromArray( n.neighbors, v ); + index.push( a, b, c ); } - removeFromArray( vertices, v ); + // + + simplifiedGeometry.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); + simplifiedGeometry.setIndex( index ); + + return simplifiedGeometry; } - function removeFace( f, faces ) { +} - removeFromArray( faces, f ); +function pushIfUnique( array, object ) { - if ( f.v1 ) removeFromArray( f.v1.faces, f ); - if ( f.v2 ) removeFromArray( f.v2.faces, f ); - if ( f.v3 ) removeFromArray( f.v3.faces, f ); + if ( array.indexOf( object ) === - 1 ) array.push( object ); - // TODO optimize this! - var vs = [ f.v1, f.v2, f.v3 ]; - var v1, v2; +} - for ( var i = 0; i < 3; i ++ ) { +function removeFromArray( array, object ) { - v1 = vs[ i ]; - v2 = vs[ ( i + 1 ) % 3 ]; + var k = array.indexOf( object ); + if ( k > - 1 ) array.splice( k, 1 ); - if ( ! v1 || ! v2 ) continue; +} - v1.removeIfNonNeighbor( v2 ); - v2.removeIfNonNeighbor( v1 ); +function computeEdgeCollapseCost( u, v ) { - } + // if we collapse edge uv by moving u to v then how + // much different will the model change, i.e. the "error". - } + const edgelength = v.position.distanceTo( u.position ); + let curvature = 0; - function collapse( vertices, faces, u, v ) { // u and v are pointers to vertices of an edge + const sideFaces = []; - // Collapse the edge uv by moving vertex u onto v + // find the "sides" triangles that are on the edge uv + for ( let i = 0, il = u.faces.length; i < il; i ++ ) { - if ( ! v ) { + const face = u.faces[ i ]; - // u is a vertex all by itself so just delete it.. - removeVertex( u, vertices ); - return; + if ( face.hasVertex( v ) ) { + + sideFaces.push( face ); } - var i; - var tmpVertices = []; + } + + // use the triangle facing most away from the sides + // to determine our curvature term + for ( let i = 0, il = u.faces.length; i < il; i ++ ) { - for ( i = 0; i < u.neighbors.length; i ++ ) { + let minCurvature = 1; + const face = u.faces[ i ]; - tmpVertices.push( u.neighbors[ i ] ); + for ( let j = 0; j < sideFaces.length; j ++ ) { + + const sideFace = sideFaces[ j ]; + // use dot product of face normals. + const dotProd = face.normal.dot( sideFace.normal ); + minCurvature = Math.min( minCurvature, ( 1.001 - dotProd ) / 2 ); } + curvature = Math.max( curvature, minCurvature ); - // delete triangles on edge uv: - for ( i = u.faces.length - 1; i >= 0; i -- ) { + } - if ( u.faces[ i ].hasVertex( v ) ) { + // crude approach in attempt to preserve borders + // though it seems not to be totally correct + const borders = 0; - removeFace( u.faces[ i ], faces ); + if ( sideFaces.length < 2 ) { - } + // we add some arbitrary cost for borders, + // borders += 10; + curvature = 1; - } + } - // update remaining triangles to have v instead of u - for ( i = u.faces.length - 1; i >= 0; i -- ) { + const amt = edgelength * curvature + borders; - u.faces[ i ].replaceVertex( u, v ); + return amt; - } +} +function computeEdgeCostAtVertex( v ) { - removeVertex( u, vertices ); + // compute the edge collapse cost for all edges that start + // from vertex v. Since we are only interested in reducing + // the object by selecting the min cost edge at each step, we + // only cache the cost of the least cost edge at this vertex + // (in member variable collapse) as well as the value of the + // cost (in member variable collapseCost). - // recompute the edge collapse costs in neighborhood - for ( i = 0; i < tmpVertices.length; i ++ ) { + if ( v.neighbors.length === 0 ) { - computeEdgeCostAtVertex( tmpVertices[ i ] ); + // collapse if no neighbors. + v.collapseNeighbor = null; + v.collapseCost = - 0.01; - } + return; } + v.collapseCost = 100000; + v.collapseNeighbor = null; + // search all neighboring edges for "least cost" edge + for ( let i = 0; i < v.neighbors.length; i ++ ) { - function minimumCostEdge( vertices ) { + const collapseCost = computeEdgeCollapseCost( v, v.neighbors[ i ] ); - // O(n * n) approach. TODO optimize this + if ( ! v.collapseNeighbor ) { - var least = vertices[ 0 ]; + v.collapseNeighbor = v.neighbors[ i ]; + v.collapseCost = collapseCost; + v.minCost = collapseCost; + v.totalCost = 0; + v.costCount = 0; - for ( var i = 0; i < vertices.length; i ++ ) { + } - if ( vertices[ i ].collapseCost < least.collapseCost ) { + v.costCount ++; + v.totalCost += collapseCost; - least = vertices[ i ]; + if ( collapseCost < v.minCost ) { - } + v.collapseNeighbor = v.neighbors[ i ]; + v.minCost = collapseCost; } - return least; - } - // we use a triangle class to represent structure of face slightly differently + // we average the cost of collapsing at this vertex + v.collapseCost = v.totalCost / v.costCount; + // v.collapseCost = v.minCost; - function Triangle( v1, v2, v3, a, b, c ) { +} - this.a = a; - this.b = b; - this.c = c; +function removeVertex( v, vertices ) { - this.v1 = v1; - this.v2 = v2; - this.v3 = v3; + console.assert( v.faces.length === 0 ); - this.normal = new Vector3(); + while ( v.neighbors.length ) { - this.computeNormal(); + const n = v.neighbors.pop(); + removeFromArray( n.neighbors, v ); - v1.faces.push( this ); - v1.addUniqueNeighbor( v2 ); - v1.addUniqueNeighbor( v3 ); + } - v2.faces.push( this ); - v2.addUniqueNeighbor( v1 ); - v2.addUniqueNeighbor( v3 ); + removeFromArray( vertices, v ); +} - v3.faces.push( this ); - v3.addUniqueNeighbor( v1 ); - v3.addUniqueNeighbor( v2 ); +function removeFace( f, faces ) { - } + removeFromArray( faces, f ); - Triangle.prototype.computeNormal = function () { + if ( f.v1 ) removeFromArray( f.v1.faces, f ); + if ( f.v2 ) removeFromArray( f.v2.faces, f ); + if ( f.v3 ) removeFromArray( f.v3.faces, f ); - var vA = this.v1.position; - var vB = this.v2.position; - var vC = this.v3.position; + // TODO optimize this! + const vs = [ f.v1, f.v2, f.v3 ]; - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ).normalize(); + for ( let i = 0; i < 3; i ++ ) { - this.normal.copy( cb ); + const v1 = vs[ i ]; + const v2 = vs[ ( i + 1 ) % 3 ]; - }; + if ( ! v1 || ! v2 ) continue; - Triangle.prototype.hasVertex = function ( v ) { + v1.removeIfNonNeighbor( v2 ); + v2.removeIfNonNeighbor( v1 ); - return v === this.v1 || v === this.v2 || v === this.v3; + } - }; +} - Triangle.prototype.replaceVertex = function ( oldv, newv ) { +function collapse( vertices, faces, u, v ) { // u and v are pointers to vertices of an edge - if ( oldv === this.v1 ) this.v1 = newv; - else if ( oldv === this.v2 ) this.v2 = newv; - else if ( oldv === this.v3 ) this.v3 = newv; + // Collapse the edge uv by moving vertex u onto v - removeFromArray( oldv.faces, this ); - newv.faces.push( this ); + if ( ! v ) { + // u is a vertex all by itself so just delete it.. + removeVertex( u, vertices ); + return; - oldv.removeIfNonNeighbor( this.v1 ); - this.v1.removeIfNonNeighbor( oldv ); + } - oldv.removeIfNonNeighbor( this.v2 ); - this.v2.removeIfNonNeighbor( oldv ); + const tmpVertices = []; - oldv.removeIfNonNeighbor( this.v3 ); - this.v3.removeIfNonNeighbor( oldv ); + for ( let i = 0; i < u.neighbors.length; i ++ ) { - this.v1.addUniqueNeighbor( this.v2 ); - this.v1.addUniqueNeighbor( this.v3 ); + tmpVertices.push( u.neighbors[ i ] ); - this.v2.addUniqueNeighbor( this.v1 ); - this.v2.addUniqueNeighbor( this.v3 ); + } - this.v3.addUniqueNeighbor( this.v1 ); - this.v3.addUniqueNeighbor( this.v2 ); - this.computeNormal(); + // delete triangles on edge uv: + for ( let i = u.faces.length - 1; i >= 0; i -- ) { - }; + if ( u.faces[ i ].hasVertex( v ) ) { - function Vertex( v, id ) { + removeFace( u.faces[ i ], faces ); - this.position = v; + } - this.id = id; // old index id + } - this.faces = []; // faces vertex is connected - this.neighbors = []; // neighbouring vertices aka "adjacentVertices" + // update remaining triangles to have v instead of u + for ( let i = u.faces.length - 1; i >= 0; i -- ) { - // these will be computed in computeEdgeCostAtVertex() - this.collapseCost = 0; // cost of collapsing this vertex, the less the better. aka objdist - this.collapseNeighbor = null; // best candinate for collapsing + u.faces[ i ].replaceVertex( u, v ); } - Vertex.prototype.addUniqueNeighbor = function ( vertex ) { - pushIfUnique( this.neighbors, vertex ); + removeVertex( u, vertices ); - }; + // recompute the edge collapse costs in neighborhood + for ( let i = 0; i < tmpVertices.length; i ++ ) { - Vertex.prototype.removeIfNonNeighbor = function ( n ) { + computeEdgeCostAtVertex( tmpVertices[ i ] ); - var neighbors = this.neighbors; - var faces = this.faces; + } - var offset = neighbors.indexOf( n ); - if ( offset === - 1 ) return; - for ( var i = 0; i < faces.length; i ++ ) { +} - if ( faces[ i ].hasVertex( n ) ) return; - } - neighbors.splice( offset, 1 ); +function minimumCostEdge( vertices ) { - }; + // O(n * n) approach. TODO optimize this - SimplifyModifier.prototype.modify = function ( geometry, count ) { + let least = vertices[ 0 ]; - if ( geometry.isGeometry === true ) { + for ( let i = 0; i < vertices.length; i ++ ) { - console.error( 'THREE.SimplifyModifier no longer supports Geometry. Use BufferGeometry instead.' ); - return; + if ( vertices[ i ].collapseCost < least.collapseCost ) { + + least = vertices[ i ]; } - geometry = geometry.clone(); - var attributes = geometry.attributes; + } - // this modifier can only process indexed and non-indexed geomtries with a position attribute + return least; - for ( var name in attributes ) { +} - if ( name !== 'position' ) geometry.deleteAttribute( name ); +// we use a triangle class to represent structure of face slightly differently - } +class Triangle { - geometry = BufferGeometryUtils.mergeVertices( geometry ); + constructor( v1, v2, v3, a, b, c ) { - // - // put data of original geometry in different data structures - // + this.a = a; + this.b = b; + this.c = c; - var vertices = []; - var faces = []; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; - // add vertices + this.normal = new Vector3(); - var positionAttribute = geometry.getAttribute( 'position' ); + this.computeNormal(); - for ( var i = 0; i < positionAttribute.count; i ++ ) { + v1.faces.push( this ); + v1.addUniqueNeighbor( v2 ); + v1.addUniqueNeighbor( v3 ); - var v = new Vector3().fromBufferAttribute( positionAttribute, i ); + v2.faces.push( this ); + v2.addUniqueNeighbor( v1 ); + v2.addUniqueNeighbor( v3 ); - var vertex = new Vertex( v, i ); - vertices.push( vertex ); - } + v3.faces.push( this ); + v3.addUniqueNeighbor( v1 ); + v3.addUniqueNeighbor( v2 ); - // add faces + } - var index = geometry.getIndex(); + computeNormal() { - if ( index !== null ) { + const vA = this.v1.position; + const vB = this.v2.position; + const vC = this.v3.position; - for ( var i = 0; i < index.count; i += 3 ) { + _cb.subVectors( vC, vB ); + _ab.subVectors( vA, vB ); + _cb.cross( _ab ).normalize(); - var a = index.getX( i ); - var b = index.getX( i + 1 ); - var c = index.getX( i + 2 ); + this.normal.copy( _cb ); - var triangle = new Triangle( vertices[ a ], vertices[ b ], vertices[ c ], a, b, c ); - faces.push( triangle ); + } - } + hasVertex( v ) { - } else { + return v === this.v1 || v === this.v2 || v === this.v3; - for ( var i = 0; i < positionAttribute.count; i += 3 ) { + } - var a = i; - var b = i + 1; - var c = i + 2; + replaceVertex( oldv, newv ) { - var triangle = new Triangle( vertices[ a ], vertices[ b ], vertices[ c ], a, b, c ); - faces.push( triangle ); + if ( oldv === this.v1 ) this.v1 = newv; + else if ( oldv === this.v2 ) this.v2 = newv; + else if ( oldv === this.v3 ) this.v3 = newv; - } + removeFromArray( oldv.faces, this ); + newv.faces.push( this ); - } - // compute all edge collapse costs + oldv.removeIfNonNeighbor( this.v1 ); + this.v1.removeIfNonNeighbor( oldv ); - for ( var i = 0, il = vertices.length; i < il; i ++ ) { + oldv.removeIfNonNeighbor( this.v2 ); + this.v2.removeIfNonNeighbor( oldv ); - computeEdgeCostAtVertex( vertices[ i ] ); + oldv.removeIfNonNeighbor( this.v3 ); + this.v3.removeIfNonNeighbor( oldv ); - } + this.v1.addUniqueNeighbor( this.v2 ); + this.v1.addUniqueNeighbor( this.v3 ); - var nextVertex; + this.v2.addUniqueNeighbor( this.v1 ); + this.v2.addUniqueNeighbor( this.v3 ); - var z = count; + this.v3.addUniqueNeighbor( this.v1 ); + this.v3.addUniqueNeighbor( this.v2 ); - while ( z -- ) { + this.computeNormal(); - nextVertex = minimumCostEdge( vertices ); + } - if ( ! nextVertex ) { +} - console.log( 'THREE.SimplifyModifier: No next vertex' ); - break; +class Vertex { - } + constructor( v, id ) { - collapse( vertices, faces, nextVertex, nextVertex.collapseNeighbor ); - - } + this.position = v; - // + this.id = id; // old index id - var simplifiedGeometry = new BufferGeometry(); - var position = []; - var index = []; + this.faces = []; // faces vertex is connected + this.neighbors = []; // neighbouring vertices aka "adjacentVertices" - // + // these will be computed in computeEdgeCostAtVertex() + this.collapseCost = 0; // cost of collapsing this vertex, the less the better. aka objdist + this.collapseNeighbor = null; // best candinate for collapsing - for ( var i = 0; i < vertices.length; i ++ ) { + } - var vertex = vertices[ i ].position; - position.push( vertex.x, vertex.y, vertex.z ); + addUniqueNeighbor( vertex ) { - } + pushIfUnique( this.neighbors, vertex ); - // + } - for ( var i = 0; i < faces.length; i ++ ) { + removeIfNonNeighbor( n ) { - var face = faces[ i ]; + const neighbors = this.neighbors; + const faces = this.faces; - var a = vertices.indexOf( face.v1 ); - var b = vertices.indexOf( face.v2 ); - var c = vertices.indexOf( face.v3 ); + const offset = neighbors.indexOf( n ); - index.push( a, b, c ); + if ( offset === - 1 ) return; - } + for ( let i = 0; i < faces.length; i ++ ) { - // + if ( faces[ i ].hasVertex( n ) ) return; - simplifiedGeometry.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - simplifiedGeometry.setIndex( index ); + } - return simplifiedGeometry; + neighbors.splice( offset, 1 ); - }; + } -} )(); +} export { SimplifyModifier }; diff --git a/examples/jsm/modifiers/TessellateModifier.js b/examples/jsm/modifiers/TessellateModifier.js index 396a0add9395c4..023d7e607369cb 100644 --- a/examples/jsm/modifiers/TessellateModifier.js +++ b/examples/jsm/modifiers/TessellateModifier.js @@ -10,301 +10,305 @@ import { * Break faces with edges longer than maxEdgeLength */ -var TessellateModifier = function ( maxEdgeLength = 0.1, maxIterations = 6 ) { +class TessellateModifier { - this.maxEdgeLength = maxEdgeLength; - this.maxIterations = maxIterations; + constructor( maxEdgeLength = 0.1, maxIterations = 6 ) { -}; + this.maxEdgeLength = maxEdgeLength; + this.maxIterations = maxIterations; -TessellateModifier.prototype.modify = function ( geometry ) { + } - if ( geometry.isGeometry === true ) { + modify( geometry ) { - console.error( 'THREE.TessellateModifier no longer supports Geometry. Use BufferGeometry instead.' ); - return geometry; + if ( geometry.isGeometry === true ) { - } + console.error( 'THREE.TessellateModifier no longer supports Geometry. Use BufferGeometry instead.' ); + return geometry; - if ( geometry.index !== null ) { + } - geometry = geometry.toNonIndexed(); + if ( geometry.index !== null ) { - } + geometry = geometry.toNonIndexed(); - // - - const maxIterations = this.maxIterations; - const maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength; - - const va = new Vector3(); - const vb = new Vector3(); - const vc = new Vector3(); - const vm = new Vector3(); - const vs = [ va, vb, vc, vm ]; - - const na = new Vector3(); - const nb = new Vector3(); - const nc = new Vector3(); - const nm = new Vector3(); - const ns = [ na, nb, nc, nm ]; - - const ca = new Color(); - const cb = new Color(); - const cc = new Color(); - const cm = new Color(); - const cs = [ ca, cb, cc, cm ]; - - const ua = new Vector2(); - const ub = new Vector2(); - const uc = new Vector2(); - const um = new Vector2(); - const us = [ ua, ub, uc, um ]; - - const u2a = new Vector2(); - const u2b = new Vector2(); - const u2c = new Vector2(); - const u2m = new Vector2(); - const u2s = [ u2a, u2b, u2c, u2m ]; - - const attributes = geometry.attributes; - const hasNormals = attributes.normal !== undefined; - const hasColors = attributes.color !== undefined; - const hasUVs = attributes.uv !== undefined; - const hasUV2s = attributes.uv2 !== undefined; - - let positions = attributes.position.array; - let normals = hasNormals ? attributes.normal.array : null; - let colors = hasColors ? attributes.color.array : null; - let uvs = hasUVs ? attributes.uv.array : null; - let uv2s = hasUV2s ? attributes.uv2.array : null; - - let positions2 = positions; - let normals2 = normals; - let colors2 = colors; - let uvs2 = uvs; - let uv2s2 = uv2s; - - let iteration = 0; - let tessellating = true; - - function addTriangle( a, b, c ) { - - const v1 = vs[ a ]; - const v2 = vs[ b ]; - const v3 = vs[ c ]; - - positions2.push( v1.x, v1.y, v1.z ); - positions2.push( v2.x, v2.y, v2.z ); - positions2.push( v3.x, v3.y, v3.z ); + } - if ( hasNormals ) { + // + + const maxIterations = this.maxIterations; + const maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength; + + const va = new Vector3(); + const vb = new Vector3(); + const vc = new Vector3(); + const vm = new Vector3(); + const vs = [ va, vb, vc, vm ]; + + const na = new Vector3(); + const nb = new Vector3(); + const nc = new Vector3(); + const nm = new Vector3(); + const ns = [ na, nb, nc, nm ]; + + const ca = new Color(); + const cb = new Color(); + const cc = new Color(); + const cm = new Color(); + const cs = [ ca, cb, cc, cm ]; + + const ua = new Vector2(); + const ub = new Vector2(); + const uc = new Vector2(); + const um = new Vector2(); + const us = [ ua, ub, uc, um ]; + + const u2a = new Vector2(); + const u2b = new Vector2(); + const u2c = new Vector2(); + const u2m = new Vector2(); + const u2s = [ u2a, u2b, u2c, u2m ]; + + const attributes = geometry.attributes; + const hasNormals = attributes.normal !== undefined; + const hasColors = attributes.color !== undefined; + const hasUVs = attributes.uv !== undefined; + const hasUV2s = attributes.uv2 !== undefined; + + let positions = attributes.position.array; + let normals = hasNormals ? attributes.normal.array : null; + let colors = hasColors ? attributes.color.array : null; + let uvs = hasUVs ? attributes.uv.array : null; + let uv2s = hasUV2s ? attributes.uv2.array : null; + + let positions2 = positions; + let normals2 = normals; + let colors2 = colors; + let uvs2 = uvs; + let uv2s2 = uv2s; + + let iteration = 0; + let tessellating = true; + + function addTriangle( a, b, c ) { + + const v1 = vs[ a ]; + const v2 = vs[ b ]; + const v3 = vs[ c ]; + + positions2.push( v1.x, v1.y, v1.z ); + positions2.push( v2.x, v2.y, v2.z ); + positions2.push( v3.x, v3.y, v3.z ); - const n1 = ns[ a ]; - const n2 = ns[ b ]; - const n3 = ns[ c ]; + if ( hasNormals ) { - normals2.push( n1.x, n1.y, n1.z ); - normals2.push( n2.x, n2.y, n2.z ); - normals2.push( n3.x, n3.y, n3.z ); + const n1 = ns[ a ]; + const n2 = ns[ b ]; + const n3 = ns[ c ]; - } + normals2.push( n1.x, n1.y, n1.z ); + normals2.push( n2.x, n2.y, n2.z ); + normals2.push( n3.x, n3.y, n3.z ); - if ( hasColors ) { + } - const c1 = cs[ a ]; - const c2 = cs[ b ]; - const c3 = cs[ c ]; + if ( hasColors ) { - colors2.push( c1.x, c1.y, c1.z ); - colors2.push( c2.x, c2.y, c2.z ); - colors2.push( c3.x, c3.y, c3.z ); + const c1 = cs[ a ]; + const c2 = cs[ b ]; + const c3 = cs[ c ]; - } + colors2.push( c1.x, c1.y, c1.z ); + colors2.push( c2.x, c2.y, c2.z ); + colors2.push( c3.x, c3.y, c3.z ); - if ( hasUVs ) { + } - const u1 = us[ a ]; - const u2 = us[ b ]; - const u3 = us[ c ]; + if ( hasUVs ) { - uvs2.push( u1.x, u1.y ); - uvs2.push( u2.x, u2.y ); - uvs2.push( u3.x, u3.y ); + const u1 = us[ a ]; + const u2 = us[ b ]; + const u3 = us[ c ]; - } + uvs2.push( u1.x, u1.y ); + uvs2.push( u2.x, u2.y ); + uvs2.push( u3.x, u3.y ); - if ( hasUV2s ) { + } - const u21 = u2s[ a ]; - const u22 = u2s[ b ]; - const u23 = u2s[ c ]; + if ( hasUV2s ) { + + const u21 = u2s[ a ]; + const u22 = u2s[ b ]; + const u23 = u2s[ c ]; - uv2s2.push( u21.x, u21.y ); - uv2s2.push( u22.x, u22.y ); - uv2s2.push( u23.x, u23.y ); + uv2s2.push( u21.x, u21.y ); + uv2s2.push( u22.x, u22.y ); + uv2s2.push( u23.x, u23.y ); + + } } - } + while ( tessellating && iteration < maxIterations ) { - while ( tessellating && iteration < maxIterations ) { + iteration ++; + tessellating = false; - iteration ++; - tessellating = false; + positions = positions2; + positions2 = []; - positions = positions2; - positions2 = []; + if ( hasNormals ) { - if ( hasNormals ) { + normals = normals2; + normals2 = []; - normals = normals2; - normals2 = []; + } - } + if ( hasColors ) { - if ( hasColors ) { + colors = colors2; + colors2 = []; - colors = colors2; - colors2 = []; + } - } + if ( hasUVs ) { - if ( hasUVs ) { + uvs = uvs2; + uvs2 = []; - uvs = uvs2; - uvs2 = []; + } - } + if ( hasUV2s ) { - if ( hasUV2s ) { + uv2s = uv2s2; + uv2s2 = []; - uv2s = uv2s2; - uv2s2 = []; + } - } + for ( let i = 0, i2 = 0, il = positions.length; i < il; i += 9, i2 += 6 ) { - for ( var i = 0, i2 = 0, il = positions.length; i < il; i += 9, i2 += 6 ) { + va.fromArray( positions, i + 0 ); + vb.fromArray( positions, i + 3 ); + vc.fromArray( positions, i + 6 ); - va.fromArray( positions, i + 0 ); - vb.fromArray( positions, i + 3 ); - vc.fromArray( positions, i + 6 ); + if ( hasNormals ) { - if ( hasNormals ) { + na.fromArray( normals, i + 0 ); + nb.fromArray( normals, i + 3 ); + nc.fromArray( normals, i + 6 ); - na.fromArray( normals, i + 0 ); - nb.fromArray( normals, i + 3 ); - nc.fromArray( normals, i + 6 ); + } - } + if ( hasColors ) { - if ( hasColors ) { + ca.fromArray( colors, i + 0 ); + cb.fromArray( colors, i + 3 ); + cc.fromArray( colors, i + 6 ); - ca.fromArray( colors, i + 0 ); - cb.fromArray( colors, i + 3 ); - cc.fromArray( colors, i + 6 ); + } - } + if ( hasUVs ) { - if ( hasUVs ) { + ua.fromArray( uvs, i2 + 0 ); + ub.fromArray( uvs, i2 + 2 ); + uc.fromArray( uvs, i2 + 4 ); - ua.fromArray( uvs, i2 + 0 ); - ub.fromArray( uvs, i2 + 2 ); - uc.fromArray( uvs, i2 + 4 ); + } - } + if ( hasUV2s ) { - if ( hasUV2s ) { + u2a.fromArray( uv2s, i2 + 0 ); + u2b.fromArray( uv2s, i2 + 2 ); + u2c.fromArray( uv2s, i2 + 4 ); - u2a.fromArray( uv2s, i2 + 0 ); - u2b.fromArray( uv2s, i2 + 2 ); - u2c.fromArray( uv2s, i2 + 4 ); + } - } + const dab = va.distanceToSquared( vb ); + const dbc = vb.distanceToSquared( vc ); + const dac = va.distanceToSquared( vc ); - const dab = va.distanceToSquared( vb ); - const dbc = vb.distanceToSquared( vc ); - const dac = va.distanceToSquared( vc ); + if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) { - if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) { + tessellating = true; - tessellating = true; + if ( dab >= dbc && dab >= dac ) { - if ( dab >= dbc && dab >= dac ) { + vm.lerpVectors( va, vb, 0.5 ); + if ( hasNormals ) nm.lerpVectors( na, nb, 0.5 ); + if ( hasColors ) cm.lerpColors( ca, cb, 0.5 ); + if ( hasUVs ) um.lerpVectors( ua, ub, 0.5 ); + if ( hasUV2s ) u2m.lerpVectors( u2a, u2b, 0.5 ); - vm.lerpVectors( va, vb, 0.5 ); - if ( hasNormals ) nm.lerpVectors( na, nb, 0.5 ); - if ( hasColors ) cm.lerpColors( ca, cb, 0.5 ); - if ( hasUVs ) um.lerpVectors( ua, ub, 0.5 ); - if ( hasUV2s ) u2m.lerpVectors( u2a, u2b, 0.5 ); + addTriangle( 0, 3, 2 ); + addTriangle( 3, 1, 2 ); - addTriangle( 0, 3, 2 ); - addTriangle( 3, 1, 2 ); + } else if ( dbc >= dab && dbc >= dac ) { - } else if ( dbc >= dab && dbc >= dac ) { + vm.lerpVectors( vb, vc, 0.5 ); + if ( hasNormals ) nm.lerpVectors( nb, nc, 0.5 ); + if ( hasColors ) cm.lerpColors( cb, cc, 0.5 ); + if ( hasUVs ) um.lerpVectors( ub, uc, 0.5 ); + if ( hasUV2s ) u2m.lerpVectors( u2b, u2c, 0.5 ); - vm.lerpVectors( vb, vc, 0.5 ); - if ( hasNormals ) nm.lerpVectors( nb, nc, 0.5 ); - if ( hasColors ) cm.lerpColors( cb, cc, 0.5 ); - if ( hasUVs ) um.lerpVectors( ub, uc, 0.5 ); - if ( hasUV2s ) u2m.lerpVectors( u2b, u2c, 0.5 ); + addTriangle( 0, 1, 3 ); + addTriangle( 3, 2, 0 ); - addTriangle( 0, 1, 3 ); - addTriangle( 3, 2, 0 ); + } else { - } else { + vm.lerpVectors( va, vc, 0.5 ); + if ( hasNormals ) nm.lerpVectors( na, nc, 0.5 ); + if ( hasColors ) cm.lerpColors( ca, cc, 0.5 ); + if ( hasUVs ) um.lerpVectors( ua, uc, 0.5 ); + if ( hasUV2s ) u2m.lerpVectors( u2a, u2c, 0.5 ); - vm.lerpVectors( va, vc, 0.5 ); - if ( hasNormals ) nm.lerpVectors( na, nc, 0.5 ); - if ( hasColors ) cm.lerpColors( ca, cc, 0.5 ); - if ( hasUVs ) um.lerpVectors( ua, uc, 0.5 ); - if ( hasUV2s ) u2m.lerpVectors( u2a, u2c, 0.5 ); + addTriangle( 0, 1, 3 ); + addTriangle( 3, 1, 2 ); - addTriangle( 0, 1, 3 ); - addTriangle( 3, 1, 2 ); + } - } + } else { - } else { + addTriangle( 0, 1, 2 ); - addTriangle( 0, 1, 2 ); + } } } - } + const geometry2 = new BufferGeometry(); - const geometry2 = new BufferGeometry(); + geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); - geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); + if ( hasNormals ) { - if ( hasNormals ) { + geometry2.setAttribute( 'normal', new Float32BufferAttribute( normals2, 3 ) ); - geometry2.setAttribute( 'normal', new Float32BufferAttribute( normals2, 3 ) ); + } - } + if ( hasColors ) { - if ( hasColors ) { + geometry2.setAttribute( 'color', new Float32BufferAttribute( colors2, 3 ) ); - geometry2.setAttribute( 'color', new Float32BufferAttribute( colors2, 3 ) ); + } - } + if ( hasUVs ) { - if ( hasUVs ) { + geometry2.setAttribute( 'uv', new Float32BufferAttribute( uvs2, 2 ) ); - geometry2.setAttribute( 'uv', new Float32BufferAttribute( uvs2, 2 ) ); + } - } + if ( hasUV2s ) { + + geometry2.setAttribute( 'uv2', new Float32BufferAttribute( uv2s2, 2 ) ); - if ( hasUV2s ) { + } - geometry2.setAttribute( 'uv2', new Float32BufferAttribute( uv2s2, 2 ) ); + return geometry2; } - return geometry2; - -}; +} export { TessellateModifier }; diff --git a/examples/jsm/nodes/materials/BasicNodeMaterial.js b/examples/jsm/nodes/materials/BasicNodeMaterial.js index 7d48c429259f5d..6a2e4c1c138e9e 100644 --- a/examples/jsm/nodes/materials/BasicNodeMaterial.js +++ b/examples/jsm/nodes/materials/BasicNodeMaterial.js @@ -2,18 +2,19 @@ import { BasicNode } from './nodes/BasicNode.js'; import { NodeMaterial } from './NodeMaterial.js'; import { NodeUtils } from '../core/NodeUtils.js'; -function BasicNodeMaterial() { +class BasicNodeMaterial extends NodeMaterial { - var node = new BasicNode(); + constructor() { - NodeMaterial.call( this, node, node ); + const node = new BasicNode(); - this.type = 'BasicNodeMaterial'; + super( node, node ); -} + this.type = 'BasicNodeMaterial'; + + } -BasicNodeMaterial.prototype = Object.create( NodeMaterial.prototype ); -BasicNodeMaterial.prototype.constructor = BasicNodeMaterial; +} NodeUtils.addShortcuts( BasicNodeMaterial.prototype, 'fragment', [ 'color', diff --git a/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js b/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js index 90f537ecbcc6f6..a6b3dbc843d098 100644 --- a/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +++ b/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js @@ -2,18 +2,19 @@ import { MeshStandardNode } from './nodes/MeshStandardNode.js'; import { NodeMaterial } from './NodeMaterial.js'; import { NodeUtils } from '../core/NodeUtils.js'; -function MeshStandardNodeMaterial() { +class MeshStandardNodeMaterial extends NodeMaterial { - var node = new MeshStandardNode(); + constructor() { - NodeMaterial.call( this, node, node ); + const node = new MeshStandardNode(); - this.type = 'MeshStandardNodeMaterial'; + super( node, node ); -} + this.type = 'MeshStandardNodeMaterial'; + + } -MeshStandardNodeMaterial.prototype = Object.create( NodeMaterial.prototype ); -MeshStandardNodeMaterial.prototype.constructor = MeshStandardNodeMaterial; +} NodeUtils.addShortcuts( MeshStandardNodeMaterial.prototype, 'properties', [ 'color', diff --git a/examples/jsm/nodes/materials/NodeMaterial.js b/examples/jsm/nodes/materials/NodeMaterial.js index bf5e1289e5899d..397609bcd99ea8 100644 --- a/examples/jsm/nodes/materials/NodeMaterial.js +++ b/examples/jsm/nodes/materials/NodeMaterial.js @@ -11,219 +11,207 @@ import { ColorNode } from '../inputs/ColorNode.js'; import { PositionNode } from '../accessors/PositionNode.js'; import { RawNode } from './nodes/RawNode.js'; -function NodeMaterial( vertex, fragment ) { +class NodeMaterial extends ShaderMaterial { - ShaderMaterial.call( this ); + constructor( vertex, fragment ) { - this.vertex = vertex || new RawNode( new PositionNode( PositionNode.PROJECTION ) ); - this.fragment = fragment || new RawNode( new ColorNode( 0xFF0000 ) ); + super(); - this.updaters = []; + this.vertex = vertex || new RawNode( new PositionNode( PositionNode.PROJECTION ) ); + this.fragment = fragment || new RawNode( new ColorNode( 0xFF0000 ) ); -} - -NodeMaterial.prototype = Object.create( ShaderMaterial.prototype ); -NodeMaterial.prototype.constructor = NodeMaterial; -NodeMaterial.prototype.type = 'NodeMaterial'; - -NodeMaterial.prototype.isNodeMaterial = true; - -Object.defineProperties( NodeMaterial.prototype, { - - properties: { - - get: function () { + this.updaters = []; - return this.fragment.properties; + this.type = 'NodeMaterial'; - } + } - }, + get properties() { - needsUpdate: { + return this.fragment.properties; - set: function ( value ) { + } - if ( value === true ) this.version ++; - this.needsCompile = value; + get needsUpdate() { - }, + return this.needsCompile; - get: function () { + } - return this.needsCompile; + set needsUpdate( value ) { - } + if ( value === true ) this.version ++; + this.needsCompile = value; } -} ); + onBeforeCompile( shader, renderer ) { -NodeMaterial.prototype.onBeforeCompile = function ( shader, renderer ) { + this.build( { renderer: renderer } ); - this.build( { renderer: renderer } ); + shader.defines = this.defines; + shader.uniforms = this.uniforms; + shader.vertexShader = this.vertexShader; + shader.fragmentShader = this.fragmentShader; - shader.defines = this.defines; - shader.uniforms = this.uniforms; - shader.vertexShader = this.vertexShader; - shader.fragmentShader = this.fragmentShader; + shader.extensionDerivatives = ( this.extensions.derivatives === true ); + shader.extensionFragDepth = ( this.extensions.fragDepth === true ); + shader.extensionDrawBuffers = ( this.extensions.drawBuffers === true ); + shader.extensionShaderTextureLOD = ( this.extensions.shaderTextureLOD === true ); - shader.extensionDerivatives = ( this.extensions.derivatives === true ); - shader.extensionFragDepth = ( this.extensions.fragDepth === true ); - shader.extensionDrawBuffers = ( this.extensions.drawBuffers === true ); - shader.extensionShaderTextureLOD = ( this.extensions.shaderTextureLOD === true ); + } -}; + customProgramCacheKey() { -NodeMaterial.prototype.customProgramCacheKey = function () { + const hash = this.getHash(); - var hash = this.getHash(); + return hash; - return hash; + } -}; + getHash() { -NodeMaterial.prototype.getHash = function () { + let hash = '{'; - var hash = '{'; + hash += '"vertex":' + this.vertex.getHash() + ','; + hash += '"fragment":' + this.fragment.getHash(); - hash += '"vertex":' + this.vertex.getHash() + ','; - hash += '"fragment":' + this.fragment.getHash(); + hash += '}'; - hash += '}'; + return hash; - return hash; + } -}; + updateFrame( frame ) { -NodeMaterial.prototype.updateFrame = function ( frame ) { + for ( let i = 0; i < this.updaters.length; ++ i ) { - for ( var i = 0; i < this.updaters.length; ++ i ) { + frame.updateNode( this.updaters[ i ] ); - frame.updateNode( this.updaters[ i ] ); + } } -}; + build( params = {} ) { -NodeMaterial.prototype.build = function ( params ) { + const builder = params.builder || new NodeBuilder(); - params = params || {}; + builder.setMaterial( this, params.renderer ); + builder.build( this.vertex, this.fragment ); - var builder = params.builder || new NodeBuilder(); + this.vertexShader = builder.getCode( 'vertex' ); + this.fragmentShader = builder.getCode( 'fragment' ); - builder.setMaterial( this, params.renderer ); - builder.build( this.vertex, this.fragment ); + this.defines = builder.defines; + this.uniforms = builder.uniforms; + this.extensions = builder.extensions; + this.updaters = builder.updaters; - this.vertexShader = builder.getCode( 'vertex' ); - this.fragmentShader = builder.getCode( 'fragment' ); + this.fog = builder.requires.fog; + this.lights = builder.requires.lights; - this.defines = builder.defines; - this.uniforms = builder.uniforms; - this.extensions = builder.extensions; - this.updaters = builder.updaters; + this.transparent = builder.requires.transparent || this.blending > NormalBlending; - this.fog = builder.requires.fog; - this.lights = builder.requires.lights; + return this; - this.transparent = builder.requires.transparent || this.blending > NormalBlending; + } - return this; + copy( source ) { -}; + const uuid = this.uuid; -NodeMaterial.prototype.copy = function ( source ) { + for ( const name in source ) { - var uuid = this.uuid; + this[ name ] = source[ name ]; - for ( var name in source ) { + } - this[ name ] = source[ name ]; + this.uuid = uuid; - } + if ( source.userData !== undefined ) { - this.uuid = uuid; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - if ( source.userData !== undefined ) { + } - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + return this; } - return this; + toJSON( meta ) { -}; + const isRootObject = ( meta === undefined || typeof meta === 'string' ); -NodeMaterial.prototype.toJSON = function ( meta ) { + if ( isRootObject ) { - var isRootObject = ( meta === undefined || typeof meta === 'string' ); + meta = { + nodes: {} + }; - if ( isRootObject ) { + } - meta = { - nodes: {} - }; + if ( meta && ! meta.materials ) meta.materials = {}; - } + if ( ! meta.materials[ this.uuid ] ) { - if ( meta && ! meta.materials ) meta.materials = {}; + const data = {}; - if ( ! meta.materials[ this.uuid ] ) { + data.uuid = this.uuid; + data.type = this.type; - var data = {}; + meta.materials[ data.uuid ] = data; - data.uuid = this.uuid; - data.type = this.type; + if ( this.name !== '' ) data.name = this.name; - meta.materials[ data.uuid ] = data; + if ( this.size !== undefined ) data.size = this.size; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; - if ( this.name !== '' ) data.name = this.name; + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.flatShading === true ) data.flatShading = this.flatShading; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; - if ( this.size !== undefined ) data.size = this.size; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; + if ( this.depthTest === false ) data.depthTest = this.depthTest; + if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.flatShading === true ) data.flatShading = this.flatShading; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; + if ( 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.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; - if ( this.depthTest === false ) data.depthTest = this.depthTest; - if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; + if ( this.dithering === true ) data.dithering = true; - if ( 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.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.dithering === true ) data.dithering = true; + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + 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.morphTargets === true ) data.morphTargets = true; + if ( this.skinning === true ) data.skinning = true; - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; + if ( this.visible === false ) data.visible = false; + if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; - if ( this.morphTargets === true ) data.morphTargets = true; - if ( this.skinning === true ) data.skinning = true; + data.fog = this.fog; + data.lights = this.lights; - if ( this.visible === false ) data.visible = false; - if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; + data.vertex = this.vertex.toJSON( meta ).uuid; + data.fragment = this.fragment.toJSON( meta ).uuid; - data.fog = this.fog; - data.lights = this.lights; + } - data.vertex = this.vertex.toJSON( meta ).uuid; - data.fragment = this.fragment.toJSON( meta ).uuid; + meta.material = this.uuid; - } + return meta; - meta.material = this.uuid; + } - return meta; +} -}; +NodeMaterial.prototype.isNodeMaterial = true; export { NodeMaterial }; diff --git a/examples/jsm/nodes/materials/PhongNodeMaterial.js b/examples/jsm/nodes/materials/PhongNodeMaterial.js index 081ecd68518332..63fe1d478afef5 100644 --- a/examples/jsm/nodes/materials/PhongNodeMaterial.js +++ b/examples/jsm/nodes/materials/PhongNodeMaterial.js @@ -2,18 +2,19 @@ import { PhongNode } from './nodes/PhongNode.js'; import { NodeMaterial } from './NodeMaterial.js'; import { NodeUtils } from '../core/NodeUtils.js'; -function PhongNodeMaterial() { +class PhongNodeMaterial extends NodeMaterial { - var node = new PhongNode(); + constructor() { - NodeMaterial.call( this, node, node ); + const node = new PhongNode(); - this.type = 'PhongNodeMaterial'; + super( node, node ); -} + this.type = 'PhongNodeMaterial'; + + } -PhongNodeMaterial.prototype = Object.create( NodeMaterial.prototype ); -PhongNodeMaterial.prototype.constructor = PhongNodeMaterial; +} NodeUtils.addShortcuts( PhongNodeMaterial.prototype, 'fragment', [ 'color', diff --git a/examples/jsm/nodes/materials/SpriteNodeMaterial.js b/examples/jsm/nodes/materials/SpriteNodeMaterial.js index 21a4f7f4f2b0e6..e77e90c9feb38d 100644 --- a/examples/jsm/nodes/materials/SpriteNodeMaterial.js +++ b/examples/jsm/nodes/materials/SpriteNodeMaterial.js @@ -2,18 +2,19 @@ import { SpriteNode } from './nodes/SpriteNode.js'; import { NodeMaterial } from './NodeMaterial.js'; import { NodeUtils } from '../core/NodeUtils.js'; -function SpriteNodeMaterial() { +class SpriteNodeMaterial extends NodeMaterial { - var node = new SpriteNode(); + constructor() { - NodeMaterial.call( this, node, node ); + const node = new SpriteNode(); - this.type = 'SpriteNodeMaterial'; + super( node, node ); -} + this.type = 'SpriteNodeMaterial'; + + } -SpriteNodeMaterial.prototype = Object.create( NodeMaterial.prototype ); -SpriteNodeMaterial.prototype.constructor = SpriteNodeMaterial; +} NodeUtils.addShortcuts( SpriteNodeMaterial.prototype, 'fragment', [ 'color', diff --git a/examples/jsm/nodes/materials/StandardNodeMaterial.js b/examples/jsm/nodes/materials/StandardNodeMaterial.js index efddf9c4f022ab..592cfe148b6228 100644 --- a/examples/jsm/nodes/materials/StandardNodeMaterial.js +++ b/examples/jsm/nodes/materials/StandardNodeMaterial.js @@ -2,18 +2,19 @@ import { StandardNode } from './nodes/StandardNode.js'; import { NodeMaterial } from './NodeMaterial.js'; import { NodeUtils } from '../core/NodeUtils.js'; -function StandardNodeMaterial() { +class StandardNodeMaterial extends NodeMaterial { - var node = new StandardNode(); + constructor() { - NodeMaterial.call( this, node, node ); + const node = new StandardNode(); - this.type = 'StandardNodeMaterial'; + super( node, node ); -} + this.type = 'StandardNodeMaterial'; + + } -StandardNodeMaterial.prototype = Object.create( NodeMaterial.prototype ); -StandardNodeMaterial.prototype.constructor = StandardNodeMaterial; +} NodeUtils.addShortcuts( StandardNodeMaterial.prototype, 'fragment', [ 'color', diff --git a/examples/jsm/nodes/postprocessing/NodePass.js b/examples/jsm/nodes/postprocessing/NodePass.js index 6f4c69bebec5c4..9fc4ebadb85183 100644 --- a/examples/jsm/nodes/postprocessing/NodePass.js +++ b/examples/jsm/nodes/postprocessing/NodePass.js @@ -4,89 +4,90 @@ import { ShaderPass } from '../../postprocessing/ShaderPass.js'; import { NodeMaterial } from '../materials/NodeMaterial.js'; import { ScreenNode } from '../inputs/ScreenNode.js'; -function NodePass() { +class NodePass extends ShaderPass { - ShaderPass.call( this ); + constructor() { - this.name = ''; - this.uuid = MathUtils.generateUUID(); + super(); - this.userData = {}; + this.name = ''; + this.uuid = MathUtils.generateUUID(); - this.textureID = 'renderTexture'; + this.userData = {}; - this.input = new ScreenNode(); + this.textureID = 'renderTexture'; - this.material = new NodeMaterial(); + this.input = new ScreenNode(); - this.needsUpdate = true; + this.material = new NodeMaterial(); -} + this.needsUpdate = true; -NodePass.prototype = Object.create( ShaderPass.prototype ); -NodePass.prototype.constructor = NodePass; + } -NodePass.prototype.render = function () { + render() { - if ( this.needsUpdate ) { + if ( this.needsUpdate ) { - this.material.dispose(); + this.material.dispose(); - this.material.fragment.value = this.input; + this.material.fragment.value = this.input; - this.needsUpdate = false; + this.needsUpdate = false; - } + } - this.uniforms = this.material.uniforms; + this.uniforms = this.material.uniforms; - ShaderPass.prototype.render.apply( this, arguments ); + super.render( ...arguments ); + + } -}; + copy( source ) { -NodePass.prototype.copy = function ( source ) { + this.input = source.input; - this.input = source.input; + return this; - return this; + } -}; + toJSON( meta ) { -NodePass.prototype.toJSON = function ( meta ) { + var isRootObject = ( meta === undefined || typeof meta === 'string' ); - var isRootObject = ( meta === undefined || typeof meta === 'string' ); + if ( isRootObject ) { - if ( isRootObject ) { + meta = { + nodes: {} + }; - meta = { - nodes: {} - }; + } - } + if ( meta && ! meta.passes ) meta.passes = {}; - if ( meta && ! meta.passes ) meta.passes = {}; + if ( ! meta.passes[ this.uuid ] ) { - if ( ! meta.passes[ this.uuid ] ) { + var data = {}; - var data = {}; + data.uuid = this.uuid; + data.type = 'NodePass'; - data.uuid = this.uuid; - data.type = 'NodePass'; + meta.passes[ this.uuid ] = data; - meta.passes[ this.uuid ] = data; + if ( this.name !== '' ) data.name = this.name; - if ( this.name !== '' ) data.name = this.name; + if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; - if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; + data.input = this.input.toJSON( meta ).uuid; - data.input = this.input.toJSON( meta ).uuid; + } - } + meta.pass = this.uuid; - meta.pass = this.uuid; + return meta; - return meta; + } -}; +} export { NodePass }; diff --git a/examples/jsm/objects/Lensflare.js b/examples/jsm/objects/Lensflare.js index 3cb7d9df1875c7..5f01d31ad8e48b 100644 --- a/examples/jsm/objects/Lensflare.js +++ b/examples/jsm/objects/Lensflare.js @@ -17,281 +17,281 @@ import { Vector4 } from '../../../build/three.module.js'; -var Lensflare = function () { +class Lensflare extends Mesh { - Mesh.call( this, Lensflare.Geometry, new MeshBasicMaterial( { opacity: 0, transparent: true } ) ); + constructor() { - this.type = 'Lensflare'; - this.frustumCulled = false; - this.renderOrder = Infinity; + super( Lensflare.Geometry, new MeshBasicMaterial( { opacity: 0, transparent: true } ) ); - // + this.type = 'Lensflare'; + this.frustumCulled = false; + this.renderOrder = Infinity; - var positionScreen = new Vector3(); - var positionView = new Vector3(); + // - // textures + const positionScreen = new Vector3(); + const positionView = new Vector3(); - var tempMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat ); - tempMap.minFilter = NearestFilter; - tempMap.magFilter = NearestFilter; - tempMap.wrapS = ClampToEdgeWrapping; - tempMap.wrapT = ClampToEdgeWrapping; + // textures - var occlusionMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat ); - occlusionMap.minFilter = NearestFilter; - occlusionMap.magFilter = NearestFilter; - occlusionMap.wrapS = ClampToEdgeWrapping; - occlusionMap.wrapT = ClampToEdgeWrapping; + const tempMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat ); + tempMap.minFilter = NearestFilter; + tempMap.magFilter = NearestFilter; + tempMap.wrapS = ClampToEdgeWrapping; + tempMap.wrapT = ClampToEdgeWrapping; - // material + const occlusionMap = new DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, RGBFormat ); + occlusionMap.minFilter = NearestFilter; + occlusionMap.magFilter = NearestFilter; + occlusionMap.wrapS = ClampToEdgeWrapping; + occlusionMap.wrapT = ClampToEdgeWrapping; - var geometry = Lensflare.Geometry; + // material - var material1a = new RawShaderMaterial( { - uniforms: { - 'scale': { value: null }, - 'screenPosition': { value: null } - }, - vertexShader: [ + const geometry = Lensflare.Geometry; - 'precision highp float;', + const material1a = new RawShaderMaterial( { + uniforms: { + 'scale': { value: null }, + 'screenPosition': { value: null } + }, + vertexShader: /* glsl */` - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', + precision highp float; - 'attribute vec3 position;', + uniform vec3 screenPosition; + uniform vec2 scale; - 'void main() {', + attribute vec3 position; - ' gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', + void main() { - '}' + gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 ); - ].join( '\n' ), - fragmentShader: [ + }`, - 'precision highp float;', + fragmentShader: /* glsl */` - 'void main() {', + precision highp float; - ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );', + void main() { - '}' + gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 ); - ].join( '\n' ), - depthTest: true, - depthWrite: false, - transparent: false - } ); + }`, + depthTest: true, + depthWrite: false, + transparent: false + } ); - var material1b = new RawShaderMaterial( { - uniforms: { - 'map': { value: tempMap }, - 'scale': { value: null }, - 'screenPosition': { value: null } - }, - vertexShader: [ + const material1b = new RawShaderMaterial( { + uniforms: { + 'map': { value: tempMap }, + 'scale': { value: null }, + 'screenPosition': { value: null } + }, + vertexShader: /* glsl */` - 'precision highp float;', + precision highp float; - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', + uniform vec3 screenPosition; + uniform vec2 scale; - 'attribute vec3 position;', - 'attribute vec2 uv;', + attribute vec3 position; + attribute vec2 uv; - 'varying vec2 vUV;', + varying vec2 vUV; - 'void main() {', + void main() { - ' vUV = uv;', + vUV = uv; - ' gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', + gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 ); - '}' + }`, - ].join( '\n' ), - fragmentShader: [ + fragmentShader: /* glsl */` - 'precision highp float;', + precision highp float; - 'uniform sampler2D map;', + uniform sampler2D map; - 'varying vec2 vUV;', + varying vec2 vUV; - 'void main() {', + void main() { - ' gl_FragColor = texture2D( map, vUV );', + gl_FragColor = texture2D( map, vUV ); - '}' + }`, + depthTest: false, + depthWrite: false, + transparent: false + } ); - ].join( '\n' ), - depthTest: false, - depthWrite: false, - transparent: false - } ); + // the following object is used for occlusionMap generation - // the following object is used for occlusionMap generation + const mesh1 = new Mesh( geometry, material1a ); - var mesh1 = new Mesh( geometry, material1a ); + // - // + const elements = []; - var elements = []; + const shader = LensflareElement.Shader; - var shader = LensflareElement.Shader; + const material2 = new RawShaderMaterial( { + uniforms: { + 'map': { value: null }, + 'occlusionMap': { value: occlusionMap }, + 'color': { value: new Color( 0xffffff ) }, + 'scale': { value: new Vector2() }, + 'screenPosition': { value: new Vector3() } + }, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + blending: AdditiveBlending, + transparent: true, + depthWrite: false + } ); - var material2 = new RawShaderMaterial( { - uniforms: { - 'map': { value: null }, - 'occlusionMap': { value: occlusionMap }, - 'color': { value: new Color( 0xffffff ) }, - 'scale': { value: new Vector2() }, - 'screenPosition': { value: new Vector3() } - }, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader, - blending: AdditiveBlending, - transparent: true, - depthWrite: false - } ); + const mesh2 = new Mesh( geometry, material2 ); - var mesh2 = new Mesh( geometry, material2 ); + this.addElement = function ( element ) { - this.addElement = function ( element ) { + elements.push( element ); - elements.push( element ); + }; - }; + // - // + const scale = new Vector2(); + const screenPositionPixels = new Vector2(); + const validArea = new Box2(); + const viewport = new Vector4(); - var scale = new Vector2(); - var screenPositionPixels = new Vector2(); - var validArea = new Box2(); - var viewport = new Vector4(); + this.onBeforeRender = function ( renderer, scene, camera ) { - this.onBeforeRender = function ( renderer, scene, camera ) { + renderer.getCurrentViewport( viewport ); - renderer.getCurrentViewport( viewport ); + const invAspect = viewport.w / viewport.z; + const halfViewportWidth = viewport.z / 2.0; + const halfViewportHeight = viewport.w / 2.0; - var invAspect = viewport.w / viewport.z; - var halfViewportWidth = viewport.z / 2.0; - var halfViewportHeight = viewport.w / 2.0; + let size = 16 / viewport.w; + scale.set( size * invAspect, size ); - var size = 16 / viewport.w; - scale.set( size * invAspect, size ); + validArea.min.set( viewport.x, viewport.y ); + validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); - validArea.min.set( viewport.x, viewport.y ); - validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); + // calculate position in screen space - // calculate position in screen space + positionView.setFromMatrixPosition( this.matrixWorld ); + positionView.applyMatrix4( camera.matrixWorldInverse ); - positionView.setFromMatrixPosition( this.matrixWorld ); - positionView.applyMatrix4( camera.matrixWorldInverse ); + if ( positionView.z > 0 ) return; // lensflare is behind the camera - if ( positionView.z > 0 ) return; // lensflare is behind the camera + positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); - positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); + // horizontal and vertical coordinate of the lower left corner of the pixels to copy - // horizontal and vertical coordinate of the lower left corner of the pixels to copy + screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8; + screenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8; - screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8; - screenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8; + // screen cull - // screen cull + if ( validArea.containsPoint( screenPositionPixels ) ) { - if ( validArea.containsPoint( screenPositionPixels ) ) { + // save current RGB to temp texture - // save current RGB to temp texture + renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); - renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); + // render pink quad - // render pink quad + let uniforms = material1a.uniforms; + uniforms[ 'scale' ].value = scale; + uniforms[ 'screenPosition' ].value = positionScreen; - var uniforms = material1a.uniforms; - uniforms[ 'scale' ].value = scale; - uniforms[ 'screenPosition' ].value = positionScreen; + renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); - renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); + // copy result to occlusionMap - // copy result to occlusionMap + renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); - renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); + // restore graphics - // restore graphics + uniforms = material1b.uniforms; + uniforms[ 'scale' ].value = scale; + uniforms[ 'screenPosition' ].value = positionScreen; - var uniforms = material1b.uniforms; - uniforms[ 'scale' ].value = scale; - uniforms[ 'screenPosition' ].value = positionScreen; + renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); - renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); + // render elements - // render elements + const vecX = - positionScreen.x * 2; + const vecY = - positionScreen.y * 2; - var vecX = - positionScreen.x * 2; - var vecY = - positionScreen.y * 2; + for ( let i = 0, l = elements.length; i < l; i ++ ) { - for ( var i = 0, l = elements.length; i < l; i ++ ) { + const element = elements[ i ]; - var element = elements[ i ]; + const uniforms = material2.uniforms; - var uniforms = material2.uniforms; + uniforms[ 'color' ].value.copy( element.color ); + uniforms[ 'map' ].value = element.texture; + uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance; + uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance; - uniforms[ 'color' ].value.copy( element.color ); - uniforms[ 'map' ].value = element.texture; - uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance; - uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance; + size = element.size / viewport.w; + const invAspect = viewport.w / viewport.z; - var size = element.size / viewport.w; - var invAspect = viewport.w / viewport.z; + uniforms[ 'scale' ].value.set( size * invAspect, size ); - uniforms[ 'scale' ].value.set( size * invAspect, size ); + material2.uniformsNeedUpdate = true; - material2.uniformsNeedUpdate = true; + renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null ); - renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null ); + } } - } + }; - }; + this.dispose = function () { - this.dispose = function () { + material1a.dispose(); + material1b.dispose(); + material2.dispose(); - material1a.dispose(); - material1b.dispose(); - material2.dispose(); + tempMap.dispose(); + occlusionMap.dispose(); - tempMap.dispose(); - occlusionMap.dispose(); + for ( let i = 0, l = elements.length; i < l; i ++ ) { - for ( var i = 0, l = elements.length; i < l; i ++ ) { + elements[ i ].texture.dispose(); - elements[ i ].texture.dispose(); + } - } + }; - }; + } -}; +} -Lensflare.prototype = Object.create( Mesh.prototype ); -Lensflare.prototype.constructor = Lensflare; Lensflare.prototype.isLensflare = true; // -var LensflareElement = function ( texture, size, distance, color ) { +class LensflareElement { - this.texture = texture; - this.size = size || 1; - this.distance = distance || 0; - this.color = color || new Color( 0xffffff ); + constructor( texture, size = 1, distance = 0, color = new Color( 0xffffff ) ) { -}; + this.texture = texture; + this.size = size; + this.distance = distance; + this.color = color; + + } + +} LensflareElement.Shader = { @@ -305,82 +305,78 @@ LensflareElement.Shader = { }, - vertexShader: [ - - 'precision highp float;', - - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', + vertexShader: /* glsl */` - 'uniform sampler2D occlusionMap;', + precision highp float; - 'attribute vec3 position;', - 'attribute vec2 uv;', + uniform vec3 screenPosition; + uniform vec2 scale; - 'varying vec2 vUV;', - 'varying float vVisibility;', + uniform sampler2D occlusionMap; - 'void main() {', + attribute vec3 position; + attribute vec2 uv; - ' vUV = uv;', + varying vec2 vUV; + varying float vVisibility; - ' vec2 pos = position.xy;', + void main() { - ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', + vUV = uv; - ' vVisibility = visibility.r / 9.0;', - ' vVisibility *= 1.0 - visibility.g / 9.0;', - ' vVisibility *= visibility.b / 9.0;', + vec2 pos = position.xy; - ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', + vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ); + visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) ); + visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) ); + visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) ); + visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) ); + visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) ); + visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) ); + visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) ); + visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) ); - '}' + vVisibility = visibility.r / 9.0; + vVisibility *= 1.0 - visibility.g / 9.0; + vVisibility *= visibility.b / 9.0; - ].join( '\n' ), + gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 ); - fragmentShader: [ + }`, - 'precision highp float;', + fragmentShader: /* glsl */` - 'uniform sampler2D map;', - 'uniform vec3 color;', + precision highp float; - 'varying vec2 vUV;', - 'varying float vVisibility;', + uniform sampler2D map; + uniform vec3 color; - 'void main() {', + varying vec2 vUV; + varying float vVisibility; - ' vec4 texture = texture2D( map, vUV );', - ' texture.a *= vVisibility;', - ' gl_FragColor = texture;', - ' gl_FragColor.rgb *= color;', + void main() { - '}' + vec4 texture = texture2D( map, vUV ); + texture.a *= vVisibility; + gl_FragColor = texture; + gl_FragColor.rgb *= color; - ].join( '\n' ) + }` }; Lensflare.Geometry = ( function () { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); - var float32Array = new Float32Array( [ + const float32Array = new Float32Array( [ - 1, - 1, 0, 0, 0, 1, - 1, 0, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 1 ] ); - var interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); + const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); diff --git a/examples/jsm/objects/LightningStorm.js b/examples/jsm/objects/LightningStorm.js index 70411a5652e1bb..ecad067a3cd473 100644 --- a/examples/jsm/objects/LightningStorm.js +++ b/examples/jsm/objects/LightningStorm.js @@ -12,7 +12,7 @@ import { LightningStrike } from '../geometries/LightningStrike.js'; * * Usage * - * var myStorm = new LightningStorm( paramsObject ); + * const myStorm = new LightningStorm( paramsObject ); * myStorm.position.set( ... ); * scene.add( myStorm ); * ... @@ -52,195 +52,194 @@ import { LightningStrike } from '../geometries/LightningStrike.js'; * */ -var LightningStorm = function ( stormParams ) { +class LightningStorm extends Object3D { - Object3D.call( this ); + constructor( stormParams = {} ) { - // Parameters + super(); - stormParams = stormParams || {}; - this.stormParams = stormParams; + // Parameters - stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0; - stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0; - stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0; - stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1; + this.stormParams = stormParams; - stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3; + stormParams.size = stormParams.size !== undefined ? stormParams.size : 1000.0; + stormParams.minHeight = stormParams.minHeight !== undefined ? stormParams.minHeight : 80.0; + stormParams.maxHeight = stormParams.maxHeight !== undefined ? stormParams.maxHeight : 100.0; + stormParams.maxSlope = stormParams.maxSlope !== undefined ? stormParams.maxSlope : 1.1; - stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0; - stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0; + stormParams.maxLightnings = stormParams.maxLightnings !== undefined ? stormParams.maxLightnings : 3; - stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0; - stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5; + stormParams.lightningMinPeriod = stormParams.lightningMinPeriod !== undefined ? stormParams.lightningMinPeriod : 3.0; + stormParams.lightningMaxPeriod = stormParams.lightningMaxPeriod !== undefined ? stormParams.lightningMaxPeriod : 7.0; - this.lightningParameters = LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters ); + stormParams.lightningMinDuration = stormParams.lightningMinDuration !== undefined ? stormParams.lightningMinDuration : 1.0; + stormParams.lightningMaxDuration = stormParams.lightningMaxDuration !== undefined ? stormParams.lightningMaxDuration : 2.5; - this.lightningParameters.isEternal = false; + this.lightningParameters = LightningStrike.copyParameters( stormParams.lightningParameters, stormParams.lightningParameters ); - this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new MeshBasicMaterial( { color: 0xB0FFFF } ); + this.lightningParameters.isEternal = false; - if ( stormParams.onRayPosition !== undefined ) { + this.lightningMaterial = stormParams.lightningMaterial !== undefined ? stormParams.lightningMaterial : new MeshBasicMaterial( { color: 0xB0FFFF } ); - this.onRayPosition = stormParams.onRayPosition; + if ( stormParams.onRayPosition !== undefined ) { - } else { + this.onRayPosition = stormParams.onRayPosition; - this.onRayPosition = function ( source, dest ) { + } else { - dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size ); + this.onRayPosition = function ( source, dest ) { - var height = MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() ); + dest.set( ( Math.random() - 0.5 ) * stormParams.size, 0, ( Math.random() - 0.5 ) * stormParams.size ); - source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest ); + const height = MathUtils.lerp( stormParams.minHeight, stormParams.maxHeight, Math.random() ); - }; + source.set( stormParams.maxSlope * ( 2 * Math.random() - 1 ), 1, stormParams.maxSlope * ( 2 * Math.random() - 1 ) ).multiplyScalar( height ).add( dest ); - } + }; - this.onLightningDown = stormParams.onLightningDown; + } - // Internal state + this.onLightningDown = stormParams.onLightningDown; - this.inited = false; - this.nextLightningTime = 0; - this.lightningsMeshes = []; - this.deadLightningsMeshes = []; + // Internal state - for ( var i = 0; i < this.stormParams.maxLightnings; i ++ ) { + this.inited = false; + this.nextLightningTime = 0; + this.lightningsMeshes = []; + this.deadLightningsMeshes = []; - var lightning = new LightningStrike( LightningStrike.copyParameters( {}, this.lightningParameters ) ); - var mesh = new Mesh( lightning, this.lightningMaterial ); - this.deadLightningsMeshes.push( mesh ); + for ( let i = 0; i < this.stormParams.maxLightnings; i ++ ) { - } + const lightning = new LightningStrike( LightningStrike.copyParameters( {}, this.lightningParameters ) ); + const mesh = new Mesh( lightning, this.lightningMaterial ); + this.deadLightningsMeshes.push( mesh ); -}; + } -LightningStorm.prototype = Object.create( Object3D.prototype ); + } -LightningStorm.prototype.constructor = LightningStorm; + update( time ) { -LightningStorm.prototype.isLightningStorm = true; + if ( ! this.inited ) { -LightningStorm.prototype.update = function ( time ) { + this.nextLightningTime = this.getNextLightningTime( time ) * Math.random(); + this.inited = true; - if ( ! this.inited ) { + } - this.nextLightningTime = this.getNextLightningTime( time ) * Math.random(); - this.inited = true; + if ( time >= this.nextLightningTime ) { - } + // Lightning creation - if ( time >= this.nextLightningTime ) { + const lightningMesh = this.deadLightningsMeshes.pop(); - // Lightning creation + if ( lightningMesh ) { - var lightningMesh = this.deadLightningsMeshes.pop(); + const lightningParams1 = LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters ); - if ( lightningMesh ) { + lightningParams1.birthTime = time; + lightningParams1.deathTime = time + MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() ); - var lightningParams1 = LightningStrike.copyParameters( lightningMesh.geometry.rayParameters, this.lightningParameters ); + this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset ); - lightningParams1.birthTime = time; - lightningParams1.deathTime = time + MathUtils.lerp( this.stormParams.lightningMinDuration, this.stormParams.lightningMaxDuration, Math.random() ); + lightningParams1.noiseSeed = Math.random(); - this.onRayPosition( lightningParams1.sourceOffset, lightningParams1.destOffset ); + this.add( lightningMesh ); - lightningParams1.noiseSeed = Math.random(); + this.lightningsMeshes.push( lightningMesh ); - this.add( lightningMesh ); + } - this.lightningsMeshes.push( lightningMesh ); + // Schedule next lightning + this.nextLightningTime = this.getNextLightningTime( time ); } - // Schedule next lightning - this.nextLightningTime = this.getNextLightningTime( time ); + let i = 0, il = this.lightningsMeshes.length; - } - - var i = 0, il = this.lightningsMeshes.length; + while ( i < il ) { - while ( i < il ) { + const mesh = this.lightningsMeshes[ i ]; - var mesh = this.lightningsMeshes[ i ]; + const lightning = mesh.geometry; - var lightning = mesh.geometry; + const prevState = lightning.state; - var prevState = lightning.state; + lightning.update( time ); - lightning.update( time ); + if ( prevState === LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) { - if ( prevState === LightningStrike.RAY_PROPAGATING && lightning.state > prevState ) { + if ( this.onLightningDown ) { - if ( this.onLightningDown ) { + this.onLightningDown( lightning ); - this.onLightningDown( lightning ); + } } - } + if ( lightning.state === LightningStrike.RAY_EXTINGUISHED ) { - if ( lightning.state === LightningStrike.RAY_EXTINGUISHED ) { + // Lightning is to be destroyed - // Lightning is to be destroyed + this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 ); - this.lightningsMeshes.splice( this.lightningsMeshes.indexOf( mesh ), 1 ); + this.deadLightningsMeshes.push( mesh ); - this.deadLightningsMeshes.push( mesh ); + this.remove( mesh ); - this.remove( mesh ); + il --; - il --; + } else { - } else { + i ++; - i ++; + } } } -}; + getNextLightningTime( currentTime ) { -LightningStorm.prototype.getNextLightningTime = function ( currentTime ) { + return currentTime + MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 ); - return currentTime + MathUtils.lerp( this.stormParams.lightningMinPeriod, this.stormParams.lightningMaxPeriod, Math.random() ) / ( this.stormParams.maxLightnings + 1 ); + } -}; + copy( source ) { -LightningStorm.prototype.copy = function ( source ) { + super.copy( source ); - Object3D.prototype.copy.call( this, source ); + this.stormParams.size = source.stormParams.size; + this.stormParams.minHeight = source.stormParams.minHeight; + this.stormParams.maxHeight = source.stormParams.maxHeight; + this.stormParams.maxSlope = source.stormParams.maxSlope; - this.stormParams.size = source.stormParams.size; - this.stormParams.minHeight = source.stormParams.minHeight; - this.stormParams.maxHeight = source.stormParams.maxHeight; - this.stormParams.maxSlope = source.stormParams.maxSlope; + this.stormParams.maxLightnings = source.stormParams.maxLightnings; - this.stormParams.maxLightnings = source.stormParams.maxLightnings; + this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod; + this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod; - this.stormParams.lightningMinPeriod = source.stormParams.lightningMinPeriod; - this.stormParams.lightningMaxPeriod = source.stormParams.lightningMaxPeriod; + this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration; + this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration; - this.stormParams.lightningMinDuration = source.stormParams.lightningMinDuration; - this.stormParams.lightningMaxDuration = source.stormParams.lightningMaxDuration; + this.lightningParameters = LightningStrike.copyParameters( {}, source.lightningParameters ); - this.lightningParameters = LightningStrike.copyParameters( {}, source.lightningParameters ); + this.lightningMaterial = source.stormParams.lightningMaterial; - this.lightningMaterial = source.stormParams.lightningMaterial; + this.onLightningDown = source.onLightningDown; - this.onLightningDown = source.onLightningDown; + return this; - return this; + } -}; + clone() { -LightningStrike.prototype.clone = function () { + return new this.constructor( this.stormParams ).copy( this ); - return new this.constructor( this.stormParams ).copy( this ); + } -}; +} + +LightningStorm.prototype.isLightningStorm = true; export { LightningStorm }; diff --git a/examples/jsm/objects/MarchingCubes.js b/examples/jsm/objects/MarchingCubes.js index 52f13b070b5655..d7cab09c73f7a6 100644 --- a/examples/jsm/objects/MarchingCubes.js +++ b/examples/jsm/objects/MarchingCubes.js @@ -10,628 +10,634 @@ import { * Port of http://webglsamples.org/blob/blob.html */ -var MarchingCubes = function ( resolution, material, enableUvs, enableColors ) { +class MarchingCubes extends ImmediateRenderObject { - ImmediateRenderObject.call( this, material ); + constructor( resolution, material, enableUvs, enableColors ) { - var scope = this; + super( material ); - // temp buffers used in polygonize + const scope = this; - var vlist = new Float32Array( 12 * 3 ); - var nlist = new Float32Array( 12 * 3 ); - var clist = new Float32Array( 12 * 3 ); + // temp buffers used in polygonize - this.enableUvs = enableUvs !== undefined ? enableUvs : false; - this.enableColors = enableColors !== undefined ? enableColors : false; + const vlist = new Float32Array( 12 * 3 ); + const nlist = new Float32Array( 12 * 3 ); + const clist = new Float32Array( 12 * 3 ); - // functions have to be object properties - // prototype functions kill performance - // (tested and it was 4x slower !!!) + this.enableUvs = enableUvs !== undefined ? enableUvs : false; + this.enableColors = enableColors !== undefined ? enableColors : false; - this.init = function ( resolution ) { + // functions have to be object properties + // prototype functions kill performance + // (tested and it was 4x slower !!!) - this.resolution = resolution; + this.init = function ( resolution ) { - // parameters + this.resolution = resolution; - this.isolation = 80.0; + // parameters - // size of field, 32 is pushing it in Javascript :) + this.isolation = 80.0; - this.size = resolution; - this.size2 = this.size * this.size; - this.size3 = this.size2 * this.size; - this.halfsize = this.size / 2.0; + // size of field, 32 is pushing it in Javascript :) - // deltas + this.size = resolution; + this.size2 = this.size * this.size; + this.size3 = this.size2 * this.size; + this.halfsize = this.size / 2.0; - this.delta = 2.0 / this.size; - this.yd = this.size; - this.zd = this.size2; + // deltas - this.field = new Float32Array( this.size3 ); - this.normal_cache = new Float32Array( this.size3 * 3 ); - this.palette = new Float32Array( this.size3 * 3 ); + this.delta = 2.0 / this.size; + this.yd = this.size; + this.zd = this.size2; - // immediate render mode simulator + this.field = new Float32Array( this.size3 ); + this.normal_cache = new Float32Array( this.size3 * 3 ); + this.palette = new Float32Array( this.size3 * 3 ); - this.maxCount = 4096; // TODO: find the fastest size for this buffer - this.count = 0; + // immediate render mode simulator - this.hasPositions = false; - this.hasNormals = false; - this.hasColors = false; - this.hasUvs = false; + this.maxCount = 4096; // TODO: find the fastest size for this buffer + this.count = 0; - this.positionArray = new Float32Array( this.maxCount * 3 ); - this.normalArray = new Float32Array( this.maxCount * 3 ); + this.hasPositions = false; + this.hasNormals = false; + this.hasColors = false; + this.hasUvs = false; - if ( this.enableUvs ) { + this.positionArray = new Float32Array( this.maxCount * 3 ); + this.normalArray = new Float32Array( this.maxCount * 3 ); - this.uvArray = new Float32Array( this.maxCount * 2 ); + if ( this.enableUvs ) { - } + this.uvArray = new Float32Array( this.maxCount * 2 ); - if ( this.enableColors ) { + } - this.colorArray = new Float32Array( this.maxCount * 3 ); + if ( this.enableColors ) { - } + this.colorArray = new Float32Array( this.maxCount * 3 ); - }; + } - /////////////////////// - // Polygonization - /////////////////////// + }; - function lerp( a, b, t ) { + /////////////////////// + // Polygonization + /////////////////////// - return a + ( b - a ) * t; + function lerp( a, b, t ) { - } + return a + ( b - a ) * t; - function VIntX( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) { + } - var mu = ( isol - valp1 ) / ( valp2 - valp1 ), - nc = scope.normal_cache; + function VIntX( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) { - vlist[ offset + 0 ] = x + mu * scope.delta; - vlist[ offset + 1 ] = y; - vlist[ offset + 2 ] = z; + const mu = ( isol - valp1 ) / ( valp2 - valp1 ), + nc = scope.normal_cache; - nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q + 3 ], mu ); - nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q + 4 ], mu ); - nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q + 5 ], mu ); + vlist[ offset + 0 ] = x + mu * scope.delta; + vlist[ offset + 1 ] = y; + vlist[ offset + 2 ] = z; - clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu ); - clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu ); - clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu ); + nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q + 3 ], mu ); + nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q + 4 ], mu ); + nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q + 5 ], mu ); - } + clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu ); + clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu ); + clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu ); - function VIntY( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) { + } - var mu = ( isol - valp1 ) / ( valp2 - valp1 ), - nc = scope.normal_cache; + function VIntY( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) { - vlist[ offset + 0 ] = x; - vlist[ offset + 1 ] = y + mu * scope.delta; - vlist[ offset + 2 ] = z; + const mu = ( isol - valp1 ) / ( valp2 - valp1 ), + nc = scope.normal_cache; - var q2 = q + scope.yd * 3; + vlist[ offset + 0 ] = x; + vlist[ offset + 1 ] = y + mu * scope.delta; + vlist[ offset + 2 ] = z; - nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu ); - nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu ); - nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu ); + const q2 = q + scope.yd * 3; - clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu ); - clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu ); - clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu ); + nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu ); + nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu ); + nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu ); - } + clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu ); + clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu ); + clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu ); + + } - function VIntZ( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) { + function VIntZ( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) { - var mu = ( isol - valp1 ) / ( valp2 - valp1 ), - nc = scope.normal_cache; + const mu = ( isol - valp1 ) / ( valp2 - valp1 ), + nc = scope.normal_cache; - vlist[ offset + 0 ] = x; - vlist[ offset + 1 ] = y; - vlist[ offset + 2 ] = z + mu * scope.delta; + vlist[ offset + 0 ] = x; + vlist[ offset + 1 ] = y; + vlist[ offset + 2 ] = z + mu * scope.delta; - var q2 = q + scope.zd * 3; + const q2 = q + scope.zd * 3; - nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu ); - nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu ); - nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu ); + nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu ); + nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu ); + nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu ); - clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu ); - clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu ); - clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu ); + clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu ); + clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu ); + clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu ); - } + } + + function compNorm( q ) { - function compNorm( q ) { + const q3 = q * 3; - var q3 = q * 3; + if ( scope.normal_cache[ q3 ] === 0.0 ) { - if ( scope.normal_cache[ q3 ] === 0.0 ) { + scope.normal_cache[ q3 + 0 ] = scope.field[ q - 1 ] - scope.field[ q + 1 ]; + scope.normal_cache[ q3 + 1 ] = + scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ]; + scope.normal_cache[ q3 + 2 ] = + scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ]; - scope.normal_cache[ q3 + 0 ] = scope.field[ q - 1 ] - scope.field[ q + 1 ]; - scope.normal_cache[ q3 + 1 ] = - scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ]; - scope.normal_cache[ q3 + 2 ] = - scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ]; + } } - } + // Returns total number of triangles. Fills triangles. + // (this is where most of time is spent - it's inner work of O(n3) loop ) + + function polygonize( fx, fy, fz, q, isol, renderCallback ) { + + // cache indices + const q1 = q + 1, + qy = q + scope.yd, + qz = q + scope.zd, + q1y = q1 + scope.yd, + q1z = q1 + scope.zd, + qyz = q + scope.yd + scope.zd, + q1yz = q1 + scope.yd + scope.zd; + + let cubeindex = 0; + const field0 = scope.field[ q ], + field1 = scope.field[ q1 ], + field2 = scope.field[ qy ], + field3 = scope.field[ q1y ], + field4 = scope.field[ qz ], + field5 = scope.field[ q1z ], + field6 = scope.field[ qyz ], + field7 = scope.field[ q1yz ]; + + if ( field0 < isol ) cubeindex |= 1; + if ( field1 < isol ) cubeindex |= 2; + if ( field2 < isol ) cubeindex |= 8; + if ( field3 < isol ) cubeindex |= 4; + if ( field4 < isol ) cubeindex |= 16; + if ( field5 < isol ) cubeindex |= 32; + if ( field6 < isol ) cubeindex |= 128; + if ( field7 < isol ) cubeindex |= 64; + + // if cube is entirely in/out of the surface - bail, nothing to draw + + const bits = edgeTable[ cubeindex ]; + if ( bits === 0 ) return 0; + + const d = scope.delta, + fx2 = fx + d, + fy2 = fy + d, + fz2 = fz + d; + + // top of the cube + + if ( bits & 1 ) { + + compNorm( q ); + compNorm( q1 ); + VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1, q, q1 ); - // Returns total number of triangles. Fills triangles. - // (this is where most of time is spent - it's inner work of O(n3) loop ) - - function polygonize( fx, fy, fz, q, isol, renderCallback ) { - - // cache indices - var q1 = q + 1, - qy = q + scope.yd, - qz = q + scope.zd, - q1y = q1 + scope.yd, - q1z = q1 + scope.zd, - qyz = q + scope.yd + scope.zd, - q1yz = q1 + scope.yd + scope.zd; - - var cubeindex = 0, - field0 = scope.field[ q ], - field1 = scope.field[ q1 ], - field2 = scope.field[ qy ], - field3 = scope.field[ q1y ], - field4 = scope.field[ qz ], - field5 = scope.field[ q1z ], - field6 = scope.field[ qyz ], - field7 = scope.field[ q1yz ]; - - if ( field0 < isol ) cubeindex |= 1; - if ( field1 < isol ) cubeindex |= 2; - if ( field2 < isol ) cubeindex |= 8; - if ( field3 < isol ) cubeindex |= 4; - if ( field4 < isol ) cubeindex |= 16; - if ( field5 < isol ) cubeindex |= 32; - if ( field6 < isol ) cubeindex |= 128; - if ( field7 < isol ) cubeindex |= 64; - - // if cube is entirely in/out of the surface - bail, nothing to draw - - var bits = edgeTable[ cubeindex ]; - if ( bits === 0 ) return 0; - - var d = scope.delta, - fx2 = fx + d, - fy2 = fy + d, - fz2 = fz + d; - - // top of the cube - - if ( bits & 1 ) { - - compNorm( q ); - compNorm( q1 ); - VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1, q, q1 ); + } - } + if ( bits & 2 ) { - if ( bits & 2 ) { + compNorm( q1 ); + compNorm( q1y ); + VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3, q1, q1y ); - compNorm( q1 ); - compNorm( q1y ); - VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3, q1, q1y ); + } - } + if ( bits & 4 ) { - if ( bits & 4 ) { + compNorm( qy ); + compNorm( q1y ); + VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3, qy, q1y ); - compNorm( qy ); - compNorm( q1y ); - VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3, qy, q1y ); + } - } + if ( bits & 8 ) { - if ( bits & 8 ) { + compNorm( q ); + compNorm( qy ); + VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2, q, qy ); - compNorm( q ); - compNorm( qy ); - VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2, q, qy ); + } - } + // bottom of the cube - // bottom of the cube + if ( bits & 16 ) { - if ( bits & 16 ) { + compNorm( qz ); + compNorm( q1z ); + VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5, qz, q1z ); - compNorm( qz ); - compNorm( q1z ); - VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5, qz, q1z ); + } - } + if ( bits & 32 ) { + + compNorm( q1z ); + compNorm( q1yz ); + VIntY( + q1z * 3, + 15, + isol, + fx2, + fy, + fz2, + field5, + field7, + q1z, + q1yz + ); - if ( bits & 32 ) { - - compNorm( q1z ); - compNorm( q1yz ); - VIntY( - q1z * 3, - 15, - isol, - fx2, - fy, - fz2, - field5, - field7, - q1z, - q1yz - ); + } - } + if ( bits & 64 ) { + + compNorm( qyz ); + compNorm( q1yz ); + VIntX( + qyz * 3, + 18, + isol, + fx, + fy2, + fz2, + field6, + field7, + qyz, + q1yz + ); - if ( bits & 64 ) { - - compNorm( qyz ); - compNorm( q1yz ); - VIntX( - qyz * 3, - 18, - isol, - fx, - fy2, - fz2, - field6, - field7, - qyz, - q1yz - ); + } - } + if ( bits & 128 ) { - if ( bits & 128 ) { + compNorm( qz ); + compNorm( qyz ); + VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6, qz, qyz ); - compNorm( qz ); - compNorm( qyz ); - VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6, qz, qyz ); + } - } + // vertical lines of the cube + if ( bits & 256 ) { - // vertical lines of the cube - if ( bits & 256 ) { + compNorm( q ); + compNorm( qz ); + VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4, q, qz ); - compNorm( q ); - compNorm( qz ); - VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4, q, qz ); + } - } + if ( bits & 512 ) { - if ( bits & 512 ) { + compNorm( q1 ); + compNorm( q1z ); + VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5, q1, q1z ); - compNorm( q1 ); - compNorm( q1z ); - VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5, q1, q1z ); + } - } + if ( bits & 1024 ) { + + compNorm( q1y ); + compNorm( q1yz ); + VIntZ( + q1y * 3, + 30, + isol, + fx2, + fy2, + fz, + field3, + field7, + q1y, + q1yz + ); - if ( bits & 1024 ) { - - compNorm( q1y ); - compNorm( q1yz ); - VIntZ( - q1y * 3, - 30, - isol, - fx2, - fy2, - fz, - field3, - field7, - q1y, - q1yz - ); + } - } + if ( bits & 2048 ) { - if ( bits & 2048 ) { + compNorm( qy ); + compNorm( qyz ); + VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6, qy, qyz ); - compNorm( qy ); - compNorm( qyz ); - VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6, qy, qyz ); + } - } + cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable - cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable + let o1, + o2, + o3, + numtris = 0, + i = 0; - var o1, - o2, - o3, - numtris = 0, - i = 0; + // here is where triangles are created - // here is where triangles are created + while ( triTable[ cubeindex + i ] != - 1 ) { - while ( triTable[ cubeindex + i ] != - 1 ) { + o1 = cubeindex + i; + o2 = o1 + 1; + o3 = o1 + 2; - o1 = cubeindex + i; - o2 = o1 + 1; - o3 = o1 + 2; + posnormtriv( + vlist, + nlist, + clist, + 3 * triTable[ o1 ], + 3 * triTable[ o2 ], + 3 * triTable[ o3 ], + renderCallback + ); - posnormtriv( - vlist, - nlist, - clist, - 3 * triTable[ o1 ], - 3 * triTable[ o2 ], - 3 * triTable[ o3 ], - renderCallback - ); + i += 3; + numtris ++; - i += 3; - numtris ++; + } + + return numtris; } - return numtris; + ///////////////////////////////////// + // Immediate render mode simulator + ///////////////////////////////////// - } + function posnormtriv( pos, norm, colors, o1, o2, o3, renderCallback ) { - ///////////////////////////////////// - // Immediate render mode simulator - ///////////////////////////////////// + const c = scope.count * 3; - function posnormtriv( pos, norm, colors, o1, o2, o3, renderCallback ) { + // positions - var c = scope.count * 3; + scope.positionArray[ c + 0 ] = pos[ o1 ]; + scope.positionArray[ c + 1 ] = pos[ o1 + 1 ]; + scope.positionArray[ c + 2 ] = pos[ o1 + 2 ]; - // positions + scope.positionArray[ c + 3 ] = pos[ o2 ]; + scope.positionArray[ c + 4 ] = pos[ o2 + 1 ]; + scope.positionArray[ c + 5 ] = pos[ o2 + 2 ]; - scope.positionArray[ c + 0 ] = pos[ o1 ]; - scope.positionArray[ c + 1 ] = pos[ o1 + 1 ]; - scope.positionArray[ c + 2 ] = pos[ o1 + 2 ]; + scope.positionArray[ c + 6 ] = pos[ o3 ]; + scope.positionArray[ c + 7 ] = pos[ o3 + 1 ]; + scope.positionArray[ c + 8 ] = pos[ o3 + 2 ]; - scope.positionArray[ c + 3 ] = pos[ o2 ]; - scope.positionArray[ c + 4 ] = pos[ o2 + 1 ]; - scope.positionArray[ c + 5 ] = pos[ o2 + 2 ]; + // normals - scope.positionArray[ c + 6 ] = pos[ o3 ]; - scope.positionArray[ c + 7 ] = pos[ o3 + 1 ]; - scope.positionArray[ c + 8 ] = pos[ o3 + 2 ]; + if ( scope.material.flatShading === true ) { - // normals + const nx = ( norm[ o1 + 0 ] + norm[ o2 + 0 ] + norm[ o3 + 0 ] ) / 3; + const ny = ( norm[ o1 + 1 ] + norm[ o2 + 1 ] + norm[ o3 + 1 ] ) / 3; + const nz = ( norm[ o1 + 2 ] + norm[ o2 + 2 ] + norm[ o3 + 2 ] ) / 3; - if ( scope.material.flatShading === true ) { + scope.normalArray[ c + 0 ] = nx; + scope.normalArray[ c + 1 ] = ny; + scope.normalArray[ c + 2 ] = nz; - var nx = ( norm[ o1 + 0 ] + norm[ o2 + 0 ] + norm[ o3 + 0 ] ) / 3; - var ny = ( norm[ o1 + 1 ] + norm[ o2 + 1 ] + norm[ o3 + 1 ] ) / 3; - var nz = ( norm[ o1 + 2 ] + norm[ o2 + 2 ] + norm[ o3 + 2 ] ) / 3; + scope.normalArray[ c + 3 ] = nx; + scope.normalArray[ c + 4 ] = ny; + scope.normalArray[ c + 5 ] = nz; - scope.normalArray[ c + 0 ] = nx; - scope.normalArray[ c + 1 ] = ny; - scope.normalArray[ c + 2 ] = nz; + scope.normalArray[ c + 6 ] = nx; + scope.normalArray[ c + 7 ] = ny; + scope.normalArray[ c + 8 ] = nz; - scope.normalArray[ c + 3 ] = nx; - scope.normalArray[ c + 4 ] = ny; - scope.normalArray[ c + 5 ] = nz; + } else { - scope.normalArray[ c + 6 ] = nx; - scope.normalArray[ c + 7 ] = ny; - scope.normalArray[ c + 8 ] = nz; + scope.normalArray[ c + 0 ] = norm[ o1 + 0 ]; + scope.normalArray[ c + 1 ] = norm[ o1 + 1 ]; + scope.normalArray[ c + 2 ] = norm[ o1 + 2 ]; - } else { + scope.normalArray[ c + 3 ] = norm[ o2 + 0 ]; + scope.normalArray[ c + 4 ] = norm[ o2 + 1 ]; + scope.normalArray[ c + 5 ] = norm[ o2 + 2 ]; - scope.normalArray[ c + 0 ] = norm[ o1 + 0 ]; - scope.normalArray[ c + 1 ] = norm[ o1 + 1 ]; - scope.normalArray[ c + 2 ] = norm[ o1 + 2 ]; + scope.normalArray[ c + 6 ] = norm[ o3 + 0 ]; + scope.normalArray[ c + 7 ] = norm[ o3 + 1 ]; + scope.normalArray[ c + 8 ] = norm[ o3 + 2 ]; - scope.normalArray[ c + 3 ] = norm[ o2 + 0 ]; - scope.normalArray[ c + 4 ] = norm[ o2 + 1 ]; - scope.normalArray[ c + 5 ] = norm[ o2 + 2 ]; + } - scope.normalArray[ c + 6 ] = norm[ o3 + 0 ]; - scope.normalArray[ c + 7 ] = norm[ o3 + 1 ]; - scope.normalArray[ c + 8 ] = norm[ o3 + 2 ]; + // uvs - } + if ( scope.enableUvs ) { - // uvs + const d = scope.count * 2; - if ( scope.enableUvs ) { + scope.uvArray[ d + 0 ] = pos[ o1 + 0 ]; + scope.uvArray[ d + 1 ] = pos[ o1 + 2 ]; - var d = scope.count * 2; + scope.uvArray[ d + 2 ] = pos[ o2 + 0 ]; + scope.uvArray[ d + 3 ] = pos[ o2 + 2 ]; - scope.uvArray[ d + 0 ] = pos[ o1 + 0 ]; - scope.uvArray[ d + 1 ] = pos[ o1 + 2 ]; + scope.uvArray[ d + 4 ] = pos[ o3 + 0 ]; + scope.uvArray[ d + 5 ] = pos[ o3 + 2 ]; - scope.uvArray[ d + 2 ] = pos[ o2 + 0 ]; - scope.uvArray[ d + 3 ] = pos[ o2 + 2 ]; + } - scope.uvArray[ d + 4 ] = pos[ o3 + 0 ]; - scope.uvArray[ d + 5 ] = pos[ o3 + 2 ]; + // colors - } + if ( scope.enableColors ) { - // colors + scope.colorArray[ c + 0 ] = colors[ o1 + 0 ]; + scope.colorArray[ c + 1 ] = colors[ o1 + 1 ]; + scope.colorArray[ c + 2 ] = colors[ o1 + 2 ]; - if ( scope.enableColors ) { + scope.colorArray[ c + 3 ] = colors[ o2 + 0 ]; + scope.colorArray[ c + 4 ] = colors[ o2 + 1 ]; + scope.colorArray[ c + 5 ] = colors[ o2 + 2 ]; - scope.colorArray[ c + 0 ] = colors[ o1 + 0 ]; - scope.colorArray[ c + 1 ] = colors[ o1 + 1 ]; - scope.colorArray[ c + 2 ] = colors[ o1 + 2 ]; + scope.colorArray[ c + 6 ] = colors[ o3 + 0 ]; + scope.colorArray[ c + 7 ] = colors[ o3 + 1 ]; + scope.colorArray[ c + 8 ] = colors[ o3 + 2 ]; - scope.colorArray[ c + 3 ] = colors[ o2 + 0 ]; - scope.colorArray[ c + 4 ] = colors[ o2 + 1 ]; - scope.colorArray[ c + 5 ] = colors[ o2 + 2 ]; + } - scope.colorArray[ c + 6 ] = colors[ o3 + 0 ]; - scope.colorArray[ c + 7 ] = colors[ o3 + 1 ]; - scope.colorArray[ c + 8 ] = colors[ o3 + 2 ]; + scope.count += 3; - } + if ( scope.count >= scope.maxCount - 3 ) { - scope.count += 3; + scope.hasPositions = true; + scope.hasNormals = true; - if ( scope.count >= scope.maxCount - 3 ) { + if ( scope.enableUvs ) { - scope.hasPositions = true; - scope.hasNormals = true; + scope.hasUvs = true; - if ( scope.enableUvs ) { + } - scope.hasUvs = true; + if ( scope.enableColors ) { - } + scope.hasColors = true; - if ( scope.enableColors ) { + } - scope.hasColors = true; + renderCallback( scope ); } - renderCallback( scope ); - } - } + this.begin = function () { - this.begin = function () { + this.count = 0; - this.count = 0; + this.hasPositions = false; + this.hasNormals = false; + this.hasUvs = false; + this.hasColors = false; - this.hasPositions = false; - this.hasNormals = false; - this.hasUvs = false; - this.hasColors = false; + }; - }; + this.end = function ( renderCallback ) { - this.end = function ( renderCallback ) { + if ( this.count === 0 ) return; - if ( this.count === 0 ) return; + for ( let i = this.count * 3; i < this.positionArray.length; i ++ ) { - for ( var i = this.count * 3; i < this.positionArray.length; i ++ ) { + this.positionArray[ i ] = 0.0; - this.positionArray[ i ] = 0.0; + } - } + this.hasPositions = true; + this.hasNormals = true; - this.hasPositions = true; - this.hasNormals = true; + if ( this.enableUvs && this.material.map ) { - if ( this.enableUvs && this.material.map ) { + this.hasUvs = true; - this.hasUvs = true; + } - } + if ( this.enableColors && this.material.vertexColors !== NoColors ) { - if ( this.enableColors && this.material.vertexColors !== NoColors ) { + this.hasColors = true; - this.hasColors = true; + } - } + renderCallback( this ); - renderCallback( this ); + }; - }; + ///////////////////////////////////// + // Metaballs + ///////////////////////////////////// - ///////////////////////////////////// - // Metaballs - ///////////////////////////////////// + // Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after + // a fixed distance, determined by strength and subtract. - // Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after - // a fixed distance, determined by strength and subtract. + this.addBall = function ( ballx, bally, ballz, strength, subtract, colors ) { - this.addBall = function ( ballx, bally, ballz, strength, subtract, colors ) { + const sign = Math.sign( strength ); + strength = Math.abs( strength ); + const userDefineColor = ! ( colors === undefined || colors === null ); + let ballColor = new Color( ballx, bally, ballz ); - var sign = Math.sign( strength ); - strength = Math.abs( strength ); - var userDefineColor = ! ( colors === undefined || colors === null ); - var ballColor = new Color( ballx, bally, ballz ); - if ( userDefineColor ) { + if ( userDefineColor ) { - try { + try { - ballColor = - colors instanceof Color - ? colors - : Array.isArray( colors ) - ? new Color( - Math.min( Math.abs( colors[ 0 ] ), 1 ), - Math.min( Math.abs( colors[ 1 ] ), 1 ), - Math.min( Math.abs( colors[ 2 ] ), 1 ) - ) - : new Color( colors ); + ballColor = + colors instanceof Color + ? colors + : Array.isArray( colors ) + ? new Color( + Math.min( Math.abs( colors[ 0 ] ), 1 ), + Math.min( Math.abs( colors[ 1 ] ), 1 ), + Math.min( Math.abs( colors[ 2 ] ), 1 ) + ) + : new Color( colors ); - } catch ( err ) { + } catch ( err ) { - ballColor = new Color( ballx, bally, ballz ); + ballColor = new Color( ballx, bally, ballz ); + + } } - } + // Let's solve the equation to find the radius: + // 1.0 / (0.000001 + radius^2) * strength - subtract = 0 + // strength / (radius^2) = subtract + // strength = subtract * radius^2 + // radius^2 = strength / subtract + // radius = sqrt(strength / subtract) + + const radius = this.size * Math.sqrt( strength / subtract ), + zs = ballz * this.size, + ys = bally * this.size, + xs = ballx * this.size; + + let min_z = Math.floor( zs - radius ); + if ( min_z < 1 ) min_z = 1; + let max_z = Math.floor( zs + radius ); + if ( max_z > this.size - 1 ) max_z = this.size - 1; + let min_y = Math.floor( ys - radius ); + if ( min_y < 1 ) min_y = 1; + let max_y = Math.floor( ys + radius ); + if ( max_y > this.size - 1 ) max_y = this.size - 1; + let min_x = Math.floor( xs - radius ); + if ( min_x < 1 ) min_x = 1; + let max_x = Math.floor( xs + radius ); + if ( max_x > this.size - 1 ) max_x = this.size - 1; + + // Don't polygonize in the outer layer because normals aren't + // well-defined there. + + let x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val; + + for ( z = min_z; z < max_z; z ++ ) { + + z_offset = this.size2 * z; + fz = z / this.size - ballz; + fz2 = fz * fz; + + for ( y = min_y; y < max_y; y ++ ) { + + y_offset = z_offset + this.size * y; + fy = y / this.size - bally; + fy2 = fy * fy; + + for ( x = min_x; x < max_x; x ++ ) { + + fx = x / this.size - ballx; + val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract; + if ( val > 0.0 ) { + + this.field[ y_offset + x ] += val * sign; + + // optimization + // http://www.geisswerks.com/ryan/BLOBS/blobs.html + const ratio = + Math.sqrt( ( x - xs ) * ( x - xs ) + ( y - ys ) * ( y - ys ) + ( z - zs ) * ( z - zs ) ) / radius; + const contrib = + 1 - ratio * ratio * ratio * ( ratio * ( ratio * 6 - 15 ) + 10 ); + this.palette[ ( y_offset + x ) * 3 + 0 ] += ballColor.r * contrib; + this.palette[ ( y_offset + x ) * 3 + 1 ] += ballColor.g * contrib; + this.palette[ ( y_offset + x ) * 3 + 2 ] += ballColor.b * contrib; - // Let's solve the equation to find the radius: - // 1.0 / (0.000001 + radius^2) * strength - subtract = 0 - // strength / (radius^2) = subtract - // strength = subtract * radius^2 - // radius^2 = strength / subtract - // radius = sqrt(strength / subtract) - - var radius = this.size * Math.sqrt( strength / subtract ), - zs = ballz * this.size, - ys = bally * this.size, - xs = ballx * this.size; - - var min_z = Math.floor( zs - radius ); - if ( min_z < 1 ) min_z = 1; - var max_z = Math.floor( zs + radius ); - if ( max_z > this.size - 1 ) max_z = this.size - 1; - var min_y = Math.floor( ys - radius ); - if ( min_y < 1 ) min_y = 1; - var max_y = Math.floor( ys + radius ); - if ( max_y > this.size - 1 ) max_y = this.size - 1; - var min_x = Math.floor( xs - radius ); - if ( min_x < 1 ) min_x = 1; - var max_x = Math.floor( xs + radius ); - if ( max_x > this.size - 1 ) max_x = this.size - 1; - - // Don't polygonize in the outer layer because normals aren't - // well-defined there. - - var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val; - for ( z = min_z; z < max_z; z ++ ) { - - z_offset = this.size2 * z; - fz = z / this.size - ballz; - fz2 = fz * fz; - - for ( y = min_y; y < max_y; y ++ ) { - - y_offset = z_offset + this.size * y; - fy = y / this.size - bally; - fy2 = fy * fy; - - for ( x = min_x; x < max_x; x ++ ) { - - fx = x / this.size - ballx; - val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract; - if ( val > 0.0 ) { - - this.field[ y_offset + x ] += val * sign; - - // optimization - // http://www.geisswerks.com/ryan/BLOBS/blobs.html - const ratio = - Math.sqrt( ( x - xs ) * ( x - xs ) + ( y - ys ) * ( y - ys ) + ( z - zs ) * ( z - zs ) ) / radius; - const contrib = - 1 - ratio * ratio * ratio * ( ratio * ( ratio * 6 - 15 ) + 10 ); - this.palette[ ( y_offset + x ) * 3 + 0 ] += ballColor.r * contrib; - this.palette[ ( y_offset + x ) * 3 + 1 ] += ballColor.g * contrib; - this.palette[ ( y_offset + x ) * 3 + 2 ] += ballColor.b * contrib; + } } @@ -639,43 +645,44 @@ var MarchingCubes = function ( resolution, material, enableUvs, enableColors ) { } - } - - }; + }; - this.addPlaneX = function ( strength, subtract ) { + this.addPlaneX = function ( strength, subtract ) { - var x, - y, - z, - xx, - val, - xdiv, - cxy, // cache attribute lookups - size = this.size, - yd = this.yd, - zd = this.zd, - field = this.field, - dist = size * Math.sqrt( strength / subtract ); + const size = this.size, + yd = this.yd, + zd = this.zd, + field = this.field; + + let x, + y, + z, + xx, + val, + xdiv, + cxy, + dist = size * Math.sqrt( strength / subtract ); - if ( dist > size ) dist = size; + if ( dist > size ) dist = size; - for ( x = 0; x < dist; x ++ ) { + for ( x = 0; x < dist; x ++ ) { - xdiv = x / size; - xx = xdiv * xdiv; - val = strength / ( 0.0001 + xx ) - subtract; + xdiv = x / size; + xx = xdiv * xdiv; + val = strength / ( 0.0001 + xx ) - subtract; - if ( val > 0.0 ) { + if ( val > 0.0 ) { - for ( y = 0; y < size; y ++ ) { + for ( y = 0; y < size; y ++ ) { - cxy = x + y * yd; + cxy = x + y * yd; - for ( z = 0; z < size; z ++ ) { + for ( z = 0; z < size; z ++ ) { - field[ zd * z + cxy ] += val; + field[ zd * z + cxy ] += val; + + } } @@ -683,300 +690,294 @@ var MarchingCubes = function ( resolution, material, enableUvs, enableColors ) { } - } - - }; + }; - this.addPlaneY = function ( strength, subtract ) { + this.addPlaneY = function ( strength, subtract ) { - var x, - y, - z, - yy, - val, - ydiv, - cy, - cxy, // cache attribute lookups - size = this.size, - yd = this.yd, - zd = this.zd, - field = this.field, - dist = size * Math.sqrt( strength / subtract ); + const size = this.size, + yd = this.yd, + zd = this.zd, + field = this.field; + + let x, + y, + z, + yy, + val, + ydiv, + cy, + cxy, + dist = size * Math.sqrt( strength / subtract ); - if ( dist > size ) dist = size; + if ( dist > size ) dist = size; - for ( y = 0; y < dist; y ++ ) { + for ( y = 0; y < dist; y ++ ) { - ydiv = y / size; - yy = ydiv * ydiv; - val = strength / ( 0.0001 + yy ) - subtract; + ydiv = y / size; + yy = ydiv * ydiv; + val = strength / ( 0.0001 + yy ) - subtract; - if ( val > 0.0 ) { + if ( val > 0.0 ) { - cy = y * yd; + cy = y * yd; - for ( x = 0; x < size; x ++ ) { + for ( x = 0; x < size; x ++ ) { - cxy = cy + x; + cxy = cy + x; - for ( z = 0; z < size; z ++ ) field[ zd * z + cxy ] += val; + for ( z = 0; z < size; z ++ ) field[ zd * z + cxy ] += val; + + } } } - } - - }; + }; - this.addPlaneZ = function ( strength, subtract ) { + this.addPlaneZ = function ( strength, subtract ) { - var x, - y, - z, - zz, - val, - zdiv, - cz, - cyz, // cache attribute lookups - size = this.size, - yd = this.yd, - zd = this.zd, - field = this.field, - dist = size * Math.sqrt( strength / subtract ); - if ( dist > size ) dist = size; + const size = this.size, + yd = this.yd, + zd = this.zd, + field = this.field; - for ( z = 0; z < dist; z ++ ) { + let x, + y, + z, + zz, + val, + zdiv, + cz, + cyz, + dist = size * Math.sqrt( strength / subtract ); - zdiv = z / size; - zz = zdiv * zdiv; - val = strength / ( 0.0001 + zz ) - subtract; - if ( val > 0.0 ) { + if ( dist > size ) dist = size; - cz = zd * z; + for ( z = 0; z < dist; z ++ ) { - for ( y = 0; y < size; y ++ ) { + zdiv = z / size; + zz = zdiv * zdiv; + val = strength / ( 0.0001 + zz ) - subtract; + if ( val > 0.0 ) { - cyz = cz + y * yd; + cz = zd * z; - for ( x = 0; x < size; x ++ ) field[ cyz + x ] += val; + for ( y = 0; y < size; y ++ ) { - } + cyz = cz + y * yd; - } + for ( x = 0; x < size; x ++ ) field[ cyz + x ] += val; - } + } - }; + } - ///////////////////////////////////// - // Updates - ///////////////////////////////////// + } - this.setCell = function ( x, y, z, value ) { + }; - var index = this.size2 * z + this.size * y + x; - this.field[ index ] = value; + ///////////////////////////////////// + // Updates + ///////////////////////////////////// - }; + this.setCell = function ( x, y, z, value ) { - this.getCell = function ( x, y, z ) { + const index = this.size2 * z + this.size * y + x; + this.field[ index ] = value; - var index = this.size2 * z + this.size * y + x; - return this.field[ index ]; + }; - }; + this.getCell = function ( x, y, z ) { - this.blur = function ( intensity ) { + const index = this.size2 * z + this.size * y + x; + return this.field[ index ]; - if ( intensity === undefined ) { + }; - intensity = 1; + this.blur = function ( intensity = 1 ) { - } + const field = this.field; + const fieldCopy = field.slice(); + const size = this.size; + const size2 = this.size2; + for ( let x = 0; x < size; x ++ ) { - var field = this.field; - var fieldCopy = field.slice(); - var size = this.size; - var size2 = this.size2; - for ( var x = 0; x < size; x ++ ) { + for ( let y = 0; y < size; y ++ ) { - for ( var y = 0; y < size; y ++ ) { + for ( let z = 0; z < size; z ++ ) { - for ( var z = 0; z < size; z ++ ) { + const index = size2 * z + size * y + x; + let val = fieldCopy[ index ]; + let count = 1; - var index = size2 * z + size * y + x; - var val = fieldCopy[ index ]; - var count = 1; + for ( let x2 = - 1; x2 <= 1; x2 += 2 ) { - for ( var x2 = - 1; x2 <= 1; x2 += 2 ) { + const x3 = x2 + x; + if ( x3 < 0 || x3 >= size ) continue; - var x3 = x2 + x; - if ( x3 < 0 || x3 >= size ) continue; + for ( let y2 = - 1; y2 <= 1; y2 += 2 ) { - for ( var y2 = - 1; y2 <= 1; y2 += 2 ) { + const y3 = y2 + y; + if ( y3 < 0 || y3 >= size ) continue; - var y3 = y2 + y; - if ( y3 < 0 || y3 >= size ) continue; + for ( let z2 = - 1; z2 <= 1; z2 += 2 ) { - for ( var z2 = - 1; z2 <= 1; z2 += 2 ) { + const z3 = z2 + z; + if ( z3 < 0 || z3 >= size ) continue; - var z3 = z2 + z; - if ( z3 < 0 || z3 >= size ) continue; + const index2 = size2 * z3 + size * y3 + x3; + const val2 = fieldCopy[ index2 ]; - var index2 = size2 * z3 + size * y3 + x3; - var val2 = fieldCopy[ index2 ]; + count ++; + val += intensity * ( val2 - val ) / count; - count ++; - val += intensity * ( val2 - val ) / count; + } } } - } + field[ index ] = val; - field[ index ] = val; + } } } - } - - }; + }; - this.reset = function () { + this.reset = function () { - var i; + // wipe the normal cache - // wipe the normal cache + for ( let i = 0; i < this.size3; i ++ ) { - for ( i = 0; i < this.size3; i ++ ) { + this.normal_cache[ i * 3 ] = 0.0; + this.field[ i ] = 0.0; + this.palette[ i * 3 ] = this.palette[ i * 3 + 1 ] = this.palette[ + i * 3 + 2 + ] = 0.0; - this.normal_cache[ i * 3 ] = 0.0; - this.field[ i ] = 0.0; - this.palette[ i * 3 ] = this.palette[ i * 3 + 1 ] = this.palette[ - i * 3 + 2 - ] = 0.0; + } - } + }; - }; + this.render = function ( renderCallback ) { - this.render = function ( renderCallback ) { + this.begin(); - this.begin(); + // Triangulate. Yeah, this is slow. - // Triangulate. Yeah, this is slow. + const smin2 = this.size - 2; - var smin2 = this.size - 2; + for ( let z = 1; z < smin2; z ++ ) { - for ( var z = 1; z < smin2; z ++ ) { + const z_offset = this.size2 * z; + const fz = ( z - this.halfsize ) / this.halfsize; //+ 1 - var z_offset = this.size2 * z; - var fz = ( z - this.halfsize ) / this.halfsize; //+ 1 + for ( let y = 1; y < smin2; y ++ ) { - for ( var y = 1; y < smin2; y ++ ) { + const y_offset = z_offset + this.size * y; + const fy = ( y - this.halfsize ) / this.halfsize; //+ 1 - var y_offset = z_offset + this.size * y; - var fy = ( y - this.halfsize ) / this.halfsize; //+ 1 + for ( let x = 1; x < smin2; x ++ ) { - for ( var x = 1; x < smin2; x ++ ) { + const fx = ( x - this.halfsize ) / this.halfsize; //+ 1 + const q = y_offset + x; - var fx = ( x - this.halfsize ) / this.halfsize; //+ 1 - var q = y_offset + x; + polygonize( fx, fy, fz, q, this.isolation, renderCallback ); - polygonize( fx, fy, fz, q, this.isolation, renderCallback ); + } } } - } - - this.end( renderCallback ); + this.end( renderCallback ); - }; - - this.generateGeometry = function () { - - console.warn( - 'THREE.MarchingCubes: generateGeometry() now returns BufferGeometry' - ); - return this.generateBufferGeometry(); - - }; - - function concatenate( a, b, length ) { + }; - var result = new Float32Array( a.length + length ); - result.set( a, 0 ); - result.set( b.slice( 0, length ), a.length ); - return result; + this.generateGeometry = function () { - } + console.warn( + 'THREE.MarchingCubes: generateGeometry() now returns BufferGeometry' + ); + return this.generateBufferGeometry(); - this.generateBufferGeometry = function () { + }; - var geo = new BufferGeometry(); - var posArray = new Float32Array(); - var normArray = new Float32Array(); - var colorArray = new Float32Array(); - var uvArray = new Float32Array(); - var scope = this; + function concatenate( a, b, length ) { - var geo_callback = function ( object ) { + const result = new Float32Array( a.length + length ); + result.set( a, 0 ); + result.set( b.slice( 0, length ), a.length ); + return result; - if ( scope.hasPositions ) - posArray = concatenate( - posArray, - object.positionArray, - object.count * 3 - ); - if ( scope.hasNormals ) - normArray = concatenate( - normArray, - object.normalArray, - object.count * 3 - ); - if ( scope.hasColors ) - colorArray = concatenate( - colorArray, - object.colorArray, - object.count * 3 - ); - if ( scope.hasUvs ) - uvArray = concatenate( uvArray, object.uvArray, object.count * 2 ); + } - object.count = 0; + this.generateBufferGeometry = function () { + + const geo = new BufferGeometry(); + let posArray = new Float32Array(); + let normArray = new Float32Array(); + let colorArray = new Float32Array(); + let uvArray = new Float32Array(); + const scope = this; + + const geo_callback = function ( object ) { + + if ( scope.hasPositions ) + posArray = concatenate( + posArray, + object.positionArray, + object.count * 3 + ); + if ( scope.hasNormals ) + normArray = concatenate( + normArray, + object.normalArray, + object.count * 3 + ); + if ( scope.hasColors ) + colorArray = concatenate( + colorArray, + object.colorArray, + object.count * 3 + ); + if ( scope.hasUvs ) + uvArray = concatenate( uvArray, object.uvArray, object.count * 2 ); + + object.count = 0; + + }; + + this.render( geo_callback ); + + if ( this.hasPositions ) + geo.setAttribute( 'position', new BufferAttribute( posArray, 3 ) ); + if ( this.hasNormals ) + geo.setAttribute( 'normal', new BufferAttribute( normArray, 3 ) ); + if ( this.hasColors ) + geo.setAttribute( 'color', new BufferAttribute( colorArray, 3 ) ); + if ( this.hasUvs ) + geo.setAttribute( 'uv', new BufferAttribute( uvArray, 2 ) ); + + return geo; }; - this.render( geo_callback ); + this.init( resolution ); - if ( this.hasPositions ) - geo.setAttribute( 'position', new BufferAttribute( posArray, 3 ) ); - if ( this.hasNormals ) - geo.setAttribute( 'normal', new BufferAttribute( normArray, 3 ) ); - if ( this.hasColors ) - geo.setAttribute( 'color', new BufferAttribute( colorArray, 3 ) ); - if ( this.hasUvs ) - geo.setAttribute( 'uv', new BufferAttribute( uvArray, 2 ) ); - - return geo; - - }; - - this.init( resolution ); + } -}; +} -MarchingCubes.prototype = Object.create( ImmediateRenderObject.prototype ); -MarchingCubes.prototype.constructor = MarchingCubes; +MarchingCubes.prototype.isMarchingCubes = true; ///////////////////////////////////// // Marching cubes lookup tables @@ -986,7 +987,7 @@ MarchingCubes.prototype.constructor = MarchingCubes; // http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/ // who in turn got them from Cory Gene Bloyd. -var edgeTable = new Int32Array( [ +const edgeTable = new Int32Array( [ 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, @@ -1020,7 +1021,7 @@ var edgeTable = new Int32Array( [ 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] ); -var triTable = new Int32Array( [ +const triTable = new Int32Array( [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, diff --git a/examples/jsm/objects/Reflector.js b/examples/jsm/objects/Reflector.js index a67a5b578f00a9..0270c24335ee97 100644 --- a/examples/jsm/objects/Reflector.js +++ b/examples/jsm/objects/Reflector.js @@ -14,189 +14,190 @@ import { WebGLRenderTarget } from '../../../build/three.module.js'; -var Reflector = function ( geometry, options ) { +class Reflector extends Mesh { - Mesh.call( this, geometry ); + constructor( geometry, options = {} ) { - this.type = 'Reflector'; + super( geometry ); - var scope = this; + this.type = 'Reflector'; - options = options || {}; + const scope = this; - var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F ); - var textureWidth = options.textureWidth || 512; - var textureHeight = options.textureHeight || 512; - var clipBias = options.clipBias || 0; - var shader = options.shader || Reflector.ReflectorShader; + const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F ); + const textureWidth = options.textureWidth || 512; + const textureHeight = options.textureHeight || 512; + const clipBias = options.clipBias || 0; + const shader = options.shader || Reflector.ReflectorShader; - // + // - var reflectorPlane = new Plane(); - var normal = new Vector3(); - var reflectorWorldPosition = new Vector3(); - var cameraWorldPosition = new Vector3(); - var rotationMatrix = new Matrix4(); - var lookAtPosition = new Vector3( 0, 0, - 1 ); - var clipPlane = new Vector4(); + const reflectorPlane = new Plane(); + const normal = new Vector3(); + const reflectorWorldPosition = new Vector3(); + const cameraWorldPosition = new Vector3(); + const rotationMatrix = new Matrix4(); + const lookAtPosition = new Vector3( 0, 0, - 1 ); + const clipPlane = new Vector4(); - var view = new Vector3(); - var target = new Vector3(); - var q = new Vector4(); + const view = new Vector3(); + const target = new Vector3(); + const q = new Vector4(); - var textureMatrix = new Matrix4(); - var virtualCamera = new PerspectiveCamera(); + const textureMatrix = new Matrix4(); + const virtualCamera = new PerspectiveCamera(); - var parameters = { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBFormat - }; + const parameters = { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBFormat + }; - var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); + const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); - if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { + if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { - renderTarget.texture.generateMipmaps = false; + renderTarget.texture.generateMipmaps = false; - } + } - var material = new ShaderMaterial( { - uniforms: UniformsUtils.clone( shader.uniforms ), - fragmentShader: shader.fragmentShader, - vertexShader: shader.vertexShader - } ); + const material = new ShaderMaterial( { + uniforms: UniformsUtils.clone( shader.uniforms ), + fragmentShader: shader.fragmentShader, + vertexShader: shader.vertexShader + } ); - material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; - material.uniforms[ 'color' ].value = color; - material.uniforms[ 'textureMatrix' ].value = textureMatrix; + material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; + material.uniforms[ 'color' ].value = color; + material.uniforms[ 'textureMatrix' ].value = textureMatrix; - this.material = material; + this.material = material; - this.onBeforeRender = function ( renderer, scene, camera ) { + this.onBeforeRender = function ( renderer, scene, camera ) { - reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); - cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); + reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); + cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); - rotationMatrix.extractRotation( scope.matrixWorld ); + rotationMatrix.extractRotation( scope.matrixWorld ); - normal.set( 0, 0, 1 ); - normal.applyMatrix4( rotationMatrix ); + normal.set( 0, 0, 1 ); + normal.applyMatrix4( rotationMatrix ); - view.subVectors( reflectorWorldPosition, cameraWorldPosition ); + view.subVectors( reflectorWorldPosition, cameraWorldPosition ); - // Avoid rendering when reflector is facing away + // Avoid rendering when reflector is facing away - if ( view.dot( normal ) > 0 ) return; + if ( view.dot( normal ) > 0 ) return; - view.reflect( normal ).negate(); - view.add( reflectorWorldPosition ); + view.reflect( normal ).negate(); + view.add( reflectorWorldPosition ); - rotationMatrix.extractRotation( camera.matrixWorld ); + rotationMatrix.extractRotation( camera.matrixWorld ); - lookAtPosition.set( 0, 0, - 1 ); - lookAtPosition.applyMatrix4( rotationMatrix ); - lookAtPosition.add( cameraWorldPosition ); + lookAtPosition.set( 0, 0, - 1 ); + lookAtPosition.applyMatrix4( rotationMatrix ); + lookAtPosition.add( cameraWorldPosition ); - target.subVectors( reflectorWorldPosition, lookAtPosition ); - target.reflect( normal ).negate(); - target.add( reflectorWorldPosition ); + target.subVectors( reflectorWorldPosition, lookAtPosition ); + target.reflect( normal ).negate(); + target.add( reflectorWorldPosition ); - virtualCamera.position.copy( view ); - virtualCamera.up.set( 0, 1, 0 ); - virtualCamera.up.applyMatrix4( rotationMatrix ); - virtualCamera.up.reflect( normal ); - virtualCamera.lookAt( target ); + virtualCamera.position.copy( view ); + virtualCamera.up.set( 0, 1, 0 ); + virtualCamera.up.applyMatrix4( rotationMatrix ); + virtualCamera.up.reflect( normal ); + virtualCamera.lookAt( target ); - virtualCamera.far = camera.far; // Used in WebGLBackground + virtualCamera.far = camera.far; // Used in WebGLBackground - virtualCamera.updateMatrixWorld(); - virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); + virtualCamera.updateMatrixWorld(); + virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); - // Update the texture matrix - textureMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - textureMatrix.multiply( virtualCamera.projectionMatrix ); - textureMatrix.multiply( virtualCamera.matrixWorldInverse ); - textureMatrix.multiply( scope.matrixWorld ); + // Update the texture matrix + textureMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); + textureMatrix.multiply( virtualCamera.projectionMatrix ); + textureMatrix.multiply( virtualCamera.matrixWorldInverse ); + textureMatrix.multiply( scope.matrixWorld ); - // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html - // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition ); - reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); + // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html + // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf + reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition ); + reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); - clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant ); + clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant ); - var projectionMatrix = virtualCamera.projectionMatrix; + const projectionMatrix = virtualCamera.projectionMatrix; - q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; - q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; - q.z = - 1.0; - q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; + q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; + q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; + q.z = - 1.0; + q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; - // Calculate the scaled plane vector - clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); + // Calculate the scaled plane vector + clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); - // Replacing the third row of the projection matrix - projectionMatrix.elements[ 2 ] = clipPlane.x; - projectionMatrix.elements[ 6 ] = clipPlane.y; - projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias; - projectionMatrix.elements[ 14 ] = clipPlane.w; + // Replacing the third row of the projection matrix + projectionMatrix.elements[ 2 ] = clipPlane.x; + projectionMatrix.elements[ 6 ] = clipPlane.y; + projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias; + projectionMatrix.elements[ 14 ] = clipPlane.w; - // Render + // Render - renderTarget.texture.encoding = renderer.outputEncoding; + renderTarget.texture.encoding = renderer.outputEncoding; - scope.visible = false; + scope.visible = false; - var currentRenderTarget = renderer.getRenderTarget(); + const currentRenderTarget = renderer.getRenderTarget(); - var currentXrEnabled = renderer.xr.enabled; - var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; + const currentXrEnabled = renderer.xr.enabled; + const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; - renderer.xr.enabled = false; // Avoid camera modification - renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows + renderer.xr.enabled = false; // Avoid camera modification + renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows - renderer.setRenderTarget( renderTarget ); + renderer.setRenderTarget( renderTarget ); - renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897 + renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897 - if ( renderer.autoClear === false ) renderer.clear(); - renderer.render( scene, virtualCamera ); + if ( renderer.autoClear === false ) renderer.clear(); + renderer.render( scene, virtualCamera ); - renderer.xr.enabled = currentXrEnabled; - renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; + renderer.xr.enabled = currentXrEnabled; + renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; - renderer.setRenderTarget( currentRenderTarget ); + renderer.setRenderTarget( currentRenderTarget ); - // Restore viewport + // Restore viewport - var viewport = camera.viewport; + const viewport = camera.viewport; - if ( viewport !== undefined ) { + if ( viewport !== undefined ) { - renderer.state.viewport( viewport ); + renderer.state.viewport( viewport ); - } + } - scope.visible = true; + scope.visible = true; - }; + }; - this.getRenderTarget = function () { + this.getRenderTarget = function () { - return renderTarget; + return renderTarget; - }; + }; -}; + } + +} -Reflector.prototype = Object.create( Mesh.prototype ); -Reflector.prototype.constructor = Reflector; +Reflector.prototype.isReflector = true; Reflector.ReflectorShader = { @@ -216,43 +217,41 @@ Reflector.ReflectorShader = { }, - vertexShader: [ - 'uniform mat4 textureMatrix;', - 'varying vec4 vUv;', + vertexShader: /* glsl */` + uniform mat4 textureMatrix; + varying vec4 vUv; - 'void main() {', + void main() { - ' vUv = textureMatrix * vec4( position, 1.0 );', + vUv = textureMatrix * vec4( position, 1.0 ); - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' - ].join( '\n' ), + }`, - fragmentShader: [ - 'uniform vec3 color;', - 'uniform sampler2D tDiffuse;', - 'varying vec4 vUv;', + fragmentShader: /* glsl */` + uniform vec3 color; + uniform sampler2D tDiffuse; + varying vec4 vUv; - 'float blendOverlay( float base, float blend ) {', + float blendOverlay( float base, float blend ) { - ' return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );', + return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) ); - '}', + } - 'vec3 blendOverlay( vec3 base, vec3 blend ) {', + vec3 blendOverlay( vec3 base, vec3 blend ) { - ' return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );', + return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) ); - '}', + } - 'void main() {', + void main() { - ' vec4 base = texture2DProj( tDiffuse, vUv );', - ' gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );', + vec4 base = texture2DProj( tDiffuse, vUv ); + gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 ); - '}' - ].join( '\n' ) + }` }; export { Reflector }; diff --git a/examples/jsm/objects/ReflectorForSSRPass.js b/examples/jsm/objects/ReflectorForSSRPass.js index 755eb0b7366c37..662bd1caa99169 100644 --- a/examples/jsm/objects/ReflectorForSSRPass.js +++ b/examples/jsm/objects/ReflectorForSSRPass.js @@ -13,271 +13,255 @@ import { WebGLRenderTarget, DepthTexture, UnsignedShortType, - NearestFilter + NearestFilter, + Plane } from '../../../build/three.module.js'; -var ReflectorForSSRPass = function ( geometry, options ) { +class ReflectorForSSRPass extends Mesh { - Mesh.call( this, geometry ); + constructor( geometry, options = {} ) { - this.type = 'ReflectorForSSRPass'; + super( geometry ); - var scope = this; + this.type = 'ReflectorForSSRPass'; - options = options || {}; + const scope = this; - var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F ); - var textureWidth = options.textureWidth || 512; - var textureHeight = options.textureHeight || 512; - var shader = options.shader || ReflectorForSSRPass.ReflectorShader; - var useDepthTexture = options.useDepthTexture === true; - var yAxis = new Vector3( 0, 1, 0 ); - var vecTemp0 = new Vector3(); - var vecTemp1 = new Vector3(); + const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F ); + const textureWidth = options.textureWidth || 512; + const textureHeight = options.textureHeight || 512; + const clipBias = options.clipBias || 0; + const shader = options.shader || ReflectorForSSRPass.ReflectorShader; + const useDepthTexture = options.useDepthTexture === true; + const yAxis = new Vector3( 0, 1, 0 ); + const vecTemp0 = new Vector3(); + const vecTemp1 = new Vector3(); - // + // - scope.needsUpdate = false; - scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value; - scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value; - scope.color = color; - scope.resolution = options.resolution || new Vector2( window.innerWidth, window.innerHeight ); + scope.needsUpdate = false; + scope.maxDistance = ReflectorForSSRPass.ReflectorShader.uniforms.maxDistance.value; + scope.opacity = ReflectorForSSRPass.ReflectorShader.uniforms.opacity.value; + scope.color = color; + scope.resolution = options.resolution || new Vector2( window.innerWidth, window.innerHeight ); - scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION; - Object.defineProperty( scope, 'distanceAttenuation', { - get() { + scope._distanceAttenuation = ReflectorForSSRPass.ReflectorShader.defines.DISTANCE_ATTENUATION; + Object.defineProperty( scope, 'distanceAttenuation', { + get() { - return scope._distanceAttenuation; + return scope._distanceAttenuation; - }, - set( val ) { + }, + set( val ) { - if ( scope._distanceAttenuation === val ) return; - scope._distanceAttenuation = val; - scope.material.defines.DISTANCE_ATTENUATION = val; - scope.material.needsUpdate = true; + if ( scope._distanceAttenuation === val ) return; + scope._distanceAttenuation = val; + scope.material.defines.DISTANCE_ATTENUATION = val; + scope.material.needsUpdate = true; - } - } ); - - scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL; - Object.defineProperty( scope, 'fresnel', { - get() { - - return scope._fresnel; - - }, - set( val ) { - - if ( scope._fresnel === val ) return; - scope._fresnel = val; - scope.material.defines.FRESNEL = val; - scope.material.needsUpdate = true; + } + } ); - } - } ); + scope._fresnel = ReflectorForSSRPass.ReflectorShader.defines.FRESNEL; + Object.defineProperty( scope, 'fresnel', { + get() { - var normal = new Vector3(); - var reflectorWorldPosition = new Vector3(); - var cameraWorldPosition = new Vector3(); - var rotationMatrix = new Matrix4(); - var lookAtPosition = new Vector3( 0, 0, - 1 ); + return scope._fresnel; - var view = new Vector3(); - var target = new Vector3(); + }, + set( val ) { - var textureMatrix = new Matrix4(); - var virtualCamera = new PerspectiveCamera(); + if ( scope._fresnel === val ) return; + scope._fresnel = val; + scope.material.defines.FRESNEL = val; + scope.material.needsUpdate = true; - if ( useDepthTexture ) { + } + } ); - var depthTexture = new DepthTexture(); - depthTexture.type = UnsignedShortType; - depthTexture.minFilter = NearestFilter; - depthTexture.magFilter = NearestFilter; + const normal = new Vector3(); + const reflectorWorldPosition = new Vector3(); + const cameraWorldPosition = new Vector3(); + const rotationMatrix = new Matrix4(); + const lookAtPosition = new Vector3( 0, 0, - 1 ); - } + const view = new Vector3(); + const target = new Vector3(); - var parameters = { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBFormat, - depthTexture: useDepthTexture ? depthTexture : null, - }; + const textureMatrix = new Matrix4(); + const virtualCamera = new PerspectiveCamera(); - var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); + let depthTexture; - if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { + if ( useDepthTexture ) { - renderTarget.texture.generateMipmaps = false; + depthTexture = new DepthTexture(); + depthTexture.type = UnsignedShortType; + depthTexture.minFilter = NearestFilter; + depthTexture.magFilter = NearestFilter; - } + } - var material = new ShaderMaterial( { - transparent: useDepthTexture, - defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, { - useDepthTexture - } ), - uniforms: UniformsUtils.clone( shader.uniforms ), - fragmentShader: shader.fragmentShader, - vertexShader: shader.vertexShader - } ); + const parameters = { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBFormat, + depthTexture: useDepthTexture ? depthTexture : null, + }; - material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; - material.uniforms[ 'color' ].value = scope.color; - material.uniforms[ 'textureMatrix' ].value = textureMatrix; - if ( useDepthTexture ) { + const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); - material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture; + if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { - } + renderTarget.texture.generateMipmaps = false; - this.material = material; - - this.doRender = function ( renderer, scene, camera ) { + } - material.uniforms[ 'maxDistance' ].value = scope.maxDistance; + const material = new ShaderMaterial( { + transparent: useDepthTexture, + defines: Object.assign( {}, ReflectorForSSRPass.ReflectorShader.defines, { + useDepthTexture + } ), + uniforms: UniformsUtils.clone( shader.uniforms ), + fragmentShader: shader.fragmentShader, + vertexShader: shader.vertexShader + } ); + + material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; material.uniforms[ 'color' ].value = scope.color; - material.uniforms[ 'opacity' ].value = scope.opacity; - - vecTemp0.copy( camera.position ).normalize(); - vecTemp1.copy( vecTemp0 ).reflect( yAxis ); - material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel. + material.uniforms[ 'textureMatrix' ].value = textureMatrix; + if ( useDepthTexture ) { - reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); - cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); + material.uniforms[ 'tDepth' ].value = renderTarget.depthTexture; - rotationMatrix.extractRotation( scope.matrixWorld ); + } - normal.set( 0, 0, 1 ); - normal.applyMatrix4( rotationMatrix ); + this.material = material; - view.subVectors( reflectorWorldPosition, cameraWorldPosition ); + const globalPlane = new Plane( new Vector3( 0, 1, 0 ), clipBias ); + const globalPlanes = [ globalPlane ]; - // Avoid rendering when reflector is facing away + this.doRender = function ( renderer, scene, camera ) { - if ( view.dot( normal ) > 0 ) return; + material.uniforms[ 'maxDistance' ].value = scope.maxDistance; + material.uniforms[ 'color' ].value = scope.color; + material.uniforms[ 'opacity' ].value = scope.opacity; - view.reflect( normal ).negate(); - view.add( reflectorWorldPosition ); + vecTemp0.copy( camera.position ).normalize(); + vecTemp1.copy( vecTemp0 ).reflect( yAxis ); + material.uniforms[ 'fresnelCoe' ].value = ( vecTemp0.dot( vecTemp1 ) + 1. ) / 2.; // TODO: Also need to use glsl viewPosition and viewNormal per pixel. - rotationMatrix.extractRotation( camera.matrixWorld ); + reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); + cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); - lookAtPosition.set( 0, 0, - 1 ); - lookAtPosition.applyMatrix4( rotationMatrix ); - lookAtPosition.add( cameraWorldPosition ); + rotationMatrix.extractRotation( scope.matrixWorld ); - target.subVectors( reflectorWorldPosition, lookAtPosition ); - target.reflect( normal ).negate(); - target.add( reflectorWorldPosition ); + normal.set( 0, 0, 1 ); + normal.applyMatrix4( rotationMatrix ); - virtualCamera.position.copy( view ); - virtualCamera.up.set( 0, 1, 0 ); - virtualCamera.up.applyMatrix4( rotationMatrix ); - virtualCamera.up.reflect( normal ); - virtualCamera.lookAt( target ); + view.subVectors( reflectorWorldPosition, cameraWorldPosition ); - virtualCamera.far = camera.far; // Used in WebGLBackground + // Avoid rendering when reflector is facing away - virtualCamera.updateMatrixWorld(); - virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); + if ( view.dot( normal ) > 0 ) return; - material.uniforms[ 'virtualCameraNear' ].value = camera.near; - material.uniforms[ 'virtualCameraFar' ].value = camera.far; - material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld; - material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix; - material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse; - material.uniforms[ 'resolution' ].value = scope.resolution; + view.reflect( normal ).negate(); + view.add( reflectorWorldPosition ); - // Update the texture matrix - textureMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - textureMatrix.multiply( virtualCamera.projectionMatrix ); - textureMatrix.multiply( virtualCamera.matrixWorldInverse ); - textureMatrix.multiply( scope.matrixWorld ); + rotationMatrix.extractRotation( camera.matrixWorld ); - /* Note: For the sake of accurate tDepth, temporarily turned off this Oblique Near-Plane Clipping feature. https://github.com/mrdoob/three.js/pull/21403 + lookAtPosition.set( 0, 0, - 1 ); + lookAtPosition.applyMatrix4( rotationMatrix ); + lookAtPosition.add( cameraWorldPosition ); - // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html - // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - reflectorPlane.setFromNormalAndCoplanarPoint( normal, reflectorWorldPosition ); - reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); + target.subVectors( reflectorWorldPosition, lookAtPosition ); + target.reflect( normal ).negate(); + target.add( reflectorWorldPosition ); - clipPlane.set( reflectorPlane.normal.x, reflectorPlane.normal.y, reflectorPlane.normal.z, reflectorPlane.constant ); + virtualCamera.position.copy( view ); + virtualCamera.up.set( 0, 1, 0 ); + virtualCamera.up.applyMatrix4( rotationMatrix ); + virtualCamera.up.reflect( normal ); + virtualCamera.lookAt( target ); - var projectionMatrix = virtualCamera.projectionMatrix; + virtualCamera.far = camera.far; // Used in WebGLBackground - q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; - q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; - q.z = - 1.0; - q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; + virtualCamera.updateMatrixWorld(); + virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); - // Calculate the scaled plane vector - clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); + material.uniforms[ 'virtualCameraNear' ].value = camera.near; + material.uniforms[ 'virtualCameraFar' ].value = camera.far; + material.uniforms[ 'virtualCameraMatrixWorld' ].value = virtualCamera.matrixWorld; + material.uniforms[ 'virtualCameraProjectionMatrix' ].value = camera.projectionMatrix; + material.uniforms[ 'virtualCameraProjectionMatrixInverse' ].value = camera.projectionMatrixInverse; + material.uniforms[ 'resolution' ].value = scope.resolution; - // Replacing the third row of the projection matrix - projectionMatrix.elements[ 2 ] = clipPlane.x; - projectionMatrix.elements[ 6 ] = clipPlane.y; - projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias; - projectionMatrix.elements[ 14 ] = clipPlane.w; + // Update the texture matrix + textureMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); + textureMatrix.multiply( virtualCamera.projectionMatrix ); + textureMatrix.multiply( virtualCamera.matrixWorldInverse ); + textureMatrix.multiply( scope.matrixWorld ); - */ + // Render - // Render + renderTarget.texture.encoding = renderer.outputEncoding; - renderTarget.texture.encoding = renderer.outputEncoding; + // scope.visible = false; - // scope.visible = false; + const currentRenderTarget = renderer.getRenderTarget(); - var currentRenderTarget = renderer.getRenderTarget(); + const currentXrEnabled = renderer.xr.enabled; + const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; + const currentClippingPlanes = renderer.clippingPlanes; - var currentXrEnabled = renderer.xr.enabled; - var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; + renderer.xr.enabled = false; // Avoid camera modification + renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows + renderer.clippingPlanes = globalPlanes; - renderer.xr.enabled = false; // Avoid camera modification - renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows + renderer.setRenderTarget( renderTarget ); - renderer.setRenderTarget( renderTarget ); + renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897 - renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897 + if ( renderer.autoClear === false ) renderer.clear(); + renderer.render( scene, virtualCamera ); - if ( renderer.autoClear === false ) renderer.clear(); - renderer.render( scene, virtualCamera ); + renderer.xr.enabled = currentXrEnabled; + renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; + renderer.clippingPlanes = currentClippingPlanes; - renderer.xr.enabled = currentXrEnabled; - renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; + renderer.setRenderTarget( currentRenderTarget ); - renderer.setRenderTarget( currentRenderTarget ); + // Restore viewport - // Restore viewport + const viewport = camera.viewport; - var viewport = camera.viewport; + if ( viewport !== undefined ) { - if ( viewport !== undefined ) { + renderer.state.viewport( viewport ); - renderer.state.viewport( viewport ); + } - } + // scope.visible = true; - // scope.visible = true; + }; - }; + this.getRenderTarget = function () { - this.getRenderTarget = function () { + return renderTarget; - return renderTarget; + }; - }; + } -}; +} -ReflectorForSSRPass.prototype = Object.create( Mesh.prototype ); -ReflectorForSSRPass.prototype.constructor = ReflectorForSSRPass; +ReflectorForSSRPass.prototype.isReflectorForSSRPass = true; ReflectorForSSRPass.ReflectorShader = { @@ -304,20 +288,19 @@ ReflectorForSSRPass.ReflectorShader = { }, - vertexShader: [ - 'uniform mat4 textureMatrix;', - 'varying vec4 vUv;', + vertexShader: /* glsl */` + uniform mat4 textureMatrix; + varying vec4 vUv; - 'void main() {', + void main() { - ' vUv = textureMatrix * vec4( position, 1.0 );', + vUv = textureMatrix * vec4( position, 1.0 ); - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' - ].join( '\n' ), + }`, - fragmentShader: ` + fragmentShader: /* glsl */` uniform vec3 color; uniform sampler2D tDiffuse; uniform sampler2D tDepth; diff --git a/examples/jsm/objects/ReflectorRTT.js b/examples/jsm/objects/ReflectorRTT.js index a4827bedabedfe..1c4c253cd866b6 100644 --- a/examples/jsm/objects/ReflectorRTT.js +++ b/examples/jsm/objects/ReflectorRTT.js @@ -1,13 +1,15 @@ import { Reflector } from '../objects/Reflector.js'; -var ReflectorRTT = function ( geometry, options ) { +class ReflectorRTT extends Reflector { - Reflector.call( this, geometry, options ); + constructor( geometry, options ) { - this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry + super( geometry, options ); -}; + this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry -ReflectorRTT.prototype = Object.create( Reflector.prototype ); + } + +} export { ReflectorRTT }; diff --git a/examples/jsm/objects/Refractor.js b/examples/jsm/objects/Refractor.js index 470997cfec5c33..78da77a86a68a9 100644 --- a/examples/jsm/objects/Refractor.js +++ b/examples/jsm/objects/Refractor.js @@ -15,257 +15,258 @@ import { WebGLRenderTarget } from '../../../build/three.module.js'; -var Refractor = function ( geometry, options ) { +class Refractor extends Mesh { - Mesh.call( this, geometry ); + constructor( geometry, options = {} ) { - this.type = 'Refractor'; + super( geometry ); - var scope = this; + this.type = 'Refractor'; - options = options || {}; + const scope = this; - var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F ); - var textureWidth = options.textureWidth || 512; - var textureHeight = options.textureHeight || 512; - var clipBias = options.clipBias || 0; - var shader = options.shader || Refractor.RefractorShader; + const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0x7F7F7F ); + const textureWidth = options.textureWidth || 512; + const textureHeight = options.textureHeight || 512; + const clipBias = options.clipBias || 0; + const shader = options.shader || Refractor.RefractorShader; - // + // - var virtualCamera = new PerspectiveCamera(); - virtualCamera.matrixAutoUpdate = false; - virtualCamera.userData.refractor = true; + const virtualCamera = new PerspectiveCamera(); + virtualCamera.matrixAutoUpdate = false; + virtualCamera.userData.refractor = true; - // + // - var refractorPlane = new Plane(); - var textureMatrix = new Matrix4(); + const refractorPlane = new Plane(); + const textureMatrix = new Matrix4(); - // render target + // render target - var parameters = { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBFormat - }; + const parameters = { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBFormat + }; - var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); + const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); - if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { + if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { - renderTarget.texture.generateMipmaps = false; + renderTarget.texture.generateMipmaps = false; - } + } - // material + // material - this.material = new ShaderMaterial( { - uniforms: UniformsUtils.clone( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader, - transparent: true // ensures, refractors are drawn from farthest to closest - } ); + this.material = new ShaderMaterial( { + uniforms: UniformsUtils.clone( shader.uniforms ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + transparent: true // ensures, refractors are drawn from farthest to closest + } ); - this.material.uniforms[ 'color' ].value = color; - this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; - this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; + this.material.uniforms[ 'color' ].value = color; + this.material.uniforms[ 'tDiffuse' ].value = renderTarget.texture; + this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; - // functions + // functions - var visible = ( function () { + const visible = ( function () { - var refractorWorldPosition = new Vector3(); - var cameraWorldPosition = new Vector3(); - var rotationMatrix = new Matrix4(); + const refractorWorldPosition = new Vector3(); + const cameraWorldPosition = new Vector3(); + const rotationMatrix = new Matrix4(); - var view = new Vector3(); - var normal = new Vector3(); + const view = new Vector3(); + const normal = new Vector3(); - return function visible( camera ) { + return function visible( camera ) { - refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); - cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); + refractorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); + cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); - view.subVectors( refractorWorldPosition, cameraWorldPosition ); + view.subVectors( refractorWorldPosition, cameraWorldPosition ); - rotationMatrix.extractRotation( scope.matrixWorld ); + rotationMatrix.extractRotation( scope.matrixWorld ); - normal.set( 0, 0, 1 ); - normal.applyMatrix4( rotationMatrix ); + normal.set( 0, 0, 1 ); + normal.applyMatrix4( rotationMatrix ); - return view.dot( normal ) < 0; + return view.dot( normal ) < 0; - }; + }; - } )(); + } )(); - var updateRefractorPlane = ( function () { + const updateRefractorPlane = ( function () { - var normal = new Vector3(); - var position = new Vector3(); - var quaternion = new Quaternion(); - var scale = new Vector3(); + const normal = new Vector3(); + const position = new Vector3(); + const quaternion = new Quaternion(); + const scale = new Vector3(); - return function updateRefractorPlane() { + return function updateRefractorPlane() { - scope.matrixWorld.decompose( position, quaternion, scale ); - normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); + scope.matrixWorld.decompose( position, quaternion, scale ); + normal.set( 0, 0, 1 ).applyQuaternion( quaternion ).normalize(); - // flip the normal because we want to cull everything above the plane + // flip the normal because we want to cull everything above the plane - normal.negate(); + normal.negate(); - refractorPlane.setFromNormalAndCoplanarPoint( normal, position ); + refractorPlane.setFromNormalAndCoplanarPoint( normal, position ); - }; + }; - } )(); + } )(); - var updateVirtualCamera = ( function () { + const updateVirtualCamera = ( function () { - var clipPlane = new Plane(); - var clipVector = new Vector4(); - var q = new Vector4(); + const clipPlane = new Plane(); + const clipVector = new Vector4(); + const q = new Vector4(); - return function updateVirtualCamera( camera ) { + return function updateVirtualCamera( camera ) { - virtualCamera.matrixWorld.copy( camera.matrixWorld ); - virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert(); - virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); - virtualCamera.far = camera.far; // used in WebGLBackground + virtualCamera.matrixWorld.copy( camera.matrixWorld ); + virtualCamera.matrixWorldInverse.copy( virtualCamera.matrixWorld ).invert(); + virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); + virtualCamera.far = camera.far; // used in WebGLBackground - // The following code creates an oblique view frustum for clipping. - // see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”. - // Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16 + // The following code creates an oblique view frustum for clipping. + // see: Lengyel, Eric. “Oblique View Frustum Depth Projection and Clipping”. + // Journal of Game Development, Vol. 1, No. 2 (2005), Charles River Media, pp. 5–16 - clipPlane.copy( refractorPlane ); - clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); + clipPlane.copy( refractorPlane ); + clipPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); - clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); + clipVector.set( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.constant ); - // calculate the clip-space corner point opposite the clipping plane and - // transform it into camera space by multiplying it by the inverse of the projection matrix + // calculate the clip-space corner point opposite the clipping plane and + // transform it into camera space by multiplying it by the inverse of the projection matrix - var projectionMatrix = virtualCamera.projectionMatrix; + const projectionMatrix = virtualCamera.projectionMatrix; - q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; - q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; - q.z = - 1.0; - q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; + q.x = ( Math.sign( clipVector.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; + q.y = ( Math.sign( clipVector.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; + q.z = - 1.0; + q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; - // calculate the scaled plane vector + // calculate the scaled plane vector - clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); + clipVector.multiplyScalar( 2.0 / clipVector.dot( q ) ); - // replacing the third row of the projection matrix + // replacing the third row of the projection matrix - projectionMatrix.elements[ 2 ] = clipVector.x; - projectionMatrix.elements[ 6 ] = clipVector.y; - projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias; - projectionMatrix.elements[ 14 ] = clipVector.w; + projectionMatrix.elements[ 2 ] = clipVector.x; + projectionMatrix.elements[ 6 ] = clipVector.y; + projectionMatrix.elements[ 10 ] = clipVector.z + 1.0 - clipBias; + projectionMatrix.elements[ 14 ] = clipVector.w; - }; + }; - } )(); + } )(); - // This will update the texture matrix that is used for projective texture mapping in the shader. - // see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf + // This will update the texture matrix that is used for projective texture mapping in the shader. + // see: http://developer.download.nvidia.com/assets/gamedev/docs/projective_texture_mapping.pdf - function updateTextureMatrix( camera ) { + function updateTextureMatrix( camera ) { - // this matrix does range mapping to [ 0, 1 ] + // this matrix does range mapping to [ 0, 1 ] - textureMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); + textureMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - // we use "Object Linear Texgen", so we need to multiply the texture matrix T - // (matrix above) with the projection and view matrix of the virtual camera - // and the model matrix of the refractor + // we use "Object Linear Texgen", so we need to multiply the texture matrix T + // (matrix above) with the projection and view matrix of the virtual camera + // and the model matrix of the refractor - textureMatrix.multiply( camera.projectionMatrix ); - textureMatrix.multiply( camera.matrixWorldInverse ); - textureMatrix.multiply( scope.matrixWorld ); + textureMatrix.multiply( camera.projectionMatrix ); + textureMatrix.multiply( camera.matrixWorldInverse ); + textureMatrix.multiply( scope.matrixWorld ); - } + } - // + // - function render( renderer, scene, camera ) { + function render( renderer, scene, camera ) { - scope.visible = false; + scope.visible = false; - var currentRenderTarget = renderer.getRenderTarget(); - var currentXrEnabled = renderer.xr.enabled; - var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; + const currentRenderTarget = renderer.getRenderTarget(); + const currentXrEnabled = renderer.xr.enabled; + const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; - renderer.xr.enabled = false; // avoid camera modification - renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows + renderer.xr.enabled = false; // avoid camera modification + renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows - renderer.setRenderTarget( renderTarget ); - if ( renderer.autoClear === false ) renderer.clear(); - renderer.render( scene, virtualCamera ); + renderer.setRenderTarget( renderTarget ); + if ( renderer.autoClear === false ) renderer.clear(); + renderer.render( scene, virtualCamera ); - renderer.xr.enabled = currentXrEnabled; - renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; - renderer.setRenderTarget( currentRenderTarget ); + renderer.xr.enabled = currentXrEnabled; + renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; + renderer.setRenderTarget( currentRenderTarget ); - // restore viewport + // restore viewport - var viewport = camera.viewport; + const viewport = camera.viewport; - if ( viewport !== undefined ) { + if ( viewport !== undefined ) { - renderer.state.viewport( viewport ); + renderer.state.viewport( viewport ); - } + } - scope.visible = true; + scope.visible = true; - } + } - // + // - this.onBeforeRender = function ( renderer, scene, camera ) { + this.onBeforeRender = function ( renderer, scene, camera ) { - // Render + // Render - renderTarget.texture.encoding = renderer.outputEncoding; + renderTarget.texture.encoding = renderer.outputEncoding; - // ensure refractors are rendered only once per frame + // ensure refractors are rendered only once per frame - if ( camera.userData.refractor === true ) return; + if ( camera.userData.refractor === true ) return; - // avoid rendering when the refractor is viewed from behind + // avoid rendering when the refractor is viewed from behind - if ( ! visible( camera ) === true ) return; + if ( ! visible( camera ) === true ) return; - // update + // update - updateRefractorPlane(); + updateRefractorPlane(); - updateTextureMatrix( camera ); + updateTextureMatrix( camera ); - updateVirtualCamera( camera ); + updateVirtualCamera( camera ); - render( renderer, scene, camera ); + render( renderer, scene, camera ); - }; + }; - this.getRenderTarget = function () { + this.getRenderTarget = function () { - return renderTarget; + return renderTarget; - }; + }; -}; + } + +} -Refractor.prototype = Object.create( Mesh.prototype ); -Refractor.prototype.constructor = Refractor; +Refractor.prototype.isRefractor = true; Refractor.RefractorShader = { @@ -285,50 +286,45 @@ Refractor.RefractorShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'uniform mat4 textureMatrix;', + uniform mat4 textureMatrix; - 'varying vec4 vUv;', + varying vec4 vUv; - 'void main() {', + void main() { - ' vUv = textureMatrix * vec4( position, 1.0 );', + vUv = textureMatrix * vec4( position, 1.0 ); + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + }`, - '}' + fragmentShader: /* glsl */` - ].join( '\n' ), + uniform vec3 color; + uniform sampler2D tDiffuse; - fragmentShader: [ + varying vec4 vUv; - 'uniform vec3 color;', - 'uniform sampler2D tDiffuse;', + float blendOverlay( float base, float blend ) { - 'varying vec4 vUv;', + return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) ); - 'float blendOverlay( float base, float blend ) {', - - ' return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );', - - '}', - - 'vec3 blendOverlay( vec3 base, vec3 blend ) {', + } - ' return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );', + vec3 blendOverlay( vec3 base, vec3 blend ) { - '}', + return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) ); - 'void main() {', + } - ' vec4 base = texture2DProj( tDiffuse, vUv );', + void main() { - ' gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );', + vec4 base = texture2DProj( tDiffuse, vUv ); + gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 ); - '}' + }` - ].join( '\n' ) }; export { Refractor }; diff --git a/examples/jsm/objects/ShadowMesh.js b/examples/jsm/objects/ShadowMesh.js index 3f91122c267079..dfbc6081bebd55 100644 --- a/examples/jsm/objects/ShadowMesh.js +++ b/examples/jsm/objects/ShadowMesh.js @@ -8,43 +8,40 @@ import { * A shadow Mesh that follows a shadow-casting Mesh in the scene, but is confined to a single plane. */ -var ShadowMesh = function ( mesh ) { +const _shadowMatrix = new Matrix4(); - var shadowMaterial = new MeshBasicMaterial( { +class ShadowMesh extends Mesh { - color: 0x000000, - transparent: true, - opacity: 0.6, - depthWrite: false + constructor( mesh ) { - } ); + const shadowMaterial = new MeshBasicMaterial( { - Mesh.call( this, mesh.geometry, shadowMaterial ); + color: 0x000000, + transparent: true, + opacity: 0.6, + depthWrite: false - this.meshMatrix = mesh.matrixWorld; + } ); - this.frustumCulled = false; - this.matrixAutoUpdate = false; + super( mesh.geometry, shadowMaterial ); -}; + this.meshMatrix = mesh.matrixWorld; -ShadowMesh.prototype = Object.create( Mesh.prototype ); -ShadowMesh.prototype.constructor = ShadowMesh; + this.frustumCulled = false; + this.matrixAutoUpdate = false; -ShadowMesh.prototype.update = function () { + } - var shadowMatrix = new Matrix4(); - - return function ( plane, lightPosition4D ) { + update( plane, lightPosition4D ) { // based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm - var dot = plane.normal.x * lightPosition4D.x + + const dot = plane.normal.x * lightPosition4D.x + plane.normal.y * lightPosition4D.y + plane.normal.z * lightPosition4D.z + - plane.constant * lightPosition4D.w; - var sme = shadowMatrix.elements; + const sme = _shadowMatrix.elements; sme[ 0 ] = dot - lightPosition4D.x * plane.normal.x; sme[ 4 ] = - lightPosition4D.x * plane.normal.y; @@ -66,10 +63,12 @@ ShadowMesh.prototype.update = function () { sme[ 11 ] = - lightPosition4D.w * plane.normal.z; sme[ 15 ] = dot - lightPosition4D.w * - plane.constant; - this.matrix.multiplyMatrices( shadowMatrix, this.meshMatrix ); + this.matrix.multiplyMatrices( _shadowMatrix, this.meshMatrix ); + + } - }; +} -}(); +ShadowMesh.prototype.isShadowMesh = true; export { ShadowMesh }; diff --git a/examples/jsm/objects/Sky.js b/examples/jsm/objects/Sky.js index b6196b3b79f244..0c8c708fa2f99c 100644 --- a/examples/jsm/objects/Sky.js +++ b/examples/jsm/objects/Sky.js @@ -21,24 +21,28 @@ import { * Three.js integration by zz85 http://twitter.com/blurspline */ -var Sky = function () { +class Sky extends Mesh { - var shader = Sky.SkyShader; + constructor() { - var material = new ShaderMaterial( { - name: 'SkyShader', - fragmentShader: shader.fragmentShader, - vertexShader: shader.vertexShader, - uniforms: UniformsUtils.clone( shader.uniforms ), - side: BackSide, - depthWrite: false - } ); + const shader = Sky.SkyShader; - Mesh.call( this, new BoxGeometry( 1, 1, 1 ), material ); + const material = new ShaderMaterial( { + name: 'SkyShader', + fragmentShader: shader.fragmentShader, + vertexShader: shader.vertexShader, + uniforms: UniformsUtils.clone( shader.uniforms ), + side: BackSide, + depthWrite: false + } ); -}; + super( new BoxGeometry( 1, 1, 1 ), material ); + + } + +} -Sky.prototype = Object.create( Mesh.prototype ); +Sky.prototype.isSky = true; Sky.SkyShader = { @@ -51,166 +55,164 @@ Sky.SkyShader = { 'up': { value: new Vector3( 0, 1, 0 ) } }, - vertexShader: [ - 'uniform vec3 sunPosition;', - 'uniform float rayleigh;', - 'uniform float turbidity;', - 'uniform float mieCoefficient;', - 'uniform vec3 up;', + vertexShader: /* glsl */` + uniform vec3 sunPosition; + uniform float rayleigh; + uniform float turbidity; + uniform float mieCoefficient; + uniform vec3 up; - 'varying vec3 vWorldPosition;', - 'varying vec3 vSunDirection;', - 'varying float vSunfade;', - 'varying vec3 vBetaR;', - 'varying vec3 vBetaM;', - 'varying float vSunE;', + varying vec3 vWorldPosition; + varying vec3 vSunDirection; + varying float vSunfade; + varying vec3 vBetaR; + varying vec3 vBetaM; + varying float vSunE; // constants for atmospheric scattering - 'const float e = 2.71828182845904523536028747135266249775724709369995957;', - 'const float pi = 3.141592653589793238462643383279502884197169;', + const float e = 2.71828182845904523536028747135266249775724709369995957; + const float pi = 3.141592653589793238462643383279502884197169; // wavelength of used primaries, according to preetham - 'const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 );', + const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 ); // this pre-calcuation replaces older TotalRayleigh(vec3 lambda) function: // (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn)) - 'const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 );', + const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 ); // mie stuff // K coefficient for the primaries - 'const float v = 4.0;', - 'const vec3 K = vec3( 0.686, 0.678, 0.666 );', + const float v = 4.0; + const vec3 K = vec3( 0.686, 0.678, 0.666 ); // MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K - 'const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 );', + const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 ); // earth shadow hack // cutoffAngle = pi / 1.95; - 'const float cutoffAngle = 1.6110731556870734;', - 'const float steepness = 1.5;', - 'const float EE = 1000.0;', + const float cutoffAngle = 1.6110731556870734; + const float steepness = 1.5; + const float EE = 1000.0; - 'float sunIntensity( float zenithAngleCos ) {', - ' zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 );', - ' return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) );', - '}', + float sunIntensity( float zenithAngleCos ) { + zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 ); + return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) ); + } - 'vec3 totalMie( float T ) {', - ' float c = ( 0.2 * T ) * 10E-18;', - ' return 0.434 * c * MieConst;', - '}', + vec3 totalMie( float T ) { + float c = ( 0.2 * T ) * 10E-18; + return 0.434 * c * MieConst; + } - 'void main() {', + void main() { - ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', - ' vWorldPosition = worldPosition.xyz;', + vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); + vWorldPosition = worldPosition.xyz; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - ' gl_Position.z = gl_Position.w;', // set z to camera.far + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + gl_Position.z = gl_Position.w; // set z to camera.far - ' vSunDirection = normalize( sunPosition );', + vSunDirection = normalize( sunPosition ); - ' vSunE = sunIntensity( dot( vSunDirection, up ) );', + vSunE = sunIntensity( dot( vSunDirection, up ) ); - ' vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 );', + vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 ); - ' float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );', + float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) ); - // extinction (absorbtion + out scattering) - // rayleigh coefficients - ' vBetaR = totalRayleigh * rayleighCoefficient;', + // extinction (absorbtion + out scattering) + // rayleigh coefficients + vBetaR = totalRayleigh * rayleighCoefficient; - // mie coefficients - ' vBetaM = totalMie( turbidity ) * mieCoefficient;', + // mie coefficients + vBetaM = totalMie( turbidity ) * mieCoefficient; - '}' - ].join( '\n' ), + }`, - fragmentShader: [ - 'varying vec3 vWorldPosition;', - 'varying vec3 vSunDirection;', - 'varying float vSunfade;', - 'varying vec3 vBetaR;', - 'varying vec3 vBetaM;', - 'varying float vSunE;', + fragmentShader: /* glsl */` + varying vec3 vWorldPosition; + varying vec3 vSunDirection; + varying float vSunfade; + varying vec3 vBetaR; + varying vec3 vBetaM; + varying float vSunE; - 'uniform float mieDirectionalG;', - 'uniform vec3 up;', + uniform float mieDirectionalG; + uniform vec3 up; - 'const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );', + const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 ); // constants for atmospheric scattering - 'const float pi = 3.141592653589793238462643383279502884197169;', + const float pi = 3.141592653589793238462643383279502884197169; - 'const float n = 1.0003;', // refractive index of air - 'const float N = 2.545E25;', // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius) + const float n = 1.0003; // refractive index of air + const float N = 2.545E25; // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius) // optical length at zenith for molecules - 'const float rayleighZenithLength = 8.4E3;', - 'const float mieZenithLength = 1.25E3;', + const float rayleighZenithLength = 8.4E3; + const float mieZenithLength = 1.25E3; // 66 arc seconds -> degrees, and the cosine of that - 'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;', + const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324; // 3.0 / ( 16.0 * pi ) - 'const float THREE_OVER_SIXTEENPI = 0.05968310365946075;', + const float THREE_OVER_SIXTEENPI = 0.05968310365946075; // 1.0 / ( 4.0 * pi ) - 'const float ONE_OVER_FOURPI = 0.07957747154594767;', + const float ONE_OVER_FOURPI = 0.07957747154594767; - 'float rayleighPhase( float cosTheta ) {', - ' return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) );', - '}', + float rayleighPhase( float cosTheta ) { + return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) ); + } - 'float hgPhase( float cosTheta, float g ) {', - ' float g2 = pow( g, 2.0 );', - ' float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 );', - ' return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse );', - '}', + float hgPhase( float cosTheta, float g ) { + float g2 = pow( g, 2.0 ); + float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 ); + return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse ); + } - 'void main() {', + void main() { - ' vec3 direction = normalize( vWorldPosition - cameraPos );', + vec3 direction = normalize( vWorldPosition - cameraPos ); - // optical length - // cutoff angle at 90 to avoid singularity in next formula. - ' float zenithAngle = acos( max( 0.0, dot( up, direction ) ) );', - ' float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) );', - ' float sR = rayleighZenithLength * inverse;', - ' float sM = mieZenithLength * inverse;', + // optical length + // cutoff angle at 90 to avoid singularity in next formula. + float zenithAngle = acos( max( 0.0, dot( up, direction ) ) ); + float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) ); + float sR = rayleighZenithLength * inverse; + float sM = mieZenithLength * inverse; - // combined extinction factor - ' vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) );', + // combined extinction factor + vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) ); - // in scattering - ' float cosTheta = dot( direction, vSunDirection );', + // in scattering + float cosTheta = dot( direction, vSunDirection ); - ' float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 );', - ' vec3 betaRTheta = vBetaR * rPhase;', + float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 ); + vec3 betaRTheta = vBetaR * rPhase; - ' float mPhase = hgPhase( cosTheta, mieDirectionalG );', - ' vec3 betaMTheta = vBetaM * mPhase;', + float mPhase = hgPhase( cosTheta, mieDirectionalG ); + vec3 betaMTheta = vBetaM * mPhase; - ' vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) );', - ' Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) );', + vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) ); + Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) ); - // nightsky - ' float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2]', - ' float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2]', - ' vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 );', - ' vec3 L0 = vec3( 0.1 ) * Fex;', + // nightsky + float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2] + float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2] + vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 ); + vec3 L0 = vec3( 0.1 ) * Fex; - // composition + solar disc - ' float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );', - ' L0 += ( vSunE * 19000.0 * Fex ) * sundisk;', + // composition + solar disc + float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta ); + L0 += ( vSunE * 19000.0 * Fex ) * sundisk; - ' vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );', + vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 ); - ' vec3 retColor = pow( texColor, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) );', + vec3 retColor = pow( texColor, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) ); - ' gl_FragColor = vec4( retColor, 1.0 );', + gl_FragColor = vec4( retColor, 1.0 ); - '#include ', - '#include ', + #include + #include - '}' - ].join( '\n' ) + }` }; diff --git a/examples/jsm/objects/Water.js b/examples/jsm/objects/Water.js index ced3d5ab6a13a5..1c72a0373b8ad6 100644 --- a/examples/jsm/objects/Water.js +++ b/examples/jsm/objects/Water.js @@ -23,323 +23,322 @@ import { * http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL */ -var Water = function ( geometry, options ) { +class Water extends Mesh { - Mesh.call( this, geometry ); + constructor( geometry, options = {} ) { - var scope = this; + super( geometry ); - options = options || {}; + const scope = this; - var textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512; - var textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512; + const textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512; + const textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512; - var clipBias = options.clipBias !== undefined ? options.clipBias : 0.0; - var alpha = options.alpha !== undefined ? options.alpha : 1.0; - var time = options.time !== undefined ? options.time : 0.0; - var normalSampler = options.waterNormals !== undefined ? options.waterNormals : null; - var sunDirection = options.sunDirection !== undefined ? options.sunDirection : new Vector3( 0.70707, 0.70707, 0.0 ); - var sunColor = new Color( options.sunColor !== undefined ? options.sunColor : 0xffffff ); - var waterColor = new Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F ); - var eye = options.eye !== undefined ? options.eye : new Vector3( 0, 0, 0 ); - var distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0; - var side = options.side !== undefined ? options.side : FrontSide; - var fog = options.fog !== undefined ? options.fog : false; + const clipBias = options.clipBias !== undefined ? options.clipBias : 0.0; + const alpha = options.alpha !== undefined ? options.alpha : 1.0; + const time = options.time !== undefined ? options.time : 0.0; + const normalSampler = options.waterNormals !== undefined ? options.waterNormals : null; + const sunDirection = options.sunDirection !== undefined ? options.sunDirection : new Vector3( 0.70707, 0.70707, 0.0 ); + const sunColor = new Color( options.sunColor !== undefined ? options.sunColor : 0xffffff ); + const waterColor = new Color( options.waterColor !== undefined ? options.waterColor : 0x7F7F7F ); + const eye = options.eye !== undefined ? options.eye : new Vector3( 0, 0, 0 ); + const distortionScale = options.distortionScale !== undefined ? options.distortionScale : 20.0; + const side = options.side !== undefined ? options.side : FrontSide; + const fog = options.fog !== undefined ? options.fog : false; - // + // - var mirrorPlane = new Plane(); - var normal = new Vector3(); - var mirrorWorldPosition = new Vector3(); - var cameraWorldPosition = new Vector3(); - var rotationMatrix = new Matrix4(); - var lookAtPosition = new Vector3( 0, 0, - 1 ); - var clipPlane = new Vector4(); + const mirrorPlane = new Plane(); + const normal = new Vector3(); + const mirrorWorldPosition = new Vector3(); + const cameraWorldPosition = new Vector3(); + const rotationMatrix = new Matrix4(); + const lookAtPosition = new Vector3( 0, 0, - 1 ); + const clipPlane = new Vector4(); - var view = new Vector3(); - var target = new Vector3(); - var q = new Vector4(); + const view = new Vector3(); + const target = new Vector3(); + const q = new Vector4(); - var textureMatrix = new Matrix4(); + const textureMatrix = new Matrix4(); - var mirrorCamera = new PerspectiveCamera(); + const mirrorCamera = new PerspectiveCamera(); - var parameters = { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBFormat - }; + const parameters = { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBFormat + }; - var renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); + const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, parameters ); - if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { + if ( ! MathUtils.isPowerOfTwo( textureWidth ) || ! MathUtils.isPowerOfTwo( textureHeight ) ) { - renderTarget.texture.generateMipmaps = false; + renderTarget.texture.generateMipmaps = false; - } + } - var mirrorShader = { - - uniforms: UniformsUtils.merge( [ - UniformsLib[ 'fog' ], - UniformsLib[ 'lights' ], - { - 'normalSampler': { value: null }, - 'mirrorSampler': { value: null }, - 'alpha': { value: 1.0 }, - 'time': { value: 0.0 }, - 'size': { value: 1.0 }, - 'distortionScale': { value: 20.0 }, - 'textureMatrix': { value: new Matrix4() }, - 'sunColor': { value: new Color( 0x7F7F7F ) }, - 'sunDirection': { value: new Vector3( 0.70707, 0.70707, 0 ) }, - 'eye': { value: new Vector3() }, - 'waterColor': { value: new Color( 0x555555 ) } - } - ] ), - - vertexShader: [ - 'uniform mat4 textureMatrix;', - 'uniform float time;', - - 'varying vec4 mirrorCoord;', - 'varying vec4 worldPosition;', - - '#include ', - '#include ', - '#include ', - '#include ', - - 'void main() {', - ' mirrorCoord = modelMatrix * vec4( position, 1.0 );', - ' worldPosition = mirrorCoord.xyzw;', - ' mirrorCoord = textureMatrix * mirrorCoord;', - ' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );', - ' gl_Position = projectionMatrix * mvPosition;', - - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '}' - ].join( '\n' ), - - fragmentShader: [ - 'uniform sampler2D mirrorSampler;', - 'uniform float alpha;', - 'uniform float time;', - 'uniform float size;', - 'uniform float distortionScale;', - 'uniform sampler2D normalSampler;', - 'uniform vec3 sunColor;', - 'uniform vec3 sunDirection;', - 'uniform vec3 eye;', - 'uniform vec3 waterColor;', - - 'varying vec4 mirrorCoord;', - 'varying vec4 worldPosition;', - - 'vec4 getNoise( vec2 uv ) {', - ' vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);', - ' vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );', - ' vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );', - ' vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );', - ' vec4 noise = texture2D( normalSampler, uv0 ) +', - ' texture2D( normalSampler, uv1 ) +', - ' texture2D( normalSampler, uv2 ) +', - ' texture2D( normalSampler, uv3 );', - ' return noise * 0.5 - 1.0;', - '}', - - 'void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) {', - ' vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );', - ' float direction = max( 0.0, dot( eyeDirection, reflection ) );', - ' specularColor += pow( direction, shiny ) * sunColor * spec;', - ' diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;', - '}', - - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - '#include ', - - 'void main() {', - - '#include ', - ' vec4 noise = getNoise( worldPosition.xz * size );', - ' vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );', - - ' vec3 diffuseLight = vec3(0.0);', - ' vec3 specularLight = vec3(0.0);', - - ' vec3 worldToEye = eye-worldPosition.xyz;', - ' vec3 eyeDirection = normalize( worldToEye );', - ' sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );', - - ' float distance = length(worldToEye);', - - ' vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;', - ' vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) );', - - ' float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );', - ' float rf0 = 0.3;', - ' float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );', - ' vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;', - ' vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance);', - ' vec3 outgoingLight = albedo;', - ' gl_FragColor = vec4( outgoingLight, alpha );', - - '#include ', - '#include ', - '}' - ].join( '\n' ) - - }; - - var material = new ShaderMaterial( { - fragmentShader: mirrorShader.fragmentShader, - vertexShader: mirrorShader.vertexShader, - uniforms: UniformsUtils.clone( mirrorShader.uniforms ), - lights: true, - side: side, - fog: fog - } ); - - material.uniforms[ 'mirrorSampler' ].value = renderTarget.texture; - material.uniforms[ 'textureMatrix' ].value = textureMatrix; - material.uniforms[ 'alpha' ].value = alpha; - material.uniforms[ 'time' ].value = time; - material.uniforms[ 'normalSampler' ].value = normalSampler; - material.uniforms[ 'sunColor' ].value = sunColor; - material.uniforms[ 'waterColor' ].value = waterColor; - material.uniforms[ 'sunDirection' ].value = sunDirection; - material.uniforms[ 'distortionScale' ].value = distortionScale; + const mirrorShader = { + + uniforms: UniformsUtils.merge( [ + UniformsLib[ 'fog' ], + UniformsLib[ 'lights' ], + { + 'normalSampler': { value: null }, + 'mirrorSampler': { value: null }, + 'alpha': { value: 1.0 }, + 'time': { value: 0.0 }, + 'size': { value: 1.0 }, + 'distortionScale': { value: 20.0 }, + 'textureMatrix': { value: new Matrix4() }, + 'sunColor': { value: new Color( 0x7F7F7F ) }, + 'sunDirection': { value: new Vector3( 0.70707, 0.70707, 0 ) }, + 'eye': { value: new Vector3() }, + 'waterColor': { value: new Color( 0x555555 ) } + } + ] ), + + vertexShader: /* glsl */` + uniform mat4 textureMatrix; + uniform float time; + + varying vec4 mirrorCoord; + varying vec4 worldPosition; + + #include + #include + #include + #include + + void main() { + mirrorCoord = modelMatrix * vec4( position, 1.0 ); + worldPosition = mirrorCoord.xyzw; + mirrorCoord = textureMatrix * mirrorCoord; + vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); + gl_Position = projectionMatrix * mvPosition; + + #include + #include + #include + #include + #include + }`, + + fragmentShader: /* glsl */` + uniform sampler2D mirrorSampler; + uniform float alpha; + uniform float time; + uniform float size; + uniform float distortionScale; + uniform sampler2D normalSampler; + uniform vec3 sunColor; + uniform vec3 sunDirection; + uniform vec3 eye; + uniform vec3 waterColor; + + varying vec4 mirrorCoord; + varying vec4 worldPosition; + + vec4 getNoise( vec2 uv ) { + vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0); + vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 ); + vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 ); + vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 ); + vec4 noise = texture2D( normalSampler, uv0 ) + + texture2D( normalSampler, uv1 ) + + texture2D( normalSampler, uv2 ) + + texture2D( normalSampler, uv3 ); + return noise * 0.5 - 1.0; + } + + void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) { + vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) ); + float direction = max( 0.0, dot( eyeDirection, reflection ) ); + specularColor += pow( direction, shiny ) * sunColor * spec; + diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse; + } + + #include + #include + #include + #include + #include + #include + #include + #include + + void main() { + + #include + vec4 noise = getNoise( worldPosition.xz * size ); + vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) ); + + vec3 diffuseLight = vec3(0.0); + vec3 specularLight = vec3(0.0); + + vec3 worldToEye = eye-worldPosition.xyz; + vec3 eyeDirection = normalize( worldToEye ); + sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight ); + + float distance = length(worldToEye); + + vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale; + vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) ); + + float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 ); + float rf0 = 0.3; + float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 ); + vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor; + vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance); + vec3 outgoingLight = albedo; + gl_FragColor = vec4( outgoingLight, alpha ); + + #include + #include + }` + + }; + + const material = new ShaderMaterial( { + fragmentShader: mirrorShader.fragmentShader, + vertexShader: mirrorShader.vertexShader, + uniforms: UniformsUtils.clone( mirrorShader.uniforms ), + lights: true, + side: side, + fog: fog + } ); + + material.uniforms[ 'mirrorSampler' ].value = renderTarget.texture; + material.uniforms[ 'textureMatrix' ].value = textureMatrix; + material.uniforms[ 'alpha' ].value = alpha; + material.uniforms[ 'time' ].value = time; + material.uniforms[ 'normalSampler' ].value = normalSampler; + material.uniforms[ 'sunColor' ].value = sunColor; + material.uniforms[ 'waterColor' ].value = waterColor; + material.uniforms[ 'sunDirection' ].value = sunDirection; + material.uniforms[ 'distortionScale' ].value = distortionScale; - material.uniforms[ 'eye' ].value = eye; + material.uniforms[ 'eye' ].value = eye; - scope.material = material; + scope.material = material; - scope.onBeforeRender = function ( renderer, scene, camera ) { + scope.onBeforeRender = function ( renderer, scene, camera ) { - mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); - cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); + mirrorWorldPosition.setFromMatrixPosition( scope.matrixWorld ); + cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); - rotationMatrix.extractRotation( scope.matrixWorld ); + rotationMatrix.extractRotation( scope.matrixWorld ); - normal.set( 0, 0, 1 ); - normal.applyMatrix4( rotationMatrix ); + normal.set( 0, 0, 1 ); + normal.applyMatrix4( rotationMatrix ); - view.subVectors( mirrorWorldPosition, cameraWorldPosition ); + view.subVectors( mirrorWorldPosition, cameraWorldPosition ); - // Avoid rendering when mirror is facing away + // Avoid rendering when mirror is facing away - if ( view.dot( normal ) > 0 ) return; + if ( view.dot( normal ) > 0 ) return; - view.reflect( normal ).negate(); - view.add( mirrorWorldPosition ); + view.reflect( normal ).negate(); + view.add( mirrorWorldPosition ); - rotationMatrix.extractRotation( camera.matrixWorld ); + rotationMatrix.extractRotation( camera.matrixWorld ); - lookAtPosition.set( 0, 0, - 1 ); - lookAtPosition.applyMatrix4( rotationMatrix ); - lookAtPosition.add( cameraWorldPosition ); + lookAtPosition.set( 0, 0, - 1 ); + lookAtPosition.applyMatrix4( rotationMatrix ); + lookAtPosition.add( cameraWorldPosition ); - target.subVectors( mirrorWorldPosition, lookAtPosition ); - target.reflect( normal ).negate(); - target.add( mirrorWorldPosition ); + target.subVectors( mirrorWorldPosition, lookAtPosition ); + target.reflect( normal ).negate(); + target.add( mirrorWorldPosition ); - mirrorCamera.position.copy( view ); - mirrorCamera.up.set( 0, 1, 0 ); - mirrorCamera.up.applyMatrix4( rotationMatrix ); - mirrorCamera.up.reflect( normal ); - mirrorCamera.lookAt( target ); + mirrorCamera.position.copy( view ); + mirrorCamera.up.set( 0, 1, 0 ); + mirrorCamera.up.applyMatrix4( rotationMatrix ); + mirrorCamera.up.reflect( normal ); + mirrorCamera.lookAt( target ); - mirrorCamera.far = camera.far; // Used in WebGLBackground + mirrorCamera.far = camera.far; // Used in WebGLBackground - mirrorCamera.updateMatrixWorld(); - mirrorCamera.projectionMatrix.copy( camera.projectionMatrix ); + mirrorCamera.updateMatrixWorld(); + mirrorCamera.projectionMatrix.copy( camera.projectionMatrix ); - // Update the texture matrix - textureMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - textureMatrix.multiply( mirrorCamera.projectionMatrix ); - textureMatrix.multiply( mirrorCamera.matrixWorldInverse ); + // Update the texture matrix + textureMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); + textureMatrix.multiply( mirrorCamera.projectionMatrix ); + textureMatrix.multiply( mirrorCamera.matrixWorldInverse ); - // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html - // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition ); - mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse ); + // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html + // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf + mirrorPlane.setFromNormalAndCoplanarPoint( normal, mirrorWorldPosition ); + mirrorPlane.applyMatrix4( mirrorCamera.matrixWorldInverse ); - clipPlane.set( mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant ); + clipPlane.set( mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant ); - var projectionMatrix = mirrorCamera.projectionMatrix; + const projectionMatrix = mirrorCamera.projectionMatrix; - q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; - q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; - q.z = - 1.0; - q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; + q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; + q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; + q.z = - 1.0; + q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; - // Calculate the scaled plane vector - clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); + // Calculate the scaled plane vector + clipPlane.multiplyScalar( 2.0 / clipPlane.dot( q ) ); - // Replacing the third row of the projection matrix - projectionMatrix.elements[ 2 ] = clipPlane.x; - projectionMatrix.elements[ 6 ] = clipPlane.y; - projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias; - projectionMatrix.elements[ 14 ] = clipPlane.w; + // Replacing the third row of the projection matrix + projectionMatrix.elements[ 2 ] = clipPlane.x; + projectionMatrix.elements[ 6 ] = clipPlane.y; + projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias; + projectionMatrix.elements[ 14 ] = clipPlane.w; - eye.setFromMatrixPosition( camera.matrixWorld ); + eye.setFromMatrixPosition( camera.matrixWorld ); - // Render + // Render - var currentRenderTarget = renderer.getRenderTarget(); + const currentRenderTarget = renderer.getRenderTarget(); - var currentXrEnabled = renderer.xr.enabled; - var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; + const currentXrEnabled = renderer.xr.enabled; + const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; - scope.visible = false; + scope.visible = false; - renderer.xr.enabled = false; // Avoid camera modification and recursion - renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows + renderer.xr.enabled = false; // Avoid camera modification and recursion + renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows - renderer.setRenderTarget( renderTarget ); + renderer.setRenderTarget( renderTarget ); - renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897 + renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897 - if ( renderer.autoClear === false ) renderer.clear(); - renderer.render( scene, mirrorCamera ); + if ( renderer.autoClear === false ) renderer.clear(); + renderer.render( scene, mirrorCamera ); - scope.visible = true; + scope.visible = true; - renderer.xr.enabled = currentXrEnabled; - renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; + renderer.xr.enabled = currentXrEnabled; + renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; - renderer.setRenderTarget( currentRenderTarget ); + renderer.setRenderTarget( currentRenderTarget ); - // Restore viewport + // Restore viewport - var viewport = camera.viewport; + const viewport = camera.viewport; - if ( viewport !== undefined ) { + if ( viewport !== undefined ) { - renderer.state.viewport( viewport ); + renderer.state.viewport( viewport ); - } + } + + }; - }; + } -}; +} -Water.prototype = Object.create( Mesh.prototype ); -Water.prototype.constructor = Water; +Water.prototype.isWater = true; export { Water }; diff --git a/examples/jsm/objects/Water2.js b/examples/jsm/objects/Water2.js index bb98ca8343a3a5..80d9f43c2fc207 100644 --- a/examples/jsm/objects/Water2.js +++ b/examples/jsm/objects/Water2.js @@ -22,189 +22,190 @@ import { Refractor } from '../objects/Refractor.js'; * */ -var Water = function ( geometry, options ) { +class Water extends Mesh { - Mesh.call( this, geometry ); + constructor( geometry, options = {} ) { - this.type = 'Water'; + super( geometry ); - var scope = this; + this.type = 'Water'; - options = options || {}; + const scope = this; - var color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0xFFFFFF ); - var textureWidth = options.textureWidth || 512; - var textureHeight = options.textureHeight || 512; - var clipBias = options.clipBias || 0; - var flowDirection = options.flowDirection || new Vector2( 1, 0 ); - var flowSpeed = options.flowSpeed || 0.03; - var reflectivity = options.reflectivity || 0.02; - var scale = options.scale || 1; - var shader = options.shader || Water.WaterShader; - var encoding = options.encoding !== undefined ? options.encoding : LinearEncoding; + const color = ( options.color !== undefined ) ? new Color( options.color ) : new Color( 0xFFFFFF ); + const textureWidth = options.textureWidth || 512; + const textureHeight = options.textureHeight || 512; + const clipBias = options.clipBias || 0; + const flowDirection = options.flowDirection || new Vector2( 1, 0 ); + const flowSpeed = options.flowSpeed || 0.03; + const reflectivity = options.reflectivity || 0.02; + const scale = options.scale || 1; + const shader = options.shader || Water.WaterShader; + const encoding = options.encoding !== undefined ? options.encoding : LinearEncoding; - var textureLoader = new TextureLoader(); + const textureLoader = new TextureLoader(); - var flowMap = options.flowMap || undefined; - var normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' ); - var normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' ); + const flowMap = options.flowMap || undefined; + const normalMap0 = options.normalMap0 || textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' ); + const normalMap1 = options.normalMap1 || textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' ); - var cycle = 0.15; // a cycle of a flow map phase - var halfCycle = cycle * 0.5; - var textureMatrix = new Matrix4(); - var clock = new Clock(); + const cycle = 0.15; // a cycle of a flow map phase + const halfCycle = cycle * 0.5; + const textureMatrix = new Matrix4(); + const clock = new Clock(); - // internal components + // internal components - if ( Reflector === undefined ) { + if ( Reflector === undefined ) { - console.error( 'THREE.Water: Required component Reflector not found.' ); - return; + console.error( 'THREE.Water: Required component Reflector not found.' ); + return; - } + } - if ( Refractor === undefined ) { + if ( Refractor === undefined ) { - console.error( 'THREE.Water: Required component Refractor not found.' ); - return; + console.error( 'THREE.Water: Required component Refractor not found.' ); + return; - } + } - var reflector = new Reflector( geometry, { - textureWidth: textureWidth, - textureHeight: textureHeight, - clipBias: clipBias, - encoding: encoding - } ); - - var refractor = new Refractor( geometry, { - textureWidth: textureWidth, - textureHeight: textureHeight, - clipBias: clipBias, - encoding: encoding - } ); - - reflector.matrixAutoUpdate = false; - refractor.matrixAutoUpdate = false; - - // material - - this.material = new ShaderMaterial( { - uniforms: UniformsUtils.merge( [ - UniformsLib[ 'fog' ], - shader.uniforms - ] ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader, - transparent: true, - fog: true - } ); - - if ( flowMap !== undefined ) { - - this.material.defines.USE_FLOWMAP = ''; - this.material.uniforms[ 'tFlowMap' ] = { - type: 't', - value: flowMap - }; + const reflector = new Reflector( geometry, { + textureWidth: textureWidth, + textureHeight: textureHeight, + clipBias: clipBias, + encoding: encoding + } ); + + const refractor = new Refractor( geometry, { + textureWidth: textureWidth, + textureHeight: textureHeight, + clipBias: clipBias, + encoding: encoding + } ); + + reflector.matrixAutoUpdate = false; + refractor.matrixAutoUpdate = false; + + // material + + this.material = new ShaderMaterial( { + uniforms: UniformsUtils.merge( [ + UniformsLib[ 'fog' ], + shader.uniforms + ] ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + transparent: true, + fog: true + } ); + + if ( flowMap !== undefined ) { + + this.material.defines.USE_FLOWMAP = ''; + this.material.uniforms[ 'tFlowMap' ] = { + type: 't', + value: flowMap + }; + + } else { + + this.material.uniforms[ 'flowDirection' ] = { + type: 'v2', + value: flowDirection + }; - } else { + } - this.material.uniforms[ 'flowDirection' ] = { - type: 'v2', - value: flowDirection - }; + // maps - } + normalMap0.wrapS = normalMap0.wrapT = RepeatWrapping; + normalMap1.wrapS = normalMap1.wrapT = RepeatWrapping; - // maps + this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture; + this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture; + this.material.uniforms[ 'tNormalMap0' ].value = normalMap0; + this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; - normalMap0.wrapS = normalMap0.wrapT = RepeatWrapping; - normalMap1.wrapS = normalMap1.wrapT = RepeatWrapping; + // water - this.material.uniforms[ 'tReflectionMap' ].value = reflector.getRenderTarget().texture; - this.material.uniforms[ 'tRefractionMap' ].value = refractor.getRenderTarget().texture; - this.material.uniforms[ 'tNormalMap0' ].value = normalMap0; - this.material.uniforms[ 'tNormalMap1' ].value = normalMap1; + this.material.uniforms[ 'color' ].value = color; + this.material.uniforms[ 'reflectivity' ].value = reflectivity; + this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; - // water + // inital values - this.material.uniforms[ 'color' ].value = color; - this.material.uniforms[ 'reflectivity' ].value = reflectivity; - this.material.uniforms[ 'textureMatrix' ].value = textureMatrix; + this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0 + this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1 + this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle + this.material.uniforms[ 'config' ].value.w = scale; // scale - // inital values + // functions - this.material.uniforms[ 'config' ].value.x = 0; // flowMapOffset0 - this.material.uniforms[ 'config' ].value.y = halfCycle; // flowMapOffset1 - this.material.uniforms[ 'config' ].value.z = halfCycle; // halfCycle - this.material.uniforms[ 'config' ].value.w = scale; // scale + function updateTextureMatrix( camera ) { - // functions + textureMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - function updateTextureMatrix( camera ) { + textureMatrix.multiply( camera.projectionMatrix ); + textureMatrix.multiply( camera.matrixWorldInverse ); + textureMatrix.multiply( scope.matrixWorld ); - textureMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - - textureMatrix.multiply( camera.projectionMatrix ); - textureMatrix.multiply( camera.matrixWorldInverse ); - textureMatrix.multiply( scope.matrixWorld ); + } - } + function updateFlow() { - function updateFlow() { + const delta = clock.getDelta(); + const config = scope.material.uniforms[ 'config' ]; - var delta = clock.getDelta(); - var config = scope.material.uniforms[ 'config' ]; + config.value.x += flowSpeed * delta; // flowMapOffset0 + config.value.y = config.value.x + halfCycle; // flowMapOffset1 - config.value.x += flowSpeed * delta; // flowMapOffset0 - config.value.y = config.value.x + halfCycle; // flowMapOffset1 + // Important: The distance between offsets should be always the value of "halfCycle". + // Moreover, both offsets should be in the range of [ 0, cycle ]. + // This approach ensures a smooth water flow and avoids "reset" effects. - // Important: The distance between offsets should be always the value of "halfCycle". - // Moreover, both offsets should be in the range of [ 0, cycle ]. - // This approach ensures a smooth water flow and avoids "reset" effects. + if ( config.value.x >= cycle ) { - if ( config.value.x >= cycle ) { + config.value.x = 0; + config.value.y = halfCycle; - config.value.x = 0; - config.value.y = halfCycle; + } else if ( config.value.y >= cycle ) { - } else if ( config.value.y >= cycle ) { + config.value.y = config.value.y - cycle; - config.value.y = config.value.y - cycle; + } } - } + // - // + this.onBeforeRender = function ( renderer, scene, camera ) { - this.onBeforeRender = function ( renderer, scene, camera ) { + updateTextureMatrix( camera ); + updateFlow(); - updateTextureMatrix( camera ); - updateFlow(); + scope.visible = false; - scope.visible = false; + reflector.matrixWorld.copy( scope.matrixWorld ); + refractor.matrixWorld.copy( scope.matrixWorld ); - reflector.matrixWorld.copy( scope.matrixWorld ); - refractor.matrixWorld.copy( scope.matrixWorld ); + reflector.onBeforeRender( renderer, scene, camera ); + refractor.onBeforeRender( renderer, scene, camera ); - reflector.onBeforeRender( renderer, scene, camera ); - refractor.onBeforeRender( renderer, scene, camera ); + scope.visible = true; - scope.visible = true; + }; - }; + } -}; +} -Water.prototype = Object.create( Mesh.prototype ); -Water.prototype.constructor = Water; +Water.prototype.isWater = true; Water.WaterShader = { @@ -252,113 +253,110 @@ Water.WaterShader = { }, - vertexShader: [ - - '#include ', - '#include ', - '#include ', + vertexShader: /* glsl */` - 'uniform mat4 textureMatrix;', + #include + #include + #include - 'varying vec4 vCoord;', - 'varying vec2 vUv;', - 'varying vec3 vToEye;', + uniform mat4 textureMatrix; - 'void main() {', + varying vec4 vCoord; + varying vec2 vUv; + varying vec3 vToEye; - ' vUv = uv;', - ' vCoord = textureMatrix * vec4( position, 1.0 );', + void main() { - ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', - ' vToEye = cameraPosition - worldPosition.xyz;', + vUv = uv; + vCoord = textureMatrix * vec4( position, 1.0 ); - ' vec4 mvPosition = viewMatrix * worldPosition;', // used in fog_vertex - ' gl_Position = projectionMatrix * mvPosition;', + vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); + vToEye = cameraPosition - worldPosition.xyz; - ' #include ', - ' #include ', + vec4 mvPosition = viewMatrix * worldPosition; // used in fog_vertex + gl_Position = projectionMatrix * mvPosition; - '}' + #include + #include - ].join( '\n' ), + }`, - fragmentShader: [ + fragmentShader: /* glsl */` - '#include ', - '#include ', - '#include ', + #include + #include + #include - 'uniform sampler2D tReflectionMap;', - 'uniform sampler2D tRefractionMap;', - 'uniform sampler2D tNormalMap0;', - 'uniform sampler2D tNormalMap1;', + uniform sampler2D tReflectionMap; + uniform sampler2D tRefractionMap; + uniform sampler2D tNormalMap0; + uniform sampler2D tNormalMap1; - '#ifdef USE_FLOWMAP', - ' uniform sampler2D tFlowMap;', - '#else', - ' uniform vec2 flowDirection;', - '#endif', + #ifdef USE_FLOWMAP + uniform sampler2D tFlowMap; + #else + uniform vec2 flowDirection; + #endif - 'uniform vec3 color;', - 'uniform float reflectivity;', - 'uniform vec4 config;', + uniform vec3 color; + uniform float reflectivity; + uniform vec4 config; - 'varying vec4 vCoord;', - 'varying vec2 vUv;', - 'varying vec3 vToEye;', + varying vec4 vCoord; + varying vec2 vUv; + varying vec3 vToEye; - 'void main() {', + void main() { - ' #include ', + #include - ' float flowMapOffset0 = config.x;', - ' float flowMapOffset1 = config.y;', - ' float halfCycle = config.z;', - ' float scale = config.w;', + float flowMapOffset0 = config.x; + float flowMapOffset1 = config.y; + float halfCycle = config.z; + float scale = config.w; - ' vec3 toEye = normalize( vToEye );', + vec3 toEye = normalize( vToEye ); - // determine flow direction - ' vec2 flow;', - ' #ifdef USE_FLOWMAP', - ' flow = texture2D( tFlowMap, vUv ).rg * 2.0 - 1.0;', - ' #else', - ' flow = flowDirection;', - ' #endif', - ' flow.x *= - 1.0;', + // determine flow direction + vec2 flow; + #ifdef USE_FLOWMAP + flow = texture2D( tFlowMap, vUv ).rg * 2.0 - 1.0; + #else + flow = flowDirection; + #endif + flow.x *= - 1.0; - // sample normal maps (distort uvs with flowdata) - ' vec4 normalColor0 = texture2D( tNormalMap0, ( vUv * scale ) + flow * flowMapOffset0 );', - ' vec4 normalColor1 = texture2D( tNormalMap1, ( vUv * scale ) + flow * flowMapOffset1 );', + // sample normal maps (distort uvs with flowdata) + vec4 normalColor0 = texture2D( tNormalMap0, ( vUv * scale ) + flow * flowMapOffset0 ); + vec4 normalColor1 = texture2D( tNormalMap1, ( vUv * scale ) + flow * flowMapOffset1 ); - // linear interpolate to get the final normal color - ' float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle;', - ' vec4 normalColor = mix( normalColor0, normalColor1, flowLerp );', + // linear interpolate to get the final normal color + float flowLerp = abs( halfCycle - flowMapOffset0 ) / halfCycle; + vec4 normalColor = mix( normalColor0, normalColor1, flowLerp ); - // calculate normal vector - ' vec3 normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );', + // calculate normal vector + vec3 normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) ); - // calculate the fresnel term to blend reflection and refraction maps - ' float theta = max( dot( toEye, normal ), 0.0 );', - ' float reflectance = reflectivity + ( 1.0 - reflectivity ) * pow( ( 1.0 - theta ), 5.0 );', + // calculate the fresnel term to blend reflection and refraction maps + float theta = max( dot( toEye, normal ), 0.0 ); + float reflectance = reflectivity + ( 1.0 - reflectivity ) * pow( ( 1.0 - theta ), 5.0 ); - // calculate final uv coords - ' vec3 coord = vCoord.xyz / vCoord.w;', - ' vec2 uv = coord.xy + coord.z * normal.xz * 0.05;', + // calculate final uv coords + vec3 coord = vCoord.xyz / vCoord.w; + vec2 uv = coord.xy + coord.z * normal.xz * 0.05; - ' vec4 reflectColor = texture2D( tReflectionMap, vec2( 1.0 - uv.x, uv.y ) );', - ' vec4 refractColor = texture2D( tRefractionMap, uv );', + vec4 reflectColor = texture2D( tReflectionMap, vec2( 1.0 - uv.x, uv.y ) ); + vec4 refractColor = texture2D( tRefractionMap, uv ); - // multiply water color with the mix of both textures - ' gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );', + // multiply water color with the mix of both textures + gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance ); - ' #include ', - ' #include ', - ' #include ', + #include + #include + #include - '}' + }` - ].join( '\n' ) }; export { Water }; diff --git a/examples/jsm/physics/AmmoPhysics.js b/examples/jsm/physics/AmmoPhysics.js index e67178b567b47c..20e129f5c6566b 100644 --- a/examples/jsm/physics/AmmoPhysics.js +++ b/examples/jsm/physics/AmmoPhysics.js @@ -137,7 +137,6 @@ async function AmmoPhysics() { if ( mass > 0 ) { - mesh.instanceMatrix.setUsage( 35048 ); // THREE.DynamicDrawUsage = 35048 meshes.push( mesh ); meshMap.set( mesh, bodies ); diff --git a/examples/jsm/postprocessing/AdaptiveToneMappingPass.js b/examples/jsm/postprocessing/AdaptiveToneMappingPass.js index 4bc12b9c5b3b97..ded11f467dd3d3 100644 --- a/examples/jsm/postprocessing/AdaptiveToneMappingPass.js +++ b/examples/jsm/postprocessing/AdaptiveToneMappingPass.js @@ -8,7 +8,7 @@ import { UniformsUtils, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; import { LuminosityShader } from '../shaders/LuminosityShader.js'; import { ToneMapShader } from '../shaders/ToneMapShader.js'; @@ -21,125 +21,122 @@ import { ToneMapShader } from '../shaders/ToneMapShader.js'; * Full-screen tone-mapping shader based on http://www.graphics.cornell.edu/~jaf/publications/sig02_paper.pdf */ -var AdaptiveToneMappingPass = function ( adaptive, resolution ) { +class AdaptiveToneMappingPass extends Pass { - Pass.call( this ); + constructor( adaptive, resolution ) { - this.resolution = ( resolution !== undefined ) ? resolution : 256; - this.needsInit = true; - this.adaptive = adaptive !== undefined ? !! adaptive : true; + super(); - this.luminanceRT = null; - this.previousLuminanceRT = null; - this.currentLuminanceRT = null; + this.resolution = ( resolution !== undefined ) ? resolution : 256; + this.needsInit = true; + this.adaptive = adaptive !== undefined ? !! adaptive : true; - if ( CopyShader === undefined ) - console.error( 'THREE.AdaptiveToneMappingPass relies on CopyShader' ); + this.luminanceRT = null; + this.previousLuminanceRT = null; + this.currentLuminanceRT = null; - var copyShader = CopyShader; + if ( CopyShader === undefined ) console.error( 'THREE.AdaptiveToneMappingPass relies on CopyShader' ); - this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); + const copyShader = CopyShader; - this.materialCopy = new ShaderMaterial( { + this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); - uniforms: this.copyUniforms, - vertexShader: copyShader.vertexShader, - fragmentShader: copyShader.fragmentShader, - blending: NoBlending, - depthTest: false + this.materialCopy = new ShaderMaterial( { - } ); + uniforms: this.copyUniforms, + vertexShader: copyShader.vertexShader, + fragmentShader: copyShader.fragmentShader, + blending: NoBlending, + depthTest: false - if ( LuminosityShader === undefined ) - console.error( 'THREE.AdaptiveToneMappingPass relies on LuminosityShader' ); + } ); - this.materialLuminance = new ShaderMaterial( { + if ( LuminosityShader === undefined ) + console.error( 'THREE.AdaptiveToneMappingPass relies on LuminosityShader' ); - uniforms: UniformsUtils.clone( LuminosityShader.uniforms ), - vertexShader: LuminosityShader.vertexShader, - fragmentShader: LuminosityShader.fragmentShader, - blending: NoBlending - } ); + this.materialLuminance = new ShaderMaterial( { - this.adaptLuminanceShader = { - defines: { - 'MIP_LEVEL_1X1': ( Math.log( this.resolution ) / Math.log( 2.0 ) ).toFixed( 1 ) - }, - uniforms: { - 'lastLum': { value: null }, - 'currentLum': { value: null }, - 'minLuminance': { value: 0.01 }, - 'delta': { value: 0.016 }, - 'tau': { value: 1.0 } - }, - vertexShader: [ - 'varying vec2 vUv;', + uniforms: UniformsUtils.clone( LuminosityShader.uniforms ), + vertexShader: LuminosityShader.vertexShader, + fragmentShader: LuminosityShader.fragmentShader, + blending: NoBlending + } ); - 'void main() {', + this.adaptLuminanceShader = { + defines: { + 'MIP_LEVEL_1X1': ( Math.log( this.resolution ) / Math.log( 2.0 ) ).toFixed( 1 ) + }, + uniforms: { + 'lastLum': { value: null }, + 'currentLum': { value: null }, + 'minLuminance': { value: 0.01 }, + 'delta': { value: 0.016 }, + 'tau': { value: 1.0 } + }, + vertexShader: + `varying vec2 vUv; - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + void main() { - '}' - ].join( '\n' ), - fragmentShader: [ - 'varying vec2 vUv;', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - 'uniform sampler2D lastLum;', - 'uniform sampler2D currentLum;', - 'uniform float minLuminance;', - 'uniform float delta;', - 'uniform float tau;', + }`, - 'void main() {', + fragmentShader: + `varying vec2 vUv; - ' vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 );', - ' vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 );', + uniform sampler2D lastLum; + uniform sampler2D currentLum; + uniform float minLuminance; + uniform float delta; + uniform float tau; - ' float fLastLum = max( minLuminance, lastLum.r );', - ' float fCurrentLum = max( minLuminance, currentLum.r );', + void main() { - //The adaption seems to work better in extreme lighting differences - //if the input luminance is squared. - ' fCurrentLum *= fCurrentLum;', + vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 ); + vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 ); - // Adapt the luminance using Pattanaik's technique - ' float fAdaptedLum = fLastLum + (fCurrentLum - fLastLum) * (1.0 - exp(-delta * tau));', - // "fAdaptedLum = sqrt(fAdaptedLum);", - ' gl_FragColor.r = fAdaptedLum;', - '}' - ].join( '\n' ) - }; + float fLastLum = max( minLuminance, lastLum.r ); + float fCurrentLum = max( minLuminance, currentLum.r ); - this.materialAdaptiveLum = new ShaderMaterial( { + //The adaption seems to work better in extreme lighting differences + //if the input luminance is squared. + fCurrentLum *= fCurrentLum; - uniforms: UniformsUtils.clone( this.adaptLuminanceShader.uniforms ), - vertexShader: this.adaptLuminanceShader.vertexShader, - fragmentShader: this.adaptLuminanceShader.fragmentShader, - defines: Object.assign( {}, this.adaptLuminanceShader.defines ), - blending: NoBlending - } ); + // Adapt the luminance using Pattanaik's technique + float fAdaptedLum = fLastLum + (fCurrentLum - fLastLum) * (1.0 - exp(-delta * tau)); + // "fAdaptedLum = sqrt(fAdaptedLum); + gl_FragColor.r = fAdaptedLum; + }` - if ( ToneMapShader === undefined ) - console.error( 'THREE.AdaptiveToneMappingPass relies on ToneMapShader' ); + }; - this.materialToneMap = new ShaderMaterial( { + this.materialAdaptiveLum = new ShaderMaterial( { - uniforms: UniformsUtils.clone( ToneMapShader.uniforms ), - vertexShader: ToneMapShader.vertexShader, - fragmentShader: ToneMapShader.fragmentShader, - blending: NoBlending - } ); + uniforms: UniformsUtils.clone( this.adaptLuminanceShader.uniforms ), + vertexShader: this.adaptLuminanceShader.vertexShader, + fragmentShader: this.adaptLuminanceShader.fragmentShader, + defines: Object.assign( {}, this.adaptLuminanceShader.defines ), + blending: NoBlending + } ); - this.fsQuad = new Pass.FullScreenQuad( null ); + if ( ToneMapShader === undefined ) + console.error( 'THREE.AdaptiveToneMappingPass relies on ToneMapShader' ); -}; + this.materialToneMap = new ShaderMaterial( { -AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype ), { + uniforms: UniformsUtils.clone( ToneMapShader.uniforms ), + vertexShader: ToneMapShader.vertexShader, + fragmentShader: ToneMapShader.fragmentShader, + blending: NoBlending + } ); - constructor: AdaptiveToneMappingPass, + this.fsQuad = new FullScreenQuad( null ); - render: function ( renderer, writeBuffer, readBuffer, deltaTime/*, maskActive*/ ) { + } + + render( renderer, writeBuffer, readBuffer, deltaTime/*, maskActive*/ ) { if ( this.needsInit ) { @@ -195,9 +192,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - }, + } - reset: function () { + reset() { // render targets if ( this.luminanceRT ) { @@ -218,7 +215,7 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; // was RGB format. changed to RGBA format. see discussion in #8415 / #8450 + const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; // was RGB format. changed to RGBA format. see discussion in #8415 / #8450 this.luminanceRT = new WebGLRenderTarget( this.resolution, this.resolution, pars ); this.luminanceRT.texture.name = 'AdaptiveToneMappingPass.l'; @@ -250,9 +247,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype // renderer.render( this.scene, this.camera, this.previousLuminanceRT ); // renderer.render( this.scene, this.camera, this.currentLuminanceRT ); - }, + } - setAdaptive: function ( adaptive ) { + setAdaptive( adaptive ) { if ( adaptive ) { @@ -270,9 +267,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype this.materialToneMap.needsUpdate = true; - }, + } - setAdaptionRate: function ( rate ) { + setAdaptionRate( rate ) { if ( rate ) { @@ -280,9 +277,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - }, + } - setMinLuminance: function ( minLum ) { + setMinLuminance( minLum ) { if ( minLum ) { @@ -291,9 +288,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - }, + } - setMaxLuminance: function ( maxLum ) { + setMaxLuminance( maxLum ) { if ( maxLum ) { @@ -301,9 +298,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - }, + } - setAverageLuminance: function ( avgLum ) { + setAverageLuminance( avgLum ) { if ( avgLum ) { @@ -311,9 +308,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - }, + } - setMiddleGrey: function ( middleGrey ) { + setMiddleGrey( middleGrey ) { if ( middleGrey ) { @@ -321,9 +318,9 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } - }, + } - dispose: function () { + dispose() { if ( this.luminanceRT ) { @@ -369,6 +366,6 @@ AdaptiveToneMappingPass.prototype = Object.assign( Object.create( Pass.prototype } -} ); +} export { AdaptiveToneMappingPass }; diff --git a/examples/jsm/postprocessing/AfterimagePass.js b/examples/jsm/postprocessing/AfterimagePass.js index bef8ec099f0959..ef5bb5b32583b9 100644 --- a/examples/jsm/postprocessing/AfterimagePass.js +++ b/examples/jsm/postprocessing/AfterimagePass.js @@ -7,58 +7,55 @@ import { UniformsUtils, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { AfterimageShader } from '../shaders/AfterimageShader.js'; -var AfterimagePass = function ( damp ) { +class AfterimagePass extends Pass { - Pass.call( this ); + constructor( damp = 0.96 ) { - if ( AfterimageShader === undefined ) - console.error( 'THREE.AfterimagePass relies on AfterimageShader' ); + super(); - this.shader = AfterimageShader; + if ( AfterimageShader === undefined ) console.error( 'THREE.AfterimagePass relies on AfterimageShader' ); - this.uniforms = UniformsUtils.clone( this.shader.uniforms ); + this.shader = AfterimageShader; - this.uniforms[ 'damp' ].value = damp !== undefined ? damp : 0.96; + this.uniforms = UniformsUtils.clone( this.shader.uniforms ); - this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { + this.uniforms[ 'damp' ].value = damp; - minFilter: LinearFilter, - magFilter: NearestFilter, - format: RGBAFormat + this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { - } ); + minFilter: LinearFilter, + magFilter: NearestFilter, + format: RGBAFormat - this.textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { + } ); - minFilter: LinearFilter, - magFilter: NearestFilter, - format: RGBAFormat + this.textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { - } ); + minFilter: LinearFilter, + magFilter: NearestFilter, + format: RGBAFormat - this.shaderMaterial = new ShaderMaterial( { + } ); - uniforms: this.uniforms, - vertexShader: this.shader.vertexShader, - fragmentShader: this.shader.fragmentShader + this.shaderMaterial = new ShaderMaterial( { - } ); + uniforms: this.uniforms, + vertexShader: this.shader.vertexShader, + fragmentShader: this.shader.fragmentShader - this.compFsQuad = new Pass.FullScreenQuad( this.shaderMaterial ); + } ); - var material = new MeshBasicMaterial(); - this.copyFsQuad = new Pass.FullScreenQuad( material ); + this.compFsQuad = new FullScreenQuad( this.shaderMaterial ); -}; + const material = new MeshBasicMaterial(); + this.copyFsQuad = new FullScreenQuad( material ); -AfterimagePass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: AfterimagePass, + } - render: function ( renderer, writeBuffer, readBuffer ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { this.uniforms[ 'tOld' ].value = this.textureOld.texture; this.uniforms[ 'tNew' ].value = readBuffer.texture; @@ -84,20 +81,20 @@ AfterimagePass.prototype = Object.assign( Object.create( Pass.prototype ), { } // Swap buffers. - var temp = this.textureOld; + const temp = this.textureOld; this.textureOld = this.textureComp; this.textureComp = temp; // Now textureOld contains the latest image, ready for the next frame. - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.textureComp.setSize( width, height ); this.textureOld.setSize( width, height ); } -} ); +} export { AfterimagePass }; diff --git a/examples/jsm/postprocessing/BloomPass.js b/examples/jsm/postprocessing/BloomPass.js index 01b037d840d536..0684d65011df68 100644 --- a/examples/jsm/postprocessing/BloomPass.js +++ b/examples/jsm/postprocessing/BloomPass.js @@ -7,84 +7,75 @@ import { Vector2, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; import { ConvolutionShader } from '../shaders/ConvolutionShader.js'; -var BloomPass = function ( strength, kernelSize, sigma, resolution ) { +class BloomPass extends Pass { - Pass.call( this ); + constructor( strength = 1, kernelSize = 25, sigma = 4, resolution = 256 ) { - strength = ( strength !== undefined ) ? strength : 1; - kernelSize = ( kernelSize !== undefined ) ? kernelSize : 25; - sigma = ( sigma !== undefined ) ? sigma : 4.0; - resolution = ( resolution !== undefined ) ? resolution : 256; + super(); - // render targets + // render targets - var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; + const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; - this.renderTargetX = new WebGLRenderTarget( resolution, resolution, pars ); - this.renderTargetX.texture.name = 'BloomPass.x'; - this.renderTargetY = new WebGLRenderTarget( resolution, resolution, pars ); - this.renderTargetY.texture.name = 'BloomPass.y'; + this.renderTargetX = new WebGLRenderTarget( resolution, resolution, pars ); + this.renderTargetX.texture.name = 'BloomPass.x'; + this.renderTargetY = new WebGLRenderTarget( resolution, resolution, pars ); + this.renderTargetY.texture.name = 'BloomPass.y'; - // copy material + // copy material - if ( CopyShader === undefined ) - console.error( 'THREE.BloomPass relies on CopyShader' ); + if ( CopyShader === undefined ) console.error( 'THREE.BloomPass relies on CopyShader' ); - var copyShader = CopyShader; + const copyShader = CopyShader; - this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); + this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); - this.copyUniforms[ 'opacity' ].value = strength; + this.copyUniforms[ 'opacity' ].value = strength; - this.materialCopy = new ShaderMaterial( { + this.materialCopy = new ShaderMaterial( { - uniforms: this.copyUniforms, - vertexShader: copyShader.vertexShader, - fragmentShader: copyShader.fragmentShader, - blending: AdditiveBlending, - transparent: true + uniforms: this.copyUniforms, + vertexShader: copyShader.vertexShader, + fragmentShader: copyShader.fragmentShader, + blending: AdditiveBlending, + transparent: true - } ); + } ); - // convolution material + // convolution material - if ( ConvolutionShader === undefined ) - console.error( 'THREE.BloomPass relies on ConvolutionShader' ); + if ( ConvolutionShader === undefined ) console.error( 'THREE.BloomPass relies on ConvolutionShader' ); - var convolutionShader = ConvolutionShader; + const convolutionShader = ConvolutionShader; - this.convolutionUniforms = UniformsUtils.clone( convolutionShader.uniforms ); + this.convolutionUniforms = UniformsUtils.clone( convolutionShader.uniforms ); - this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX; - this.convolutionUniforms[ 'cKernel' ].value = ConvolutionShader.buildKernel( sigma ); - - this.materialConvolution = new ShaderMaterial( { - - uniforms: this.convolutionUniforms, - vertexShader: convolutionShader.vertexShader, - fragmentShader: convolutionShader.fragmentShader, - defines: { - 'KERNEL_SIZE_FLOAT': kernelSize.toFixed( 1 ), - 'KERNEL_SIZE_INT': kernelSize.toFixed( 0 ) - } + this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX; + this.convolutionUniforms[ 'cKernel' ].value = ConvolutionShader.buildKernel( sigma ); - } ); + this.materialConvolution = new ShaderMaterial( { - this.needsSwap = false; + uniforms: this.convolutionUniforms, + vertexShader: convolutionShader.vertexShader, + fragmentShader: convolutionShader.fragmentShader, + defines: { + 'KERNEL_SIZE_FLOAT': kernelSize.toFixed( 1 ), + 'KERNEL_SIZE_INT': kernelSize.toFixed( 0 ) + } - this.fsQuad = new Pass.FullScreenQuad( null ); + } ); -}; + this.needsSwap = false; -BloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.fsQuad = new FullScreenQuad( null ); - constructor: BloomPass, + } - render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { + render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); @@ -123,7 +114,7 @@ BloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} BloomPass.blurX = new Vector2( 0.001953125, 0.0 ); BloomPass.blurY = new Vector2( 0.0, 0.001953125 ); diff --git a/examples/jsm/postprocessing/BokehPass.js b/examples/jsm/postprocessing/BokehPass.js index a598a8d7458a4d..54fe24756c250b 100644 --- a/examples/jsm/postprocessing/BokehPass.js +++ b/examples/jsm/postprocessing/BokehPass.js @@ -8,92 +8,90 @@ import { UniformsUtils, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { BokehShader } from '../shaders/BokehShader.js'; /** * Depth-of-field post-process with bokeh shader */ -var BokehPass = function ( scene, camera, params ) { +class BokehPass extends Pass { - Pass.call( this ); + constructor( scene, camera, params ) { - this.scene = scene; - this.camera = camera; + super(); - var focus = ( params.focus !== undefined ) ? params.focus : 1.0; - var aspect = ( params.aspect !== undefined ) ? params.aspect : camera.aspect; - var aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025; - var maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0; + this.scene = scene; + this.camera = camera; - // render targets + const focus = ( params.focus !== undefined ) ? params.focus : 1.0; + const aspect = ( params.aspect !== undefined ) ? params.aspect : camera.aspect; + const aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025; + const maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0; - var width = params.width || window.innerWidth || 1; - var height = params.height || window.innerHeight || 1; + // render targets - this.renderTargetDepth = new WebGLRenderTarget( width, height, { - minFilter: NearestFilter, - magFilter: NearestFilter - } ); + const width = params.width || window.innerWidth || 1; + const height = params.height || window.innerHeight || 1; - this.renderTargetDepth.texture.name = 'BokehPass.depth'; + this.renderTargetDepth = new WebGLRenderTarget( width, height, { + minFilter: NearestFilter, + magFilter: NearestFilter + } ); - // depth material + this.renderTargetDepth.texture.name = 'BokehPass.depth'; - this.materialDepth = new MeshDepthMaterial(); - this.materialDepth.depthPacking = RGBADepthPacking; - this.materialDepth.blending = NoBlending; + // depth material - // bokeh material + this.materialDepth = new MeshDepthMaterial(); + this.materialDepth.depthPacking = RGBADepthPacking; + this.materialDepth.blending = NoBlending; - if ( BokehShader === undefined ) { + // bokeh material - console.error( 'THREE.BokehPass relies on BokehShader' ); + if ( BokehShader === undefined ) { - } - - var bokehShader = BokehShader; - var bokehUniforms = UniformsUtils.clone( bokehShader.uniforms ); + console.error( 'THREE.BokehPass relies on BokehShader' ); - bokehUniforms[ 'tDepth' ].value = this.renderTargetDepth.texture; + } - bokehUniforms[ 'focus' ].value = focus; - bokehUniforms[ 'aspect' ].value = aspect; - bokehUniforms[ 'aperture' ].value = aperture; - bokehUniforms[ 'maxblur' ].value = maxblur; - bokehUniforms[ 'nearClip' ].value = camera.near; - bokehUniforms[ 'farClip' ].value = camera.far; + const bokehShader = BokehShader; + const bokehUniforms = UniformsUtils.clone( bokehShader.uniforms ); - this.materialBokeh = new ShaderMaterial( { - defines: Object.assign( {}, bokehShader.defines ), - uniforms: bokehUniforms, - vertexShader: bokehShader.vertexShader, - fragmentShader: bokehShader.fragmentShader - } ); + bokehUniforms[ 'tDepth' ].value = this.renderTargetDepth.texture; - this.uniforms = bokehUniforms; - this.needsSwap = false; + bokehUniforms[ 'focus' ].value = focus; + bokehUniforms[ 'aspect' ].value = aspect; + bokehUniforms[ 'aperture' ].value = aperture; + bokehUniforms[ 'maxblur' ].value = maxblur; + bokehUniforms[ 'nearClip' ].value = camera.near; + bokehUniforms[ 'farClip' ].value = camera.far; - this.fsQuad = new Pass.FullScreenQuad( this.materialBokeh ); + this.materialBokeh = new ShaderMaterial( { + defines: Object.assign( {}, bokehShader.defines ), + uniforms: bokehUniforms, + vertexShader: bokehShader.vertexShader, + fragmentShader: bokehShader.fragmentShader + } ); - this._oldClearColor = new Color(); + this.uniforms = bokehUniforms; + this.needsSwap = false; -}; + this.fsQuad = new FullScreenQuad( this.materialBokeh ); -BokehPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this._oldClearColor = new Color(); - constructor: BokehPass, + } - render: function ( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { // Render depth into texture this.scene.overrideMaterial = this.materialDepth; renderer.getClearColor( this._oldClearColor ); - var oldClearAlpha = renderer.getClearAlpha(); - var oldAutoClear = renderer.autoClear; + const oldClearAlpha = renderer.getClearAlpha(); + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; renderer.setClearColor( 0xffffff ); @@ -128,6 +126,6 @@ BokehPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { BokehPass }; diff --git a/examples/jsm/postprocessing/ClearPass.js b/examples/jsm/postprocessing/ClearPass.js index 373a4b81a3e0b1..f533e2a3a8ac12 100644 --- a/examples/jsm/postprocessing/ClearPass.js +++ b/examples/jsm/postprocessing/ClearPass.js @@ -3,25 +3,23 @@ import { } from '../../../build/three.module.js'; import { Pass } from '../postprocessing/Pass.js'; -var ClearPass = function ( clearColor, clearAlpha ) { +class ClearPass extends Pass { - Pass.call( this ); + constructor( clearColor, clearAlpha ) { - this.needsSwap = false; + super(); - this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000; - this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; - this._oldClearColor = new Color(); + this.needsSwap = false; -}; + this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000; + this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; + this._oldClearColor = new Color(); -ClearPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: ClearPass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { - var oldClearAlpha; + let oldClearAlpha; if ( this.clearColor ) { @@ -43,6 +41,6 @@ ClearPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { ClearPass }; diff --git a/examples/jsm/postprocessing/CubeTexturePass.js b/examples/jsm/postprocessing/CubeTexturePass.js index 9a59f3e04ef84b..08273a4f7e089b 100644 --- a/examples/jsm/postprocessing/CubeTexturePass.js +++ b/examples/jsm/postprocessing/CubeTexturePass.js @@ -10,53 +10,51 @@ import { } from '../../../build/three.module.js'; import { Pass } from '../postprocessing/Pass.js'; -var CubeTexturePass = function ( camera, envMap, opacity ) { +class CubeTexturePass extends Pass { - Pass.call( this ); + constructor( camera, envMap, opacity = 1 ) { - this.camera = camera; + super(); - this.needsSwap = false; + this.camera = camera; - this.cubeShader = ShaderLib[ 'cube' ]; - this.cubeMesh = new Mesh( - new BoxGeometry( 10, 10, 10 ), - new ShaderMaterial( { - uniforms: UniformsUtils.clone( this.cubeShader.uniforms ), - vertexShader: this.cubeShader.vertexShader, - fragmentShader: this.cubeShader.fragmentShader, - depthTest: false, - depthWrite: false, - side: BackSide - } ) - ); + this.needsSwap = false; - Object.defineProperty( this.cubeMesh.material, 'envMap', { + this.cubeShader = ShaderLib[ 'cube' ]; + this.cubeMesh = new Mesh( + new BoxGeometry( 10, 10, 10 ), + new ShaderMaterial( { + uniforms: UniformsUtils.clone( this.cubeShader.uniforms ), + vertexShader: this.cubeShader.vertexShader, + fragmentShader: this.cubeShader.fragmentShader, + depthTest: false, + depthWrite: false, + side: BackSide + } ) + ); - get: function () { + Object.defineProperty( this.cubeMesh.material, 'envMap', { - return this.uniforms.envMap.value; + get: function () { - } + return this.uniforms.envMap.value; - } ); + } - this.envMap = envMap; - this.opacity = ( opacity !== undefined ) ? opacity : 1.0; + } ); - this.cubeScene = new Scene(); - this.cubeCamera = new PerspectiveCamera(); - this.cubeScene.add( this.cubeMesh ); + this.envMap = envMap; + this.opacity = opacity; -}; + this.cubeScene = new Scene(); + this.cubeCamera = new PerspectiveCamera(); + this.cubeScene.add( this.cubeMesh ); -CubeTexturePass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: CubeTexturePass, + } - render: function ( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { - var oldAutoClear = renderer.autoClear; + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; this.cubeCamera.projectionMatrix.copy( this.camera.projectionMatrix ); @@ -75,6 +73,6 @@ CubeTexturePass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { CubeTexturePass }; diff --git a/examples/jsm/postprocessing/DotScreenPass.js b/examples/jsm/postprocessing/DotScreenPass.js index 4e06ed1f5f5d07..4cbfd06136fcf9 100644 --- a/examples/jsm/postprocessing/DotScreenPass.js +++ b/examples/jsm/postprocessing/DotScreenPass.js @@ -2,41 +2,38 @@ import { ShaderMaterial, UniformsUtils } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { DotScreenShader } from '../shaders/DotScreenShader.js'; -var DotScreenPass = function ( center, angle, scale ) { +class DotScreenPass extends Pass { - Pass.call( this ); + constructor( center, angle, scale ) { - if ( DotScreenShader === undefined ) - console.error( 'THREE.DotScreenPass relies on DotScreenShader' ); + super(); - var shader = DotScreenShader; + if ( DotScreenShader === undefined ) console.error( 'THREE.DotScreenPass relies on DotScreenShader' ); - this.uniforms = UniformsUtils.clone( shader.uniforms ); + var shader = DotScreenShader; - if ( center !== undefined ) this.uniforms[ 'center' ].value.copy( center ); - if ( angle !== undefined ) this.uniforms[ 'angle' ].value = angle; - if ( scale !== undefined ) this.uniforms[ 'scale' ].value = scale; + this.uniforms = UniformsUtils.clone( shader.uniforms ); - this.material = new ShaderMaterial( { + if ( center !== undefined ) this.uniforms[ 'center' ].value.copy( center ); + if ( angle !== undefined ) this.uniforms[ 'angle' ].value = angle; + if ( scale !== undefined ) this.uniforms[ 'scale' ].value = scale; - uniforms: this.uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + this.material = new ShaderMaterial( { - } ); + uniforms: this.uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader - this.fsQuad = new Pass.FullScreenQuad( this.material ); + } ); -}; + this.fsQuad = new FullScreenQuad( this.material ); -DotScreenPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: DotScreenPass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { this.uniforms[ 'tDiffuse' ].value = readBuffer.texture; this.uniforms[ 'tSize' ].value.set( readBuffer.width, readBuffer.height ); @@ -56,6 +53,6 @@ DotScreenPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { DotScreenPass }; diff --git a/examples/jsm/postprocessing/EffectComposer.js b/examples/jsm/postprocessing/EffectComposer.js index b76da556be5b04..6e1c85b96abca5 100644 --- a/examples/jsm/postprocessing/EffectComposer.js +++ b/examples/jsm/postprocessing/EffectComposer.js @@ -14,90 +14,90 @@ import { ShaderPass } from '../postprocessing/ShaderPass.js'; import { MaskPass } from '../postprocessing/MaskPass.js'; import { ClearMaskPass } from '../postprocessing/MaskPass.js'; -var EffectComposer = function ( renderer, renderTarget ) { +class EffectComposer { - this.renderer = renderer; + constructor( renderer, renderTarget ) { - if ( renderTarget === undefined ) { + this.renderer = renderer; - var parameters = { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat - }; + if ( renderTarget === undefined ) { - var size = renderer.getSize( new Vector2() ); - this._pixelRatio = renderer.getPixelRatio(); - this._width = size.width; - this._height = size.height; + const parameters = { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBAFormat + }; - renderTarget = new WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, parameters ); - renderTarget.texture.name = 'EffectComposer.rt1'; + const size = renderer.getSize( new Vector2() ); + this._pixelRatio = renderer.getPixelRatio(); + this._width = size.width; + this._height = size.height; - } else { + renderTarget = new WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, parameters ); + renderTarget.texture.name = 'EffectComposer.rt1'; - this._pixelRatio = 1; - this._width = renderTarget.width; - this._height = renderTarget.height; + } else { - } + this._pixelRatio = 1; + this._width = renderTarget.width; + this._height = renderTarget.height; - this.renderTarget1 = renderTarget; - this.renderTarget2 = renderTarget.clone(); - this.renderTarget2.texture.name = 'EffectComposer.rt2'; + } - this.writeBuffer = this.renderTarget1; - this.readBuffer = this.renderTarget2; + this.renderTarget1 = renderTarget; + this.renderTarget2 = renderTarget.clone(); + this.renderTarget2.texture.name = 'EffectComposer.rt2'; - this.renderToScreen = true; + this.writeBuffer = this.renderTarget1; + this.readBuffer = this.renderTarget2; - this.passes = []; + this.renderToScreen = true; - // dependencies + this.passes = []; - if ( CopyShader === undefined ) { + // dependencies - console.error( 'THREE.EffectComposer relies on CopyShader' ); + if ( CopyShader === undefined ) { - } + console.error( 'THREE.EffectComposer relies on CopyShader' ); - if ( ShaderPass === undefined ) { + } - console.error( 'THREE.EffectComposer relies on ShaderPass' ); + if ( ShaderPass === undefined ) { - } + console.error( 'THREE.EffectComposer relies on ShaderPass' ); - this.copyPass = new ShaderPass( CopyShader ); + } - this.clock = new Clock(); + this.copyPass = new ShaderPass( CopyShader ); -}; + this.clock = new Clock(); -Object.assign( EffectComposer.prototype, { + } - swapBuffers: function () { + swapBuffers() { - var tmp = this.readBuffer; + const tmp = this.readBuffer; this.readBuffer = this.writeBuffer; this.writeBuffer = tmp; - }, + } - addPass: function ( pass ) { + addPass( pass ) { this.passes.push( pass ); pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); - }, + } - insertPass: function ( pass, index ) { + insertPass( pass, index ) { this.passes.splice( index, 0, pass ); pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); - }, + } - removePass: function ( pass ) { + removePass( pass ) { const index = this.passes.indexOf( pass ); @@ -107,11 +107,11 @@ Object.assign( EffectComposer.prototype, { } - }, + } - isLastEnabledPass: function ( passIndex ) { + isLastEnabledPass( passIndex ) { - for ( var i = passIndex + 1; i < this.passes.length; i ++ ) { + for ( let i = passIndex + 1; i < this.passes.length; i ++ ) { if ( this.passes[ i ].enabled ) { @@ -123,9 +123,9 @@ Object.assign( EffectComposer.prototype, { return true; - }, + } - render: function ( deltaTime ) { + render( deltaTime ) { // deltaTime value is in seconds @@ -135,15 +135,13 @@ Object.assign( EffectComposer.prototype, { } - var currentRenderTarget = this.renderer.getRenderTarget(); - - var maskActive = false; + const currentRenderTarget = this.renderer.getRenderTarget(); - var pass, i, il = this.passes.length; + let maskActive = false; - for ( i = 0; i < il; i ++ ) { + for ( let i = 0, il = this.passes.length; i < il; i ++ ) { - pass = this.passes[ i ]; + const pass = this.passes[ i ]; if ( pass.enabled === false ) continue; @@ -154,8 +152,8 @@ Object.assign( EffectComposer.prototype, { if ( maskActive ) { - var context = this.renderer.getContext(); - var stencil = this.renderer.state.buffers.stencil; + const context = this.renderer.getContext(); + const stencil = this.renderer.state.buffers.stencil; //context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); stencil.setFunc( context.NOTEQUAL, 1, 0xffffffff ); @@ -189,13 +187,13 @@ Object.assign( EffectComposer.prototype, { this.renderer.setRenderTarget( currentRenderTarget ); - }, + } - reset: function ( renderTarget ) { + reset( renderTarget ) { if ( renderTarget === undefined ) { - var size = this.renderer.getSize( new Vector2() ); + const size = this.renderer.getSize( new Vector2() ); this._pixelRatio = this.renderer.getPixelRatio(); this._width = size.width; this._height = size.height; @@ -213,28 +211,28 @@ Object.assign( EffectComposer.prototype, { this.writeBuffer = this.renderTarget1; this.readBuffer = this.renderTarget2; - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this._width = width; this._height = height; - var effectiveWidth = this._width * this._pixelRatio; - var effectiveHeight = this._height * this._pixelRatio; + const effectiveWidth = this._width * this._pixelRatio; + const effectiveHeight = this._height * this._pixelRatio; this.renderTarget1.setSize( effectiveWidth, effectiveHeight ); this.renderTarget2.setSize( effectiveWidth, effectiveHeight ); - for ( var i = 0; i < this.passes.length; i ++ ) { + for ( let i = 0; i < this.passes.length; i ++ ) { this.passes[ i ].setSize( effectiveWidth, effectiveHeight ); } - }, + } - setPixelRatio: function ( pixelRatio ) { + setPixelRatio( pixelRatio ) { this._pixelRatio = pixelRatio; @@ -242,88 +240,79 @@ Object.assign( EffectComposer.prototype, { } -} ); +} -var Pass = function () { +class Pass { - // if set to true, the pass is processed by the composer - this.enabled = true; + constructor() { - // if set to true, the pass indicates to swap read and write buffer after rendering - this.needsSwap = true; + // if set to true, the pass is processed by the composer + this.enabled = true; - // if set to true, the pass clears its buffer before rendering - this.clear = false; + // if set to true, the pass indicates to swap read and write buffer after rendering + this.needsSwap = true; - // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. - this.renderToScreen = false; + // if set to true, the pass clears its buffer before rendering + this.clear = false; -}; + // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. + this.renderToScreen = false; -Object.assign( Pass.prototype, { + } - setSize: function ( /* width, height */ ) {}, + setSize( /* width, height */ ) {} - render: function ( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) { + render( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) { console.error( 'THREE.Pass: .render() must be implemented in derived pass.' ); } -} ); +} // Helper for passes that need to fill the viewport with a single quad. -Pass.FullScreenQuad = ( function () { - - var camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - // https://github.com/mrdoob/three.js/pull/21358 - - var geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); - geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); - var FullScreenQuad = function ( material ) { +const _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - this._mesh = new Mesh( geometry, material ); +// https://github.com/mrdoob/three.js/pull/21358 - }; +const _geometry = new BufferGeometry(); +_geometry.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); +_geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); - Object.defineProperty( FullScreenQuad.prototype, 'material', { +class FullScreenQuad { - get: function () { + constructor( material ) { - return this._mesh.material; + this._mesh = new Mesh( _geometry, material ); - }, - - set: function ( value ) { + } - this._mesh.material = value; + dispose() { - } + this._mesh.geometry.dispose(); - } ); + } - Object.assign( FullScreenQuad.prototype, { + render( renderer ) { - dispose: function () { + renderer.render( this._mesh, _camera ); - this._mesh.geometry.dispose(); + } - }, + get material() { - render: function ( renderer ) { + return this._mesh.material; - renderer.render( this._mesh, camera ); + } - } + set material( value ) { - } ); + this._mesh.material = value; - return FullScreenQuad; + } -} )(); +} -export { EffectComposer, Pass }; +export { EffectComposer, Pass, FullScreenQuad }; diff --git a/examples/jsm/postprocessing/FilmPass.js b/examples/jsm/postprocessing/FilmPass.js index 661e9d709097ca..49c28d6c7e5f5d 100644 --- a/examples/jsm/postprocessing/FilmPass.js +++ b/examples/jsm/postprocessing/FilmPass.js @@ -2,42 +2,39 @@ import { ShaderMaterial, UniformsUtils } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { FilmShader } from '../shaders/FilmShader.js'; -var FilmPass = function ( noiseIntensity, scanlinesIntensity, scanlinesCount, grayscale ) { +class FilmPass extends Pass { - Pass.call( this ); + constructor( noiseIntensity, scanlinesIntensity, scanlinesCount, grayscale ) { - if ( FilmShader === undefined ) - console.error( 'THREE.FilmPass relies on FilmShader' ); + super(); - var shader = FilmShader; + if ( FilmShader === undefined ) console.error( 'THREE.FilmPass relies on FilmShader' ); - this.uniforms = UniformsUtils.clone( shader.uniforms ); + const shader = FilmShader; - this.material = new ShaderMaterial( { + this.uniforms = UniformsUtils.clone( shader.uniforms ); - uniforms: this.uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + this.material = new ShaderMaterial( { - } ); + uniforms: this.uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader - if ( grayscale !== undefined ) this.uniforms.grayscale.value = grayscale; - if ( noiseIntensity !== undefined ) this.uniforms.nIntensity.value = noiseIntensity; - if ( scanlinesIntensity !== undefined ) this.uniforms.sIntensity.value = scanlinesIntensity; - if ( scanlinesCount !== undefined ) this.uniforms.sCount.value = scanlinesCount; + } ); - this.fsQuad = new Pass.FullScreenQuad( this.material ); + if ( grayscale !== undefined ) this.uniforms.grayscale.value = grayscale; + if ( noiseIntensity !== undefined ) this.uniforms.nIntensity.value = noiseIntensity; + if ( scanlinesIntensity !== undefined ) this.uniforms.sIntensity.value = scanlinesIntensity; + if ( scanlinesCount !== undefined ) this.uniforms.sCount.value = scanlinesCount; -}; + this.fsQuad = new FullScreenQuad( this.material ); -FilmPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: FilmPass, + } - render: function ( renderer, writeBuffer, readBuffer, deltaTime /*, maskActive */ ) { + render( renderer, writeBuffer, readBuffer, deltaTime /*, maskActive */ ) { this.uniforms[ 'tDiffuse' ].value = readBuffer.texture; this.uniforms[ 'time' ].value += deltaTime; @@ -57,6 +54,6 @@ FilmPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { FilmPass }; diff --git a/examples/jsm/postprocessing/GlitchPass.js b/examples/jsm/postprocessing/GlitchPass.js index 77cbd1a766d799..6f6674586ed857 100644 --- a/examples/jsm/postprocessing/GlitchPass.js +++ b/examples/jsm/postprocessing/GlitchPass.js @@ -6,43 +6,38 @@ import { ShaderMaterial, UniformsUtils } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { DigitalGlitch } from '../shaders/DigitalGlitch.js'; -var GlitchPass = function ( dt_size ) { +class GlitchPass extends Pass { - Pass.call( this ); + constructor( dt_size = 64 ) { - if ( DigitalGlitch === undefined ) console.error( 'THREE.GlitchPass relies on DigitalGlitch' ); + super(); - var shader = DigitalGlitch; - this.uniforms = UniformsUtils.clone( shader.uniforms ); + if ( DigitalGlitch === undefined ) console.error( 'THREE.GlitchPass relies on DigitalGlitch' ); - if ( dt_size == undefined ) dt_size = 64; + const shader = DigitalGlitch; + this.uniforms = UniformsUtils.clone( shader.uniforms ); - this.uniforms[ 'tDisp' ].value = this.generateHeightmap( dt_size ); + this.uniforms[ 'tDisp' ].value = this.generateHeightmap( dt_size ); + this.material = new ShaderMaterial( { + uniforms: this.uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader + } ); - this.material = new ShaderMaterial( { - uniforms: this.uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader - } ); + this.fsQuad = new FullScreenQuad( this.material ); - this.fsQuad = new Pass.FullScreenQuad( this.material ); + this.goWild = false; + this.curF = 0; + this.generateTrigger(); - this.goWild = false; - this.curF = 0; - this.generateTrigger(); - -}; - -GlitchPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: GlitchPass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { this.uniforms[ 'tDiffuse' ].value = readBuffer.texture; this.uniforms[ 'seed' ].value = Math.random();//default seeding @@ -89,22 +84,22 @@ GlitchPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - generateTrigger: function () { + generateTrigger() { this.randX = MathUtils.randInt( 120, 240 ); - }, + } - generateHeightmap: function ( dt_size ) { + generateHeightmap( dt_size ) { - var data_arr = new Float32Array( dt_size * dt_size * 3 ); - var length = dt_size * dt_size; + const data_arr = new Float32Array( dt_size * dt_size * 3 ); + const length = dt_size * dt_size; - for ( var i = 0; i < length; i ++ ) { + for ( let i = 0; i < length; i ++ ) { - var val = MathUtils.randFloat( 0, 1 ); + const val = MathUtils.randFloat( 0, 1 ); data_arr[ i * 3 + 0 ] = val; data_arr[ i * 3 + 1 ] = val; data_arr[ i * 3 + 2 ] = val; @@ -115,6 +110,6 @@ GlitchPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { GlitchPass }; diff --git a/examples/jsm/postprocessing/HalftonePass.js b/examples/jsm/postprocessing/HalftonePass.js index cc7ab3d87a870c..8b19e9afbd84b3 100644 --- a/examples/jsm/postprocessing/HalftonePass.js +++ b/examples/jsm/postprocessing/HalftonePass.js @@ -2,53 +2,51 @@ import { ShaderMaterial, UniformsUtils } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { HalftoneShader } from '../shaders/HalftoneShader.js'; /** * RGB Halftone pass for three.js effects composer. Requires HalftoneShader. */ -var HalftonePass = function ( width, height, params ) { +class HalftonePass extends Pass { - Pass.call( this ); + constructor( width, height, params ) { - if ( HalftoneShader === undefined ) { + super(); - console.error( 'THREE.HalftonePass requires HalftoneShader' ); + if ( HalftoneShader === undefined ) { - } - - this.uniforms = UniformsUtils.clone( HalftoneShader.uniforms ); - this.material = new ShaderMaterial( { - uniforms: this.uniforms, - fragmentShader: HalftoneShader.fragmentShader, - vertexShader: HalftoneShader.vertexShader - } ); + console.error( 'THREE.HalftonePass requires HalftoneShader' ); - // set params - this.uniforms.width.value = width; - this.uniforms.height.value = height; + } - for ( var key in params ) { + this.uniforms = UniformsUtils.clone( HalftoneShader.uniforms ); + this.material = new ShaderMaterial( { + uniforms: this.uniforms, + fragmentShader: HalftoneShader.fragmentShader, + vertexShader: HalftoneShader.vertexShader + } ); - if ( params.hasOwnProperty( key ) && this.uniforms.hasOwnProperty( key ) ) { + // set params + this.uniforms.width.value = width; + this.uniforms.height.value = height; - this.uniforms[ key ].value = params[ key ]; + for ( const key in params ) { - } + if ( params.hasOwnProperty( key ) && this.uniforms.hasOwnProperty( key ) ) { - } + this.uniforms[ key ].value = params[ key ]; - this.fsQuad = new Pass.FullScreenQuad( this.material ); + } -}; + } -HalftonePass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.fsQuad = new FullScreenQuad( this.material ); - constructor: HalftonePass, + } - render: function ( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { this.material.uniforms[ 'tDiffuse' ].value = readBuffer.texture; @@ -65,14 +63,15 @@ HalftonePass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.uniforms.width.value = width; this.uniforms.height.value = height; } -} ); + +} export { HalftonePass }; diff --git a/examples/jsm/postprocessing/MaskPass.js b/examples/jsm/postprocessing/MaskPass.js index bc49ebbb961a3e..d9c26196e3c5c1 100644 --- a/examples/jsm/postprocessing/MaskPass.js +++ b/examples/jsm/postprocessing/MaskPass.js @@ -1,27 +1,25 @@ import { Pass } from '../postprocessing/Pass.js'; -var MaskPass = function ( scene, camera ) { +class MaskPass extends Pass { - Pass.call( this ); + constructor( scene, camera ) { - this.scene = scene; - this.camera = camera; + super(); - this.clear = true; - this.needsSwap = false; + this.scene = scene; + this.camera = camera; - this.inverse = false; + this.clear = true; + this.needsSwap = false; -}; + this.inverse = false; -MaskPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: MaskPass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { - var context = renderer.getContext(); - var state = renderer.state; + const context = renderer.getContext(); + const state = renderer.state; // don't update color or depth @@ -35,7 +33,7 @@ MaskPass.prototype = Object.assign( Object.create( Pass.prototype ), { // set up stencil - var writeValue, clearValue; + let writeValue, clearValue; if ( this.inverse ) { @@ -79,28 +77,25 @@ MaskPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); - +} -var ClearMaskPass = function () { +class ClearMaskPass extends Pass { - Pass.call( this ); + constructor() { - this.needsSwap = false; + super(); -}; + this.needsSwap = false; -ClearMaskPass.prototype = Object.create( Pass.prototype ); - -Object.assign( ClearMaskPass.prototype, { + } - render: function ( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) { + render( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) { renderer.state.buffers.stencil.setLocked( false ); renderer.state.buffers.stencil.setTest( false ); } -} ); +} export { MaskPass, ClearMaskPass }; diff --git a/examples/jsm/postprocessing/OutlinePass.js b/examples/jsm/postprocessing/OutlinePass.js index 0cd281088071e4..76c763a27450b6 100644 --- a/examples/jsm/postprocessing/OutlinePass.js +++ b/examples/jsm/postprocessing/OutlinePass.js @@ -15,131 +15,129 @@ import { Vector3, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; -var OutlinePass = function ( resolution, scene, camera, selectedObjects ) { - - this.renderScene = scene; - this.renderCamera = camera; - this.selectedObjects = selectedObjects !== undefined ? selectedObjects : []; - this.visibleEdgeColor = new Color( 1, 1, 1 ); - this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 ); - this.edgeGlow = 0.0; - this.usePatternTexture = false; - this.edgeThickness = 1.0; - this.edgeStrength = 3.0; - this.downSampleRatio = 2; - this.pulsePeriod = 0; +class OutlinePass extends Pass { - this._visibilityCache = new Map(); + constructor( resolution, scene, camera, selectedObjects ) { - Pass.call( this ); + super(); - this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); + this.renderScene = scene; + this.renderCamera = camera; + this.selectedObjects = selectedObjects !== undefined ? selectedObjects : []; + this.visibleEdgeColor = new Color( 1, 1, 1 ); + this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 ); + this.edgeGlow = 0.0; + this.usePatternTexture = false; + this.edgeThickness = 1.0; + this.edgeStrength = 3.0; + this.downSampleRatio = 2; + this.pulsePeriod = 0; - var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; + this._visibilityCache = new Map(); - var resx = Math.round( this.resolution.x / this.downSampleRatio ); - var resy = Math.round( this.resolution.y / this.downSampleRatio ); - this.maskBufferMaterial = new MeshBasicMaterial( { color: 0xffffff } ); - this.maskBufferMaterial.side = DoubleSide; - this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ); - this.renderTargetMaskBuffer.texture.name = 'OutlinePass.mask'; - this.renderTargetMaskBuffer.texture.generateMipmaps = false; + this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); - this.depthMaterial = new MeshDepthMaterial(); - this.depthMaterial.side = DoubleSide; - this.depthMaterial.depthPacking = RGBADepthPacking; - this.depthMaterial.blending = NoBlending; + const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; - this.prepareMaskMaterial = this.getPrepareMaskMaterial(); - this.prepareMaskMaterial.side = DoubleSide; - this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera ); + const resx = Math.round( this.resolution.x / this.downSampleRatio ); + const resy = Math.round( this.resolution.y / this.downSampleRatio ); - this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ); - this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth'; - this.renderTargetDepthBuffer.texture.generateMipmaps = false; + this.maskBufferMaterial = new MeshBasicMaterial( { color: 0xffffff } ); + this.maskBufferMaterial.side = DoubleSide; + this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ); + this.renderTargetMaskBuffer.texture.name = 'OutlinePass.mask'; + this.renderTargetMaskBuffer.texture.generateMipmaps = false; - this.renderTargetMaskDownSampleBuffer = new WebGLRenderTarget( resx, resy, pars ); - this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample'; - this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false; + this.depthMaterial = new MeshDepthMaterial(); + this.depthMaterial.side = DoubleSide; + this.depthMaterial.depthPacking = RGBADepthPacking; + this.depthMaterial.blending = NoBlending; - this.renderTargetBlurBuffer1 = new WebGLRenderTarget( resx, resy, pars ); - this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1'; - this.renderTargetBlurBuffer1.texture.generateMipmaps = false; - this.renderTargetBlurBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars ); - this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2'; - this.renderTargetBlurBuffer2.texture.generateMipmaps = false; + this.prepareMaskMaterial = this.getPrepareMaskMaterial(); + this.prepareMaskMaterial.side = DoubleSide; + this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera ); - this.edgeDetectionMaterial = this.getEdgeDetectionMaterial(); - this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, pars ); - this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1'; - this.renderTargetEdgeBuffer1.texture.generateMipmaps = false; - this.renderTargetEdgeBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars ); - this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2'; - this.renderTargetEdgeBuffer2.texture.generateMipmaps = false; + this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, pars ); + this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth'; + this.renderTargetDepthBuffer.texture.generateMipmaps = false; - var MAX_EDGE_THICKNESS = 4; - var MAX_EDGE_GLOW = 4; + this.renderTargetMaskDownSampleBuffer = new WebGLRenderTarget( resx, resy, pars ); + this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample'; + this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false; - this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS ); - this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy ); - this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1; - this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW ); - this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) ); - this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW; + this.renderTargetBlurBuffer1 = new WebGLRenderTarget( resx, resy, pars ); + this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1'; + this.renderTargetBlurBuffer1.texture.generateMipmaps = false; + this.renderTargetBlurBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars ); + this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2'; + this.renderTargetBlurBuffer2.texture.generateMipmaps = false; - // Overlay material - this.overlayMaterial = this.getOverlayMaterial(); + this.edgeDetectionMaterial = this.getEdgeDetectionMaterial(); + this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, pars ); + this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1'; + this.renderTargetEdgeBuffer1.texture.generateMipmaps = false; + this.renderTargetEdgeBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars ); + this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2'; + this.renderTargetEdgeBuffer2.texture.generateMipmaps = false; - // copy material - if ( CopyShader === undefined ) - console.error( 'THREE.OutlinePass relies on CopyShader' ); + const MAX_EDGE_THICKNESS = 4; + const MAX_EDGE_GLOW = 4; - var copyShader = CopyShader; + this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS ); + this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy ); + this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1; + this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW ); + this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) ); + this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW; - this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); - this.copyUniforms[ 'opacity' ].value = 1.0; + // Overlay material + this.overlayMaterial = this.getOverlayMaterial(); - this.materialCopy = new ShaderMaterial( { - uniforms: this.copyUniforms, - vertexShader: copyShader.vertexShader, - fragmentShader: copyShader.fragmentShader, - blending: NoBlending, - depthTest: false, - depthWrite: false, - transparent: true - } ); + // copy material + if ( CopyShader === undefined ) console.error( 'THREE.OutlinePass relies on CopyShader' ); - this.enabled = true; - this.needsSwap = false; + const copyShader = CopyShader; - this._oldClearColor = new Color(); - this.oldClearAlpha = 1; + this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); + this.copyUniforms[ 'opacity' ].value = 1.0; - this.fsQuad = new Pass.FullScreenQuad( null ); + this.materialCopy = new ShaderMaterial( { + uniforms: this.copyUniforms, + vertexShader: copyShader.vertexShader, + fragmentShader: copyShader.fragmentShader, + blending: NoBlending, + depthTest: false, + depthWrite: false, + transparent: true + } ); - this.tempPulseColor1 = new Color(); - this.tempPulseColor2 = new Color(); - this.textureMatrix = new Matrix4(); + this.enabled = true; + this.needsSwap = false; - function replaceDepthToViewZ( string, camera ) { + this._oldClearColor = new Color(); + this.oldClearAlpha = 1; - var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic'; + this.fsQuad = new FullScreenQuad( null ); - return string.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' ); + this.tempPulseColor1 = new Color(); + this.tempPulseColor2 = new Color(); + this.textureMatrix = new Matrix4(); - } + function replaceDepthToViewZ( string, camera ) { -}; + var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic'; -OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { + return string.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' ); - constructor: OutlinePass, + } - dispose: function () { + } + + dispose() { this.renderTargetMaskBuffer.dispose(); this.renderTargetDepthBuffer.dispose(); @@ -149,15 +147,15 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { this.renderTargetEdgeBuffer1.dispose(); this.renderTargetEdgeBuffer2.dispose(); - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.renderTargetMaskBuffer.setSize( width, height ); this.renderTargetDepthBuffer.setSize( width, height ); - var resx = Math.round( width / this.downSampleRatio ); - var resy = Math.round( height / this.downSampleRatio ); + let resx = Math.round( width / this.downSampleRatio ); + let resy = Math.round( height / this.downSampleRatio ); this.renderTargetMaskDownSampleBuffer.setSize( resx, resy ); this.renderTargetBlurBuffer1.setSize( resx, resy ); this.renderTargetEdgeBuffer1.setSize( resx, resy ); @@ -171,11 +169,11 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( resx, resy ); - }, + } - changeVisibilityOfSelectedObjects: function ( bVisible ) { + changeVisibilityOfSelectedObjects( bVisible ) { - var cache = this._visibilityCache; + const cache = this._visibilityCache; function gatherSelectedMeshesCallBack( object ) { @@ -196,19 +194,19 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { } - for ( var i = 0; i < this.selectedObjects.length; i ++ ) { + for ( let i = 0; i < this.selectedObjects.length; i ++ ) { - var selectedObject = this.selectedObjects[ i ]; + const selectedObject = this.selectedObjects[ i ]; selectedObject.traverse( gatherSelectedMeshesCallBack ); } - }, + } - changeVisibilityOfNonSelectedObjects: function ( bVisible ) { + changeVisibilityOfNonSelectedObjects( bVisible ) { - var cache = this._visibilityCache; - var selectedMeshes = []; + const cache = this._visibilityCache; + const selectedMeshes = []; function gatherSelectedMeshesCallBack( object ) { @@ -216,9 +214,9 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { } - for ( var i = 0; i < this.selectedObjects.length; i ++ ) { + for ( let i = 0; i < this.selectedObjects.length; i ++ ) { - var selectedObject = this.selectedObjects[ i ]; + const selectedObject = this.selectedObjects[ i ]; selectedObject.traverse( gatherSelectedMeshesCallBack ); } @@ -229,11 +227,11 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { // only meshes and sprites are supported by OutlinePass - var bFound = false; + let bFound = false; - for ( var i = 0; i < selectedMeshes.length; i ++ ) { + for ( let i = 0; i < selectedMeshes.length; i ++ ) { - var selectedObjectId = selectedMeshes[ i ].id; + const selectedObjectId = selectedMeshes[ i ].id; if ( selectedObjectId === object.id ) { @@ -246,7 +244,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { if ( bFound === false ) { - var visibility = object.visible; + const visibility = object.visible; if ( bVisible === false || cache.get( object ) === true ) { @@ -280,9 +278,9 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { this.renderScene.traverse( VisibilityChangeCallBack ); - }, + } - updateTextureMatrix: function () { + updateTextureMatrix() { this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, @@ -291,15 +289,15 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { this.textureMatrix.multiply( this.renderCamera.projectionMatrix ); this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse ); - }, + } - render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { + render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { if ( this.selectedObjects.length > 0 ) { renderer.getClearColor( this._oldClearColor ); this.oldClearAlpha = renderer.getClearAlpha(); - var oldAutoClear = renderer.autoClear; + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; @@ -310,7 +308,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { // Make selected objects invisible this.changeVisibilityOfSelectedObjects( false ); - var currentBackground = this.renderScene.background; + const currentBackground = this.renderScene.background; this.renderScene.background = null; // 1. Draw Non Selected objects in the depth buffer @@ -353,7 +351,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { if ( this.pulsePeriod > 0 ) { - var scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2; + const scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2; this.tempPulseColor1.multiplyScalar( scalar ); this.tempPulseColor2.multiplyScalar( scalar ); @@ -426,9 +424,9 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - getPrepareMaskMaterial: function () { + getPrepareMaskMaterial() { return new ShaderMaterial( { @@ -438,51 +436,49 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { 'textureMatrix': { value: null } }, - vertexShader: [ - '#include ', - '#include ', + vertexShader: + `#include + #include - 'varying vec4 projTexCoord;', - 'varying vec4 vPosition;', - 'uniform mat4 textureMatrix;', + varying vec4 projTexCoord; + varying vec4 vPosition; + uniform mat4 textureMatrix; - 'void main() {', + void main() { - ' #include ', - ' #include ', - ' #include ', - ' #include ', - ' #include ', + #include + #include + #include + #include + #include - ' vPosition = mvPosition;', - ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', - ' projTexCoord = textureMatrix * worldPosition;', + vPosition = mvPosition; + vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); + projTexCoord = textureMatrix * worldPosition; - '}' - ].join( '\n' ), + }`, - fragmentShader: [ - '#include ', - 'varying vec4 vPosition;', - 'varying vec4 projTexCoord;', - 'uniform sampler2D depthTexture;', - 'uniform vec2 cameraNearFar;', + fragmentShader: + `#include + varying vec4 vPosition; + varying vec4 projTexCoord; + uniform sampler2D depthTexture; + uniform vec2 cameraNearFar; - 'void main() {', + void main() { - ' float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));', - ' float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );', - ' float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;', - ' gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);', + float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord )); + float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y ); + float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0; + gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0); - '}' - ].join( '\n' ) + }` } ); - }, + } - getEdgeDetectionMaterial: function () { + getEdgeDetectionMaterial() { return new ShaderMaterial( { @@ -494,40 +490,42 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { }, vertexShader: - 'varying vec2 vUv;\n\ - void main() {\n\ - vUv = uv;\n\ - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ - }', + `varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, fragmentShader: - 'varying vec2 vUv;\ - uniform sampler2D maskTexture;\ - uniform vec2 texSize;\ - uniform vec3 visibleEdgeColor;\ - uniform vec3 hiddenEdgeColor;\ - \ - void main() {\n\ - vec2 invSize = 1.0 / texSize;\ - vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);\ - vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);\ - vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);\ - vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);\ - vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);\ - float diff1 = (c1.r - c2.r)*0.5;\ - float diff2 = (c3.r - c4.r)*0.5;\ - float d = length( vec2(diff1, diff2) );\ - float a1 = min(c1.g, c2.g);\ - float a2 = min(c3.g, c4.g);\ - float visibilityFactor = min(a1, a2);\ - vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;\ - gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);\ - }' + `varying vec2 vUv; + + uniform sampler2D maskTexture; + uniform vec2 texSize; + uniform vec3 visibleEdgeColor; + uniform vec3 hiddenEdgeColor; + + void main() { + vec2 invSize = 1.0 / texSize; + vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize); + vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy); + vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy); + vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw); + vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw); + float diff1 = (c1.r - c2.r)*0.5; + float diff2 = (c3.r - c4.r)*0.5; + float d = length( vec2(diff1, diff2) ); + float a1 = min(c1.g, c2.g); + float a2 = min(c3.g, c4.g); + float visibilityFactor = min(a1, a2); + vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor; + gl_FragColor = vec4(edgeColor, 1.0) * vec4(d); + }` } ); - }, + } - getSeperableBlurMaterial: function ( maxRadius ) { + getSeperableBlurMaterial( maxRadius ) { return new ShaderMaterial( { @@ -543,44 +541,46 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { }, vertexShader: - 'varying vec2 vUv;\n\ - void main() {\n\ - vUv = uv;\n\ - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ - }', + `varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, fragmentShader: - '#include \ - varying vec2 vUv;\ - uniform sampler2D colorTexture;\ - uniform vec2 texSize;\ - uniform vec2 direction;\ - uniform float kernelRadius;\ - \ - float gaussianPdf(in float x, in float sigma) {\ - return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\ - }\ - void main() {\ - vec2 invSize = 1.0 / texSize;\ - float weightSum = gaussianPdf(0.0, kernelRadius);\ - vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;\ - vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\ - vec2 uvOffset = delta;\ - for( int i = 1; i <= MAX_RADIUS; i ++ ) {\ - float w = gaussianPdf(uvOffset.x, kernelRadius);\ - vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\ - vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\ - diffuseSum += ((sample1 + sample2) * w);\ - weightSum += (2.0 * w);\ - uvOffset += delta;\ - }\ - gl_FragColor = diffuseSum/weightSum;\ - }' + `#include + varying vec2 vUv; + uniform sampler2D colorTexture; + uniform vec2 texSize; + uniform vec2 direction; + uniform float kernelRadius; + + float gaussianPdf(in float x, in float sigma) { + return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma; + } + + void main() { + vec2 invSize = 1.0 / texSize; + float weightSum = gaussianPdf(0.0, kernelRadius); + vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum; + vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS); + vec2 uvOffset = delta; + for( int i = 1; i <= MAX_RADIUS; i ++ ) { + float w = gaussianPdf(uvOffset.x, kernelRadius); + vec4 sample1 = texture2D( colorTexture, vUv + uvOffset); + vec4 sample2 = texture2D( colorTexture, vUv - uvOffset); + diffuseSum += ((sample1 + sample2) * w); + weightSum += (2.0 * w); + uvOffset += delta; + } + gl_FragColor = diffuseSum/weightSum; + }` } ); - }, + } - getOverlayMaterial: function () { + getOverlayMaterial() { return new ShaderMaterial( { @@ -595,34 +595,36 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { }, vertexShader: - 'varying vec2 vUv;\n\ - void main() {\n\ - vUv = uv;\n\ - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ - }', + `varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, fragmentShader: - 'varying vec2 vUv;\ - uniform sampler2D maskTexture;\ - uniform sampler2D edgeTexture1;\ - uniform sampler2D edgeTexture2;\ - uniform sampler2D patternTexture;\ - uniform float edgeStrength;\ - uniform float edgeGlow;\ - uniform bool usePatternTexture;\ - \ - void main() {\ - vec4 edgeValue1 = texture2D(edgeTexture1, vUv);\ - vec4 edgeValue2 = texture2D(edgeTexture2, vUv);\ - vec4 maskColor = texture2D(maskTexture, vUv);\ - vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);\ - float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;\ - vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;\ - vec4 finalColor = edgeStrength * maskColor.r * edgeValue;\ - if(usePatternTexture)\ - finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);\ - gl_FragColor = finalColor;\ - }', + `varying vec2 vUv; + + uniform sampler2D maskTexture; + uniform sampler2D edgeTexture1; + uniform sampler2D edgeTexture2; + uniform sampler2D patternTexture; + uniform float edgeStrength; + uniform float edgeGlow; + uniform bool usePatternTexture; + + void main() { + vec4 edgeValue1 = texture2D(edgeTexture1, vUv); + vec4 edgeValue2 = texture2D(edgeTexture2, vUv); + vec4 maskColor = texture2D(maskTexture, vUv); + vec4 patternColor = texture2D(patternTexture, 6.0 * vUv); + float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5; + vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow; + vec4 finalColor = edgeStrength * maskColor.r * edgeValue; + if(usePatternTexture) + finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r); + gl_FragColor = finalColor; + }`, blending: AdditiveBlending, depthTest: false, depthWrite: false, @@ -631,7 +633,7 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} OutlinePass.BlurDirectionX = new Vector2( 1.0, 0.0 ); OutlinePass.BlurDirectionY = new Vector2( 0.0, 1.0 ); diff --git a/examples/jsm/postprocessing/Pass.js b/examples/jsm/postprocessing/Pass.js index 9d4166a2d03928..28aa106d1478d8 100644 --- a/examples/jsm/postprocessing/Pass.js +++ b/examples/jsm/postprocessing/Pass.js @@ -5,90 +5,76 @@ import { Mesh } from '../../../build/three.module.js'; -function Pass() { +class Pass { - // if set to true, the pass is processed by the composer - this.enabled = true; + constructor() { - // if set to true, the pass indicates to swap read and write buffer after rendering - this.needsSwap = true; + // if set to true, the pass is processed by the composer + this.enabled = true; - // if set to true, the pass clears its buffer before rendering - this.clear = false; + // if set to true, the pass indicates to swap read and write buffer after rendering + this.needsSwap = true; - // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. - this.renderToScreen = false; + // if set to true, the pass clears its buffer before rendering + this.clear = false; -} + // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. + this.renderToScreen = false; -Object.assign( Pass.prototype, { + } - setSize: function ( /* width, height */ ) {}, + setSize( /* width, height */ ) {} - render: function ( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) { + render( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) { console.error( 'THREE.Pass: .render() must be implemented in derived pass.' ); } -} ); +} // Helper for passes that need to fill the viewport with a single quad. -// Important: It's actually a hack to put FullScreenQuad into the Pass namespace. This is only -// done to make examples/js code work. Normally, FullScreenQuad should be exported -// from this module like Pass. - -Pass.FullScreenQuad = ( function () { - - var camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - // https://github.com/mrdoob/three.js/pull/21358 - - var geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); - geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); - - var FullScreenQuad = function ( material ) { +const _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - this._mesh = new Mesh( geometry, material ); +// https://github.com/mrdoob/three.js/pull/21358 - }; +const _geometry = new BufferGeometry(); +_geometry.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); +_geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) ); - Object.defineProperty( FullScreenQuad.prototype, 'material', { +class FullScreenQuad { - get: function () { + constructor( material ) { - return this._mesh.material; + this._mesh = new Mesh( _geometry, material ); - }, - - set: function ( value ) { + } - this._mesh.material = value; + dispose() { - } + this._mesh.geometry.dispose(); - } ); + } - Object.assign( FullScreenQuad.prototype, { + render( renderer ) { - dispose: function () { + renderer.render( this._mesh, _camera ); - this._mesh.geometry.dispose(); + } - }, + get material() { - render: function ( renderer ) { + return this._mesh.material; - renderer.render( this._mesh, camera ); + } - } + set material( value ) { - } ); + this._mesh.material = value; - return FullScreenQuad; + } -} )(); +} -export { Pass }; +export { Pass, FullScreenQuad }; diff --git a/examples/jsm/postprocessing/RenderPass.js b/examples/jsm/postprocessing/RenderPass.js index 87a7d01bc9069d..e735df1ecb2708 100644 --- a/examples/jsm/postprocessing/RenderPass.js +++ b/examples/jsm/postprocessing/RenderPass.js @@ -3,35 +3,33 @@ import { } from '../../../build/three.module.js'; import { Pass } from '../postprocessing/Pass.js'; -var RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) { +class RenderPass extends Pass { - Pass.call( this ); + constructor( scene, camera, overrideMaterial, clearColor, clearAlpha ) { - this.scene = scene; - this.camera = camera; + super(); - this.overrideMaterial = overrideMaterial; + this.scene = scene; + this.camera = camera; - this.clearColor = clearColor; - this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; + this.overrideMaterial = overrideMaterial; - this.clear = true; - this.clearDepth = false; - this.needsSwap = false; - this._oldClearColor = new Color(); + this.clearColor = clearColor; + this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; -}; + this.clear = true; + this.clearDepth = false; + this.needsSwap = false; + this._oldClearColor = new Color(); -RenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: RenderPass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { - var oldAutoClear = renderer.autoClear; + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; - var oldClearAlpha, oldOverrideMaterial; + let oldClearAlpha, oldOverrideMaterial; if ( this.overrideMaterial !== undefined ) { @@ -78,6 +76,6 @@ RenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { RenderPass }; diff --git a/examples/jsm/postprocessing/SAOPass.js b/examples/jsm/postprocessing/SAOPass.js index 4b98b33d6727ee..7e5327a527ac6d 100644 --- a/examples/jsm/postprocessing/SAOPass.js +++ b/examples/jsm/postprocessing/SAOPass.js @@ -19,7 +19,7 @@ import { WebGLRenderTarget, ZeroFactor } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { SAOShader } from '../shaders/SAOShader.js'; import { DepthLimitedBlurShader } from '../shaders/DepthLimitedBlurShader.js'; import { BlurShaderUtils } from '../shaders/DepthLimitedBlurShader.js'; @@ -30,177 +30,168 @@ import { UnpackDepthRGBAShader } from '../shaders/UnpackDepthRGBAShader.js'; * SAO implementation inspired from bhouston previous SAO work */ -var SAOPass = function ( scene, camera, depthTexture, useNormals, resolution ) { +class SAOPass extends Pass { - Pass.call( this ); + constructor( scene, camera, depthTexture, useNormals, resolution ) { - this.scene = scene; - this.camera = camera; + super(); - this.clear = true; - this.needsSwap = false; + this.scene = scene; + this.camera = camera; - this.supportsDepthTextureExtension = ( depthTexture !== undefined ) ? depthTexture : false; - this.supportsNormalTexture = ( useNormals !== undefined ) ? useNormals : false; + this.clear = true; + this.needsSwap = false; - this.originalClearColor = new Color(); - this._oldClearColor = new Color(); - this.oldClearAlpha = 1; + this.supportsDepthTextureExtension = ( depthTexture !== undefined ) ? depthTexture : false; + this.supportsNormalTexture = ( useNormals !== undefined ) ? useNormals : false; - this.params = { - output: 0, - saoBias: 0.5, - saoIntensity: 0.18, - saoScale: 1, - saoKernelRadius: 100, - saoMinResolution: 0, - saoBlur: true, - saoBlurRadius: 8, - saoBlurStdDev: 4, - saoBlurDepthCutoff: 0.01 - }; + this.originalClearColor = new Color(); + this._oldClearColor = new Color(); + this.oldClearAlpha = 1; - this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); + this.params = { + output: 0, + saoBias: 0.5, + saoIntensity: 0.18, + saoScale: 1, + saoKernelRadius: 100, + saoMinResolution: 0, + saoBlur: true, + saoBlurRadius: 8, + saoBlurStdDev: 4, + saoBlurDepthCutoff: 0.01 + }; - this.saoRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat - } ); - this.blurIntermediateRenderTarget = this.saoRenderTarget.clone(); - this.beautyRenderTarget = this.saoRenderTarget.clone(); + this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); - this.normalRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat - } ); - this.depthRenderTarget = this.normalRenderTarget.clone(); + this.saoRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBAFormat + } ); + this.blurIntermediateRenderTarget = this.saoRenderTarget.clone(); + this.beautyRenderTarget = this.saoRenderTarget.clone(); - if ( this.supportsDepthTextureExtension ) { + this.normalRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat + } ); + this.depthRenderTarget = this.normalRenderTarget.clone(); - var depthTexture = new DepthTexture(); - depthTexture.type = UnsignedShortType; + if ( this.supportsDepthTextureExtension ) { - this.beautyRenderTarget.depthTexture = depthTexture; - this.beautyRenderTarget.depthBuffer = true; + const depthTexture = new DepthTexture(); + depthTexture.type = UnsignedShortType; - } + this.beautyRenderTarget.depthTexture = depthTexture; + this.beautyRenderTarget.depthBuffer = true; - this.depthMaterial = new MeshDepthMaterial(); - this.depthMaterial.depthPacking = RGBADepthPacking; - this.depthMaterial.blending = NoBlending; + } - this.normalMaterial = new MeshNormalMaterial(); - this.normalMaterial.blending = NoBlending; + this.depthMaterial = new MeshDepthMaterial(); + this.depthMaterial.depthPacking = RGBADepthPacking; + this.depthMaterial.blending = NoBlending; - if ( SAOShader === undefined ) { + this.normalMaterial = new MeshNormalMaterial(); + this.normalMaterial.blending = NoBlending; - console.error( 'THREE.SAOPass relies on SAOShader' ); + if ( SAOShader === undefined ) { - } + console.error( 'THREE.SAOPass relies on SAOShader' ); - this.saoMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SAOShader.defines ), - fragmentShader: SAOShader.fragmentShader, - vertexShader: SAOShader.vertexShader, - uniforms: UniformsUtils.clone( SAOShader.uniforms ) - } ); - this.saoMaterial.extensions.derivatives = true; - this.saoMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1; - this.saoMaterial.defines[ 'NORMAL_TEXTURE' ] = this.supportsNormalTexture ? 1 : 0; - this.saoMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0; - this.saoMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture; - this.saoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture; - this.saoMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y ); - this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); - this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix; - this.saoMaterial.blending = NoBlending; - - if ( DepthLimitedBlurShader === undefined ) { - - console.error( 'THREE.SAOPass relies on DepthLimitedBlurShader' ); + } - } + this.saoMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SAOShader.defines ), + fragmentShader: SAOShader.fragmentShader, + vertexShader: SAOShader.vertexShader, + uniforms: UniformsUtils.clone( SAOShader.uniforms ) + } ); + this.saoMaterial.extensions.derivatives = true; + this.saoMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1; + this.saoMaterial.defines[ 'NORMAL_TEXTURE' ] = this.supportsNormalTexture ? 1 : 0; + this.saoMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0; + this.saoMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture; + this.saoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture; + this.saoMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y ); + this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); + this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix; + this.saoMaterial.blending = NoBlending; - this.vBlurMaterial = new ShaderMaterial( { - uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ), - defines: Object.assign( {}, DepthLimitedBlurShader.defines ), - vertexShader: DepthLimitedBlurShader.vertexShader, - fragmentShader: DepthLimitedBlurShader.fragmentShader - } ); - this.vBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1; - this.vBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0; - this.vBlurMaterial.uniforms[ 'tDiffuse' ].value = this.saoRenderTarget.texture; - this.vBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture; - this.vBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y ); - this.vBlurMaterial.blending = NoBlending; - - this.hBlurMaterial = new ShaderMaterial( { - uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ), - defines: Object.assign( {}, DepthLimitedBlurShader.defines ), - vertexShader: DepthLimitedBlurShader.vertexShader, - fragmentShader: DepthLimitedBlurShader.fragmentShader - } ); - this.hBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1; - this.hBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0; - this.hBlurMaterial.uniforms[ 'tDiffuse' ].value = this.blurIntermediateRenderTarget.texture; - this.hBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture; - this.hBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y ); - this.hBlurMaterial.blending = NoBlending; - - if ( CopyShader === undefined ) { - - console.error( 'THREE.SAOPass relies on CopyShader' ); + if ( DepthLimitedBlurShader === undefined ) { - } + console.error( 'THREE.SAOPass relies on DepthLimitedBlurShader' ); - this.materialCopy = new ShaderMaterial( { - uniforms: UniformsUtils.clone( CopyShader.uniforms ), - vertexShader: CopyShader.vertexShader, - fragmentShader: CopyShader.fragmentShader, - blending: NoBlending - } ); - this.materialCopy.transparent = true; - this.materialCopy.depthTest = false; - this.materialCopy.depthWrite = false; - this.materialCopy.blending = CustomBlending; - this.materialCopy.blendSrc = DstColorFactor; - this.materialCopy.blendDst = ZeroFactor; - this.materialCopy.blendEquation = AddEquation; - this.materialCopy.blendSrcAlpha = DstAlphaFactor; - this.materialCopy.blendDstAlpha = ZeroFactor; - this.materialCopy.blendEquationAlpha = AddEquation; - - if ( UnpackDepthRGBAShader === undefined ) { - - console.error( 'THREE.SAOPass relies on UnpackDepthRGBAShader' ); + } - } + this.vBlurMaterial = new ShaderMaterial( { + uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ), + defines: Object.assign( {}, DepthLimitedBlurShader.defines ), + vertexShader: DepthLimitedBlurShader.vertexShader, + fragmentShader: DepthLimitedBlurShader.fragmentShader + } ); + this.vBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1; + this.vBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0; + this.vBlurMaterial.uniforms[ 'tDiffuse' ].value = this.saoRenderTarget.texture; + this.vBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture; + this.vBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y ); + this.vBlurMaterial.blending = NoBlending; + + this.hBlurMaterial = new ShaderMaterial( { + uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ), + defines: Object.assign( {}, DepthLimitedBlurShader.defines ), + vertexShader: DepthLimitedBlurShader.vertexShader, + fragmentShader: DepthLimitedBlurShader.fragmentShader + } ); + this.hBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1; + this.hBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0; + this.hBlurMaterial.uniforms[ 'tDiffuse' ].value = this.blurIntermediateRenderTarget.texture; + this.hBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture; + this.hBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y ); + this.hBlurMaterial.blending = NoBlending; + + if ( CopyShader === undefined ) { + + console.error( 'THREE.SAOPass relies on CopyShader' ); - this.depthCopy = new ShaderMaterial( { - uniforms: UniformsUtils.clone( UnpackDepthRGBAShader.uniforms ), - vertexShader: UnpackDepthRGBAShader.vertexShader, - fragmentShader: UnpackDepthRGBAShader.fragmentShader, - blending: NoBlending - } ); + } - this.fsQuad = new Pass.FullScreenQuad( null ); + this.materialCopy = new ShaderMaterial( { + uniforms: UniformsUtils.clone( CopyShader.uniforms ), + vertexShader: CopyShader.vertexShader, + fragmentShader: CopyShader.fragmentShader, + blending: NoBlending + } ); + this.materialCopy.transparent = true; + this.materialCopy.depthTest = false; + this.materialCopy.depthWrite = false; + this.materialCopy.blending = CustomBlending; + this.materialCopy.blendSrc = DstColorFactor; + this.materialCopy.blendDst = ZeroFactor; + this.materialCopy.blendEquation = AddEquation; + this.materialCopy.blendSrcAlpha = DstAlphaFactor; + this.materialCopy.blendDstAlpha = ZeroFactor; + this.materialCopy.blendEquationAlpha = AddEquation; + + if ( UnpackDepthRGBAShader === undefined ) { + + console.error( 'THREE.SAOPass relies on UnpackDepthRGBAShader' ); -}; + } -SAOPass.OUTPUT = { - 'Beauty': 1, - 'Default': 0, - 'SAO': 2, - 'Depth': 3, - 'Normal': 4 -}; + this.depthCopy = new ShaderMaterial( { + uniforms: UniformsUtils.clone( UnpackDepthRGBAShader.uniforms ), + vertexShader: UnpackDepthRGBAShader.vertexShader, + fragmentShader: UnpackDepthRGBAShader.fragmentShader, + blending: NoBlending + } ); + + this.fsQuad = new FullScreenQuad( null ); -SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { - constructor: SAOPass, + } - render: function ( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { // Rendering readBuffer first when rendering to screen if ( this.renderToScreen ) { @@ -220,7 +211,7 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.getClearColor( this._oldClearColor ); this.oldClearAlpha = renderer.getClearAlpha(); - var oldAutoClear = renderer.autoClear; + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; renderer.setRenderTarget( this.depthRenderTarget ); @@ -235,7 +226,7 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.saoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; // this.saoMaterial.uniforms['randomSeed'].value = Math.random(); - var depthCutoff = this.params.saoBlurDepthCutoff * ( this.camera.far - this.camera.near ); + const depthCutoff = this.params.saoBlurDepthCutoff * ( this.camera.far - this.camera.near ); this.vBlurMaterial.uniforms[ 'depthCutoff' ].value = depthCutoff; this.hBlurMaterial.uniforms[ 'depthCutoff' ].value = depthCutoff; @@ -286,7 +277,7 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - var outputMaterial = this.materialCopy; + let outputMaterial = this.materialCopy; // Setting up SAO rendering if ( this.params.output === 3 ) { @@ -332,14 +323,14 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this._oldClearColor, this.oldClearAlpha ); renderer.autoClear = oldAutoClear; - }, + } - renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { + renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { // save original state renderer.getClearColor( this.originalClearColor ); - var originalClearAlpha = renderer.getClearAlpha(); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha(); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); @@ -361,13 +352,13 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { + renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { renderer.getClearColor( this.originalClearColor ); - var originalClearAlpha = renderer.getClearAlpha(); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha(); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); renderer.autoClear = false; @@ -391,9 +382,9 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.beautyRenderTarget.setSize( width, height ); this.saoRenderTarget.setSize( width, height ); @@ -414,6 +405,14 @@ SAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} + +SAOPass.OUTPUT = { + 'Beauty': 1, + 'Default': 0, + 'SAO': 2, + 'Depth': 3, + 'Normal': 4 +}; export { SAOPass }; diff --git a/examples/jsm/postprocessing/SMAAPass.js b/examples/jsm/postprocessing/SMAAPass.js index 7ba31226319490..0f62237bb9e4aa 100644 --- a/examples/jsm/postprocessing/SMAAPass.js +++ b/examples/jsm/postprocessing/SMAAPass.js @@ -8,129 +8,127 @@ import { UniformsUtils, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { SMAAEdgesShader } from '../shaders/SMAAShader.js'; import { SMAAWeightsShader } from '../shaders/SMAAShader.js'; import { SMAABlendShader } from '../shaders/SMAAShader.js'; -var SMAAPass = function ( width, height ) { +class SMAAPass extends Pass { - Pass.call( this ); + constructor( width, height ) { - // render targets + super(); - this.edgesRT = new WebGLRenderTarget( width, height, { - depthBuffer: false, - generateMipmaps: false, - minFilter: LinearFilter, - format: RGBFormat - } ); - this.edgesRT.texture.name = 'SMAAPass.edges'; + // render targets - this.weightsRT = new WebGLRenderTarget( width, height, { - depthBuffer: false, - generateMipmaps: false, - minFilter: LinearFilter, - format: RGBAFormat - } ); - this.weightsRT.texture.name = 'SMAAPass.weights'; + this.edgesRT = new WebGLRenderTarget( width, height, { + depthBuffer: false, + generateMipmaps: false, + minFilter: LinearFilter, + format: RGBFormat + } ); + this.edgesRT.texture.name = 'SMAAPass.edges'; - // textures - var scope = this; + this.weightsRT = new WebGLRenderTarget( width, height, { + depthBuffer: false, + generateMipmaps: false, + minFilter: LinearFilter, + format: RGBAFormat + } ); + this.weightsRT.texture.name = 'SMAAPass.weights'; - var areaTextureImage = new Image(); - areaTextureImage.src = this.getAreaTexture(); - areaTextureImage.onload = function () { + // textures + const scope = this; - // assigning data to HTMLImageElement.src is asynchronous (see #15162) - scope.areaTexture.needsUpdate = true; + const areaTextureImage = new Image(); + areaTextureImage.src = this.getAreaTexture(); + areaTextureImage.onload = function () { - }; + // assigning data to HTMLImageElement.src is asynchronous (see #15162) + scope.areaTexture.needsUpdate = true; - this.areaTexture = new Texture(); - this.areaTexture.name = 'SMAAPass.area'; - this.areaTexture.image = areaTextureImage; - this.areaTexture.format = RGBFormat; - this.areaTexture.minFilter = LinearFilter; - this.areaTexture.generateMipmaps = false; - this.areaTexture.flipY = false; + }; - var searchTextureImage = new Image(); - searchTextureImage.src = this.getSearchTexture(); - searchTextureImage.onload = function () { + this.areaTexture = new Texture(); + this.areaTexture.name = 'SMAAPass.area'; + this.areaTexture.image = areaTextureImage; + this.areaTexture.format = RGBFormat; + this.areaTexture.minFilter = LinearFilter; + this.areaTexture.generateMipmaps = false; + this.areaTexture.flipY = false; - // assigning data to HTMLImageElement.src is asynchronous (see #15162) - scope.searchTexture.needsUpdate = true; + const searchTextureImage = new Image(); + searchTextureImage.src = this.getSearchTexture(); + searchTextureImage.onload = function () { - }; + // assigning data to HTMLImageElement.src is asynchronous (see #15162) + scope.searchTexture.needsUpdate = true; - this.searchTexture = new Texture(); - this.searchTexture.name = 'SMAAPass.search'; - this.searchTexture.image = searchTextureImage; - this.searchTexture.magFilter = NearestFilter; - this.searchTexture.minFilter = NearestFilter; - this.searchTexture.generateMipmaps = false; - this.searchTexture.flipY = false; + }; - // materials - pass 1 + this.searchTexture = new Texture(); + this.searchTexture.name = 'SMAAPass.search'; + this.searchTexture.image = searchTextureImage; + this.searchTexture.magFilter = NearestFilter; + this.searchTexture.minFilter = NearestFilter; + this.searchTexture.generateMipmaps = false; + this.searchTexture.flipY = false; - if ( SMAAEdgesShader === undefined ) { + // materials - pass 1 - console.error( 'THREE.SMAAPass relies on SMAAShader' ); + if ( SMAAEdgesShader === undefined ) { - } - - this.uniformsEdges = UniformsUtils.clone( SMAAEdgesShader.uniforms ); + console.error( 'THREE.SMAAPass relies on SMAAShader' ); - this.uniformsEdges[ 'resolution' ].value.set( 1 / width, 1 / height ); + } - this.materialEdges = new ShaderMaterial( { - defines: Object.assign( {}, SMAAEdgesShader.defines ), - uniforms: this.uniformsEdges, - vertexShader: SMAAEdgesShader.vertexShader, - fragmentShader: SMAAEdgesShader.fragmentShader - } ); + this.uniformsEdges = UniformsUtils.clone( SMAAEdgesShader.uniforms ); - // materials - pass 2 + this.uniformsEdges[ 'resolution' ].value.set( 1 / width, 1 / height ); - this.uniformsWeights = UniformsUtils.clone( SMAAWeightsShader.uniforms ); + this.materialEdges = new ShaderMaterial( { + defines: Object.assign( {}, SMAAEdgesShader.defines ), + uniforms: this.uniformsEdges, + vertexShader: SMAAEdgesShader.vertexShader, + fragmentShader: SMAAEdgesShader.fragmentShader + } ); - this.uniformsWeights[ 'resolution' ].value.set( 1 / width, 1 / height ); - this.uniformsWeights[ 'tDiffuse' ].value = this.edgesRT.texture; - this.uniformsWeights[ 'tArea' ].value = this.areaTexture; - this.uniformsWeights[ 'tSearch' ].value = this.searchTexture; + // materials - pass 2 - this.materialWeights = new ShaderMaterial( { - defines: Object.assign( {}, SMAAWeightsShader.defines ), - uniforms: this.uniformsWeights, - vertexShader: SMAAWeightsShader.vertexShader, - fragmentShader: SMAAWeightsShader.fragmentShader - } ); + this.uniformsWeights = UniformsUtils.clone( SMAAWeightsShader.uniforms ); - // materials - pass 3 + this.uniformsWeights[ 'resolution' ].value.set( 1 / width, 1 / height ); + this.uniformsWeights[ 'tDiffuse' ].value = this.edgesRT.texture; + this.uniformsWeights[ 'tArea' ].value = this.areaTexture; + this.uniformsWeights[ 'tSearch' ].value = this.searchTexture; - this.uniformsBlend = UniformsUtils.clone( SMAABlendShader.uniforms ); + this.materialWeights = new ShaderMaterial( { + defines: Object.assign( {}, SMAAWeightsShader.defines ), + uniforms: this.uniformsWeights, + vertexShader: SMAAWeightsShader.vertexShader, + fragmentShader: SMAAWeightsShader.fragmentShader + } ); - this.uniformsBlend[ 'resolution' ].value.set( 1 / width, 1 / height ); - this.uniformsBlend[ 'tDiffuse' ].value = this.weightsRT.texture; + // materials - pass 3 - this.materialBlend = new ShaderMaterial( { - uniforms: this.uniformsBlend, - vertexShader: SMAABlendShader.vertexShader, - fragmentShader: SMAABlendShader.fragmentShader - } ); + this.uniformsBlend = UniformsUtils.clone( SMAABlendShader.uniforms ); - this.needsSwap = false; + this.uniformsBlend[ 'resolution' ].value.set( 1 / width, 1 / height ); + this.uniformsBlend[ 'tDiffuse' ].value = this.weightsRT.texture; - this.fsQuad = new Pass.FullScreenQuad( null ); + this.materialBlend = new ShaderMaterial( { + uniforms: this.uniformsBlend, + vertexShader: SMAABlendShader.vertexShader, + fragmentShader: SMAABlendShader.fragmentShader + } ); -}; + this.needsSwap = false; -SMAAPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.fsQuad = new FullScreenQuad( null ); - constructor: SMAAPass, + } - render: function ( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { // pass 1 @@ -169,9 +167,9 @@ SMAAPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.edgesRT.setSize( width, height ); this.weightsRT.setSize( width, height ); @@ -180,20 +178,20 @@ SMAAPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.materialWeights.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); this.materialBlend.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); - }, + } - getAreaTexture: function () { + getAreaTexture() { return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAAIwCAIAAACOVPcQAACBeklEQVR42u39W4xlWXrnh/3WWvuciIzMrKxrV8/0rWbY0+SQFKcb4owIkSIFCjY9AC1BT/LYBozRi+EX+cV+8IMsYAaCwRcBwjzMiw2jAWtgwC8WR5Q8mDFHZLNHTarZGrLJJllt1W2qKrsumZWZcTvn7L3W54e1vrXX3vuciLPPORFR1XE2EomorB0nVuz//r71re/y/1eMvb4Cb3N11xV/PP/2v4UBAwJG/7H8urx6/25/Gf8O5hypMQ0EEEQwAqLfoN/Z+97f/SW+/NvcgQk4sGBJK6H7N4PFVL+K+e0N11yNfkKvwUdwdlUAXPHHL38oa15f/i/46Ih6SuMSPmLAYAwyRKn7dfMGH97jaMFBYCJUgotIC2YAdu+LyW9vvubxAP8kAL8H/koAuOKP3+q6+xGnd5kdYCeECnGIJViwGJMAkQKfDvB3WZxjLKGh8VSCCzhwEWBpMc5/kBbjawT4HnwJfhr+pPBIu7uu+OOTo9vsmtQcniMBGkKFd4jDWMSCRUpLjJYNJkM+IRzQ+PQvIeAMTrBS2LEiaiR9b/5PuT6Ap/AcfAFO4Y3dA3DFH7/VS+M8k4baEAQfMI4QfbVDDGIRg7GKaIY52qAjTAgTvGBAPGIIghOCYAUrGFNgzA7Q3QhgCwfwAnwe5vDejgG44o/fbm1C5ZlYQvQDARPAIQGxCWBM+wWl37ZQESb4gImexGMDouhGLx1Cst0Saa4b4AqO4Hk4gxo+3DHAV/nx27p3JziPM2pVgoiia5MdEzCGULprIN7gEEeQ5IQxEBBBQnxhsDb5auGmAAYcHMA9eAAz8PBol8/xij9+C4Djlim4gJjWcwZBhCBgMIIYxGAVIkH3ZtcBuLdtRFMWsPGoY9rN+HoBji9VBYdwD2ZQg4cnO7OSq/z4rU5KKdwVbFAjNojCQzTlCLPFSxtamwh2jMUcEgg2Wm/6XgErIBhBckQtGN3CzbVacERgCnfgLswhnvqf7QyAq/z4rRZm1YglYE3affGITaZsdIe2FmMIpnOCap25I6jt2kCwCW0D1uAD9sZctNGXcQIHCkINDQgc78aCr+zjtw3BU/ijdpw3zhCwcaONwBvdeS2YZKkJNJsMPf2JKEvC28RXxxI0ASJyzQCjCEQrO4Q7sFArEzjZhaFc4cdv+/JFdKULM4px0DfUBI2hIsy06BqLhGTQEVdbfAIZXYMPesq6VoCHICzUyjwInO4Y411//LYLs6TDa9wvg2CC2rElgAnpTBziThxaL22MYhzfkghz6GAs2VHbbdM91VZu1MEEpupMMwKyVTb5ij9+u4VJG/5EgEMMmFF01cFai3isRbKbzb+YaU/MQbAm2XSMoUPAmvZzbuKYRIFApbtlrfFuUGd6vq2hXNnH78ZLh/iFhsQG3T4D1ib7k5CC6vY0DCbtrohgLEIClXiGtl10zc0CnEGIhhatLBva7NP58Tvw0qE8yWhARLQ8h4+AhQSP+I4F5xoU+VilGRJs6wnS7ruti/4KvAY/CfdgqjsMy4pf8fodQO8/gnuX3f/3xi3om1/h7THr+co3x93PP9+FBUfbNUjcjEmhcrkT+8K7ml7V10Jo05mpIEFy1NmCJWx9SIKKt+EjAL4Ez8EBVOB6havuT/rByPvHXK+9zUcfcbb254+9fydJknYnRr1oGfdaiAgpxu1Rx/Rek8KISftx3L+DfsLWAANn8Hvw0/AFeAGO9DFV3c6D+CcWbL8Dj9e7f+T1k8AZv/d7+PXWM/Z+VvdCrIvuAKO09RpEEQJM0Ci6+B4xhTWr4cZNOvhktabw0ta0rSJmqz3Yw5/AKXwenod7cAhTmBSPKf6JBdvH8IP17h95pXqw50/+BFnj88fev4NchyaK47OPhhtI8RFSvAfDSNh0Ck0p2gLxGkib5NJj/JWCr90EWQJvwBzO4AHcgztwAFN1evHPUVGwfXON+0debT1YeGON9Yy9/63X+OguiwmhIhQhD7l4sMqlG3D86Suc3qWZ4rWjI1X7u0Ytw6x3rIMeIOPDprfe2XzNgyj6PahhBjO4C3e6puDgXrdg+/5l948vF3bqwZetZ+z9Rx9zdIY5pInPK4Nk0t+l52xdK2B45Qd87nM8fsD5EfUhIcJcERw4RdqqH7Yde5V7m1vhNmtedkz6EDzUMF/2jJYWbC+4fzzA/Y+/8PPH3j9dcBAPIRP8JLXd5BpAu03aziOL3VVHZzz3CXWDPWd+SH2AnxIqQoTZpo9Ckc6HIrFbAbzNmlcg8Ag8NFDDAhbJvTBZXbC94P7t68EXfv6o+21gUtPETU7bbkLxvNKRFG2+KXzvtObonPP4rBvsgmaKj404DlshFole1Glfh02fE7bYR7dZ82oTewIBGn1Md6CG6YUF26X376oevOLzx95vhUmgblI6LBZwTCDY7vMq0op5WVXgsObOXJ+1x3qaBl9j1FeLxbhU9w1F+Wiba6s1X/TBz1LnUfuYDi4r2C69f1f14BWfP+p+W2GFKuC9phcELMYRRLur9DEZTUdEH+iEqWdaM7X4WOoPGI+ZYD2+wcQ+y+ioHUZ9dTDbArzxmi/bJI9BND0Ynd6lBdve/butBw8+f/T9D3ABa3AG8W3VPX4hBin+bj8dMMmSpp5pg7fJ6xrBFE2WQQEWnV8Qg3FbAWzYfM1rREEnmvkN2o1+acG2d/9u68GDzx91v3mAjb1zkpqT21OipPKO0b9TO5W0nTdOmAQm0TObts3aBKgwARtoPDiCT0gHgwnbArzxmtcLc08HgF1asN0C4Ms/fvD5I+7PhfqyXE/b7RbbrGyRQRT9ARZcwAUmgdoz0ehJ9Fn7QAhUjhDAQSw0bV3T3WbNa59jzmiP6GsWbGXDX2ytjy8+f9T97fiBPq9YeLdBmyuizZHaqXITnXiMUEEVcJ7K4j3BFPurtB4bixW8wTpweL8DC95szWMOqucFYGsWbGU7p3TxxxefP+r+oTVktxY0v5hbq3KiOKYnY8ddJVSBxuMMVffNbxwIOERShst73HZ78DZrHpmJmH3K6sGz0fe3UUj0eyRrSCGTTc+rjVNoGzNSv05srAxUBh8IhqChiQgVNIIBH3AVPnrsnXQZbLTm8ammv8eVXn/vWpaTem5IXRlt+U/LA21zhSb9cye6jcOfCnOwhIAYXAMVTUNV0QhVha9xjgA27ODJbLbmitt3tRN80lqG6N/khgot4ZVlOyO4WNg3OIMzhIZQpUEHieg2im6F91hB3I2tubql6BYNN9Hj5S7G0G2tahslBWKDnOiIvuAEDzakDQKDNFQT6gbn8E2y4BBubM230YIpBnDbMa+y3dx0n1S0BtuG62lCCXwcY0F72T1VRR3t2ONcsmDjbmzNt9RFs2LO2hQNyb022JisaI8rAWuw4HI3FuAIhZdOGIcdjLJvvObqlpqvWTJnnQbyi/1M9O8UxWhBs//H42I0q1Yb/XPGONzcmm+ri172mHKvZBpHkJaNJz6v9jxqiklDj3U4CA2ugpAaYMWqNXsdXbmJNd9egCnJEsphXNM+MnK3m0FCJ5S1kmJpa3DgPVbnQnPGWIDspW9ozbcO4K/9LkfaQO2KHuqlfFXSbdNzcEcwoqNEFE9zcIXu9/6n/ym/BC/C3aJLzEKPuYVlbFnfhZ8kcWxV3dbv4bKl28566wD+8C53aw49lTABp9PWbsB+knfc/Li3eVizf5vv/xmvnPKg5ihwKEwlrcHqucuVcVOxEv8aH37E3ZqpZypUulrHEtIWKUr+txHg+ojZDGlwnqmkGlzcVi1dLiNSJiHjfbRNOPwKpx9TVdTn3K05DBx4psIk4Ei8aCkJahRgffk4YnEXe07T4H2RR1u27E6wfQsBDofUgjFUFnwC2AiVtA+05J2zpiDK2Oa0c5fmAecN1iJzmpqFZxqYBCYhFTCsUNEmUnIcZ6aEA5rQVhEywG6w7HSW02XfOoBlQmjwulOFQAg66SvJblrTEX1YtJ3uG15T/BH1OfOQeuR8g/c0gdpT5fx2SKbs9EfHTKdM8A1GaJRHLVIwhcGyydZsbifAFVKl5EMKNU2Hryo+06BeTgqnxzYjThVySDikbtJPieco75lYfKAJOMEZBTjoITuWHXXZVhcUDIS2hpiXHV9Ku4u44bN5OYLDOkJo8w+xJSMbhBRHEdEs9JZUCkQrPMAvaHyLkxgkEHxiNkx/x2YB0mGsQ8EUWj/stW5YLhtS5SMu+/YBbNPDCkGTUybN8krRLBGPlZkVOA0j+a1+rkyQKWGaPHPLZOkJhioQYnVZ2hS3zVxMtgC46KuRwbJNd9nV2PHgb36F194ecf/Yeu2vAFe5nm/bRBFrnY4BauE8ERmZRFUn0k8hbftiVYSKMEme2dJCJSCGYAlNqh87bXOPdUkGy24P6d1ll21MBqqx48Fvv8ZHH8HZFY7j/uAq1xMJUFqCSUlJPmNbIiNsmwuMs/q9CMtsZsFO6SprzCS1Z7QL8xCQClEelpjTduDMsmWD8S1PT152BtvmIGvUeDA/yRn83u/x0/4qxoPHjx+PXY9pqX9bgMvh/Nz9kpP4pOe1/fYf3axUiMdHLlPpZCNjgtNFAhcHEDxTumNONhHrBduW+vOyY++70WWnPXj98eA4kOt/mj/5E05l9+O4o8ePx67HFqyC+qSSnyselqjZGaVK2TadbFLPWAQ4NBhHqDCCV7OTpo34AlSSylPtIdd2AJZlyzYQrDJ5lcWGNceD80CunPLGGzsfD+7wRb95NevJI5docQ3tgCyr5bGnyaPRlmwNsFELViOOx9loebGNq2moDOKpHLVP5al2cymWHbkfzGXL7kfRl44H9wZy33tvt+PB/Xnf93e+nh5ZlU18wCiRUa9m7kib9LYuOk+hudQNbxwm0AQqbfloimaB2lM5fChex+ylMwuTbfmXQtmWlenZljbdXTLuOxjI/fDDHY4Hjx8/Hrse0zXfPFxbUN1kKqSCCSk50m0Ajtx3ub9XHBKHXESb8iO6E+qGytF4nO0OG3SXzbJlhxBnKtKyl0NwybjvYCD30aMdjgePHz8eu56SVTBbgxJMliQ3Oauwg0QHxXE2Ez/EIReLdQj42Gzb4CLS0YJD9xUx7bsi0vJi5mUbW1QzL0h0PFk17rtiIPfJk52MB48fPx67npJJwyrBa2RCCQRTbGZSPCxTPOiND4G2pYyOQ4h4jINIJh5wFU1NFZt+IsZ59LSnDqBjZ2awbOku+yInunLcd8VA7rNnOxkPHj9+PGY9B0MWJJNozOJmlglvDMXDEozdhQWbgs/U6oBanGzLrdSNNnZFjOkmbi5bNt1lX7JLLhn3vXAg9/h4y/Hg8ePHI9dzQMEkWCgdRfYykYKnkP7D4rIujsujaKPBsB54vE2TS00ccvFY/Tth7JXeq1hz+qgVy04sAJawTsvOknHfCwdyT062HA8eP348Zj0vdoXF4pilKa2BROed+9fyw9rWRXeTFXESMOanvDZfJuJaSXouQdMdDJZtekZcLLvEeK04d8m474UDuaenW44Hjx8/Xns9YYqZpszGWB3AN/4VHw+k7WSFtJ3Qicuqb/NlVmgXWsxh570xg2UwxUw3WfO6B5nOuO8aA7lnZxuPB48fPx6znm1i4bsfcbaptF3zNT78eFPtwi1OaCNOqp1x3zUGcs/PN++AGD1+fMXrSVm2baTtPhPahbPhA71wIHd2bXzRa69nG+3CraTtPivahV/55tXWg8fyRY/9AdsY8VbSdp8V7cKrrgdfM//z6ILQFtJ2nxHtwmuoB4/kf74+gLeRtvvMaBdeSz34+vifx0YG20jbfTa0C6+tHrwe//NmOG0L8EbSdp8R7cLrrQe/996O+ai3ujQOskpTNULa7jOjXXj99eCd8lHvoFiwsbTdZ0a78PrrwTvlo966pLuRtB2fFe3Cm6oHP9kNH/W2FryxtN1nTLvwRurBO+Kj3pWXHidtx2dFu/Bm68Fb81HvykuPlrb7LGkX3mw9eGs+6h1Y8MbSdjegXcguQLjmevDpTQLMxtJ2N6NdyBZu9AbrwVvwUW+LbteULUpCdqm0HTelXbhNPe8G68Gb8lFvVfYfSNuxvrTdTWoXbozAzdaDZzfkorOj1oxVxlIMlpSIlpLrt8D4hrQL17z+c3h6hU/wv4Q/utps4+bm+6P/hIcf0JwQ5oQGPBL0eKPTYEXTW+eL/2DKn73J9BTXYANG57hz1cEMviVf/4tf5b/6C5pTQkMIWoAq7hTpOJjtAM4pxKu5vg5vXeUrtI09/Mo/5H+4z+Mp5xULh7cEm2QbRP2tFIKR7WM3fPf/jZ3SWCqLM2l4NxID5zB72HQXv3jj/8mLR5xXNA5v8EbFQEz7PpRfl1+MB/hlAN65qgDn3wTgH13hK7T59bmP+NIx1SHHU84nLOITt3iVz8mNO+lPrjGAnBFqmioNn1mTyk1ta47R6d4MrX7tjrnjYUpdUbv2rVr6YpVfsGG58AG8Ah9eyUN8CX4WfgV+G8LVWPDGb+Zd4cU584CtqSbMKxauxTg+dyn/LkVgA+IR8KHtejeFKRtTmLLpxN6mYVLjYxwXf5x2VofiZcp/lwKk4wGOpYDnoIZPdg/AAbwMfx0+ge9dgZvYjuqKe4HnGnykYo5TvJbG0Vj12JagRhwKa44H95ShkZa5RyLGGdfYvG7aw1TsF6iapPAS29mNS3NmsTQZCmgTzFwgL3upCTgtBTRwvGMAKrgLn4evwin8+afJRcff+8izUGUM63GOOuAs3tJkw7J4kyoNreqrpO6cYLQeFUd7TTpr5YOTLc9RUUogUOVJQ1GYJaFLAW0oTmKyYS46ZooP4S4EON3xQ5zC8/CX4CnM4c1PE8ApexpoYuzqlP3d4S3OJP8ZDK7cKWNaTlqmgDiiHwl1YsE41w1zT4iRTm3DBqxvOUsbMKKDa/EHxagtnta072ejc3DOIh5ojvh8l3tk1JF/AV6FU6jh3U8HwEazLgdCLYSQ+MYiAI2ltomkzttUb0gGHdSUUgsIYjTzLG3mObX4FBRaYtpDVNZrih9TgTeYOBxsEnN1gOCTM8Bsw/ieMc75w9kuAT6A+/AiHGvN/+Gn4KRkiuzpNNDYhDGFndWRpE6SVfm8U5bxnSgVV2jrg6JCKmneqey8VMFgq2+AM/i4L4RUbfSi27lNXZ7R7W9RTcq/q9fk4Xw3AMQd4I5ifAZz8FcVtm9SAom/dyN4lczJQW/kC42ZrHgcCoIf1oVMKkVItmMBi9cOeNHGLqOZk+QqQmrbc5YmYgxELUUN35z2iohstgfLIFmcMV7s4CFmI74L9+EFmGsi+tGnAOD4Yk9gIpo01Y4cA43BWGygMdr4YZekG3OBIUXXNukvJS8tqa06e+lSDCtnqqMFu6hWHXCF+WaYt64m9QBmNxi7Ioy7D+fa1yHw+FMAcPt7SysFLtoG4PXAk7JOA3aAxBRqUiAdU9Yp5lK3HLSRFtOim0sa8euEt08xvKjYjzeJ2GU7YawexrnKI9tmobInjFXCewpwriY9+RR4aaezFhMhGCppKwom0ChrgFlKzyPKkGlTW1YQrE9HJqu8hKGgMc6hVi5QRq0PZxNfrYNgE64utmRv6KKHRpxf6VDUaOvNP5jCEx5q185My/7RKz69UQu2im5k4/eownpxZxNLwiZ1AZTO2ZjWjkU9uaB2HFn6Q3u0JcsSx/qV9hTEApRzeBLDJQXxYmTnq7bdLa3+uqFrxLJ5w1TehnNHx5ECvCh2g2c3hHH5YsfdaSKddztfjQ6imKFGSyFwlLzxEGPp6r5IevVjk1AMx3wMqi1NxDVjLBiPs9tbsCkIY5we5/ML22zrCScFxnNtzsr9Wcc3CnD+pYO+4VXXiDE0oc/vQQ/fDK3oPESJMYXNmJa/DuloJZkcTpcYE8lIH8Dz8DJMiynNC86Mb2lNaaqP/+L7f2fcE/yP7/Lde8xfgSOdMxvOixZf/9p3+M4hT1+F+zApxg9XfUvYjc8qX2lfOOpK2gNRtB4flpFu9FTKCp2XJRgXnX6olp1zyYjTKJSkGmLE2NjUr1bxFM4AeAAHBUFIeSLqXR+NvH/M9fOnfHzOD2vCSyQJKzfgsCh+yi/Mmc35F2fUrw7miW33W9hBD1vpuUojFphIyvg7aTeoymDkIkeW3XLHmguMzbIAJejN6B5MDrhipE2y6SoFRO/AK/AcHHZHNIfiWrEe/C6cr3f/yOvrQKB+zMM55/GQdLDsR+ifr5Fiuu+/y+M78LzOE5dsNuXC3PYvYWd8NXvphLSkJIasrlD2/HOqQ+RjcRdjKTGWYhhVUm4yxlyiGPuMsZR7sMCHUBeTuNWA7if+ifXgc/hovftHXs/DV+Fvwe+f8shzMiMcweFgBly3//vwJfg5AN4450fn1Hd1Rm1aBLu22Dy3y3H2+OqMemkbGZ4jozcDjJf6596xOLpC0eMTHbKnxLxH27uZ/bMTGs2jOaMOY4m87CfQwF0dw53oa1k80JRuz/XgS+8fX3N9Af4qPIMfzKgCp4H5TDGe9GGeFPzSsZz80SlPTxXjgwJmC45njzgt2vbQ4b4OAdUK4/vWhO8d8v6EE8fMUsfakXbPpFJeLs2ubM/qdm/la3WP91uWhxXHjoWhyRUq2iJ/+5mA73zwIIo+LoZ/SgvIRjAd1IMvvn98PfgOvAJfhhm8scAKVWDuaRaK8aQ9f7vuPDH6Bj47ZXau7rqYJ66mTDwEDU6lLbCjCK0qTXyl5mnDoeNRxanj3FJbaksTk0faXxHxLrssgPkWB9LnA/MFleXcJozzjwsUvUG0X/QCve51qkMDXp9mtcyOy3rwBfdvVJK7D6/ACSzg3RoruIq5UDeESfEmVclDxnniU82vxMLtceD0hGZWzBNPMM/jSPne2OVatiTKUpY5vY7gc0LdUAWeWM5tH+O2I66AOWw9xT2BuyRVLGdoDHUsVRXOo/c+ZdRXvFfnxWyIV4upFLCl9eAL7h8Zv0QH8Ry8pA2cHzQpGesctVA37ZtklBTgHjyvdSeKY/RZw/kJMk0Y25cSNRWSigQtlULPTw+kzuJPeYEkXjQRpoGZobYsLF79pyd1dMRHInbgFTZqNLhDqiIsTNpoex2WLcy0/X6rHcdMMQvFSd5dWA++4P7xv89deACnmr36uGlL69bRCL6BSZsS6c0TU2TKK5gtWCzgAOOwQcurqk9j8whvziZSMLcq5hbuwBEsYjopUBkqw1yYBGpLA97SRElEmx5MCInBY5vgLk94iKqSWmhIGmkJ4Bi9m4L645J68LyY4wsFYBfUg5feP/6gWWm58IEmKQM89hq7KsZNaKtP5TxxrUZZVkNmMJtjbKrGxLNEbHPJxhqy7lAmbC32ZqeF6lTaknRWcYaFpfLUBh/rwaQycCCJmW15Kstv6jRHyJFry2C1ahkkIW0LO75s61+owxK1y3XqweX9m5YLM2DPFeOjn/iiqCKJ+yKXF8t5Yl/kNsqaSCryxPq5xWTFIaP8KSW0RYxqupaUf0RcTNSSdJZGcKYdYA6kdtrtmyBckfKXwqk0pHpUHlwWaffjNRBYFPUDWa8e3Lt/o0R0CdisKDM89cX0pvRHEfM8ca4t0s2Xx4kgo91MPQJ/0c9MQYq0co8MBh7bz1fio0UUHLR4aAIOvOmoYO6kwlEVODSSTliWtOtH6sPkrtctF9ZtJ9GIerBskvhdVS5cFNv9s1BU0AbdUgdK4FG+dRnjFmDTzniRMdZO1QhzMK355vigbdkpz9P6qjUGE5J2qAcXmwJ20cZUiAD0z+pGMx6xkzJkmEf40Hr4qZfVg2XzF9YOyoV5BjzVkUJngKf8lgNYwKECEHrCNDrWZzMlflS3yBhr/InyoUgBc/lKT4pxVrrC6g1YwcceK3BmNxZcAtz3j5EIpqguh9H6wc011YN75cKDLpFDxuwkrPQmUwW4KTbj9mZTwBwLq4aQMUZbHm1rylJ46dzR0dua2n3RYCWZsiHROeywyJGR7mXKlpryyCiouY56sFkBWEnkEB/raeh/Sw4162KeuAxMQpEkzy5alMY5wamMsWKKrtW2WpEWNnReZWONKWjrdsKZarpFjqCslq773PLmEhM448Pc3+FKr1+94vv/rfw4tEcu+lKTBe4kZSdijBrykwv9vbCMPcLQTygBjzVckSLPRVGslqdunwJ4oegtFOYb4SwxNgWLCmD7T9kVjTv5YDgpo0XBmN34Z/rEHp0sgyz7lngsrm4lvMm2Mr1zNOJYJ5cuxuQxwMGJq/TP5emlb8fsQBZviK4t8hFL+zbhtlpwaRSxQRWfeETjuauPsdGxsBVdO7nmP4xvzSoT29pRl7kGqz+k26B3Oy0YNV+SXbbQas1ctC/GarskRdFpKczVAF1ZXnLcpaMuzVe6lZ2g/1ndcvOVgRG3sdUAY1bKD6achijMPdMxV4muKVorSpiDHituH7rSTs7n/4y5DhRXo4FVBN4vO/zbAcxhENzGbHCzU/98Mcx5e7a31kWjw9FCe/zNeYyQjZsWb1uc7U33pN4Mji6hCLhivqfa9Ss6xLg031AgfesA/l99m9fgvnaF9JoE6bYKmkGNK3aPbHB96w3+DnxFm4hs0drLsk7U8kf/N/CvwQNtllna0rjq61sH8L80HAuvwH1tvBy2ChqWSCaYTaGN19sTvlfzFD6n+iKTbvtayfrfe9ueWh6GJFoxLdr7V72a5ZpvHcCPDzma0wTO4EgbLyedxstO81n57LYBOBzyfsOhUKsW1J1BB5vr/tz8RyqOFylQP9Tvst2JALsC5lsH8PyQ40DV4ANzYa4dedNiKNR1s+x2wwbR7q4/4cTxqEk4LWDebfisuo36JXLiWFjOtLrlNWh3K1rRS4xvHcDNlFnNmWBBAl5SWaL3oPOfnvbr5pdjVnEaeBJSYjuLEkyLLsWhKccadmOphZkOPgVdalj2QpSmfOsADhMWE2ZBu4+EEJI4wKTAuCoC4xwQbWXBltpxbjkXJtKxxabo9e7tyhlgb6gNlSbUpMh+l/FaqzVwewGu8BW1Zx7pTpQDJUjb8tsUTW6+GDXbMn3mLbXlXJiGdggxFAoUrtPS3wE4Nk02UZG2OOzlk7fRs7i95QCLo3E0jtrjnM7SR3uS1p4qtS2nJ5OwtQVHgOvArLBFijZUV9QtSl8dAY5d0E0hM0w3HS2DpIeB6m/A1+HfhJcGUq4sOxH+x3f5+VO+Ds9rYNI7zPXOYWPrtf8bYMx6fuOAX5jzNR0PdsuON+X1f7EERxMJJoU6GkTEWBvVolVlb5lh3tKCg6Wx1IbaMDdJ+9sUCc5KC46hKGCk3IVOS4TCqdBNfUs7Kd4iXf2RjnT/LLysJy3XDcHLh/vde3x8DoGvwgsa67vBk91G5Pe/HbOe7xwym0NXbtiuuDkGO2IJDh9oQvJ4cY4vdoqLDuoH9Zl2F/ofsekn8lkuhIlhQcffUtSjytFyp++p6NiE7Rqx/lodgKVoceEp/CP4FfjrquZaTtj2AvH5K/ywpn7M34K/SsoYDAdIN448I1/0/wveW289T1/lX5xBzc8N5IaHr0XMOQdHsIkDuJFifj20pBm5jzwUv9e2FhwRsvhAbalCIuIw3bhJihY3p6nTFFIZgiSYjfTf3aXuOjmeGn4bPoGvwl+CFzTRczBIuHBEeImHc37/lGfwZR0cXzVDOvaKfNHvwe+suZ771K/y/XcBlsoN996JpBhoE2toYxOznNEOS5TJc6Id5GEXLjrWo+LEWGNpPDU4WAwsIRROu+1vM+0oW37z/MBN9kqHnSArwPfgFJ7Cq/Ai3Ie7g7ncmI09v8sjzw9mzOAEXoIHxURueaAce5V80f/DOuuZwHM8vsMb5wBzOFWM7wymTXPAEvm4vcFpZ2ut0VZRjkiP2MlmLd6DIpbGSiHOjdnUHN90hRYmhTnmvhzp1iKDNj+b7t5hi79lWGwQ+HN9RsfFMy0FXbEwhfuczKgCbyxYwBmcFhhvo/7a44v+i3XWcwDP86PzpGQYdWh7csP5dBvZ1jNzdxC8pBGuxqSW5vw40nBpj5JhMwvOzN0RWqERHMr4Lv1kWX84xLR830G3j6yqZ1a8UstTlW+qJPOZ+sZ7xZPKTJLhiNOAFd6tk+jrTH31ncLOxid8+nzRb128HhUcru/y0Wn6iT254YPC6FtVSIMoW2sk727AhvTtrWKZTvgsmckfXYZWeNRXx/3YQ2OUxLDrbHtN11IwrgXT6c8dATDwLniYwxzO4RzuQqTKSC5gAofMZ1QBK3zQ4JWobFbcvJm87FK+6JXrKahLn54m3p+McXzzYtP8VF/QpJuh1OwieElEoI1pRxPS09FBrkq2tWCU59+HdhNtTIqKm8EBrw2RTOEDpG3IKo2Y7mFdLm3ZeVjYwVw11o/oznceMve4CgMfNym/utA/d/ILMR7gpXzRy9eDsgLcgbs8O2Va1L0zzIdwGGemTBuwROHeoMShkUc7P+ISY3KH5ZZeWqO8mFTxQYeXTNuzvvK5FGPdQfuu00DwYFY9dyhctEt+OJDdnucfpmyhzUJzfsJjr29l8S0bXBfwRS9ZT26tmMIdZucch5ZboMz3Nio3nIOsYHCGoDT4kUA9MiXEp9Xsui1S8th/kbWIrMBxDGLodWUQIWcvnXy+9M23xPiSMOiRPqM+YMXkUN3gXFrZJwXGzUaMpJfyRS9ZT0lPe8TpScuRlbMHeUmlaKDoNuy62iWNTWNFYjoxFzuJs8oR+RhRx7O4SVNSXpa0ZJQ0K1LAHDQ+D9IepkMXpcsq5EVCvClBUIzDhDoyKwDw1Lc59GbTeORivugw1IcuaEOaGWdNm+Ps5fQ7/tm0DjMegq3yM3vb5j12qUId5UZD2oxDSEWOZMSqFl/W+5oynWDa/aI04tJRQ2eTXusg86SQVu/nwSYwpW6wLjlqIzwLuxGIvoAvul0PS+ZNz0/akp/pniO/8JDnGyaCkzbhl6YcqmK/69prxPqtpx2+Km9al9sjL+rwMgHw4jE/C8/HQ3m1vBuL1fldbzd8mOueVJ92syqdEY4KJjSCde3mcRw2TA6szxedn+zwhZMps0XrqEsiUjnC1hw0TELC2Ek7uAAdzcheXv1BYLagspxpzSAoZZUsIzIq35MnFQ9DOrlNB30jq3L4pkhccKUAA8/ocvN1Rzx9QyOtERs4CVsJRK/DF71kPYrxYsGsm6RMh4cps5g1DOmM54Ly1ii0Hd3Y/BMk8VWFgBVmhqrkJCPBHAolwZaWzLR9Vb7bcWdX9NyUYE+uB2BKfuaeBUcjDljbYVY4DdtsVWvzRZdWnyUzDpjNl1Du3aloAjVJTNDpcIOVVhrHFF66lLfJL1zJr9PQ2nFJSBaKoDe+sAvLufZVHVzYh7W0h/c6AAZ+7Tvj6q9j68G/cTCS/3n1vLKHZwNi+P+pS0WkZNMBMUl+LDLuiE4omZy71r3UFMwNJV+VJ/GC5ixVUkBStsT4gGKh0Gm4Oy3qvq7Lbmq24nPdDuDR9deR11XzP4vFu3TYzfnIyiSVmgizUYGqkIXNdKTY9pgb9D2Ix5t0+NHkVzCdU03suWkkVZAoCONCn0T35gAeW38de43mf97sMOpSvj4aa1KYUm58USI7Wxxes03bAZdRzk6UtbzMaCQ6IxO0dy7X+XsjoD16hpsBeGz9dfzHj+R/Hp8nCxZRqkEDTaCKCSywjiaoMJ1TITE9eg7Jqnq8HL6gDwiZb0u0V0Rr/rmvqjxKuaLCX7ZWXTvAY+uvm3z8CP7nzVpngqrJpZKwWnCUjIviYVlirlGOzPLI3SMVyp/elvBUjjDkNhrtufFFErQ8pmdSlbK16toBHlt/HV8uHMX/vEGALkV3RJREiSlopxwdMXOZPLZ+ix+kAHpMKIk8UtE1ygtquttwxNhphrIZ1IBzjGF3IIGxGcBj6q8bHJBG8T9vdsoWrTFEuebEZuVxhhClH6P5Zo89OG9fwHNjtNQTpD0TG9PJLEYqvEY6Rlxy+ZZGfL0Aj62/bnQCXp//eeM4KzfQVJbgMQbUjlMFIm6TpcfWlZje7NBSV6IsEVmumWIbjiloUzQX9OzYdo8L1wjw2PrrpimONfmfNyzKklrgnEkSzT5QWYQW40YShyzqsRmMXbvVxKtGuYyMKaU1ugenLDm5Ily4iT14fP11Mx+xJv+zZ3MvnfdFqxU3a1W/FTB4m3Qfsyc1XUcdVhDeUDZXSFHHLQj/Y5jtC7ZqM0CXGwB4bP11i3LhOvzPGygYtiUBiwQV/4wFO0majijGsafHyRLu0yG6q35cL1rOpVxr2s5cM2jJYMCdc10Aj6q/blRpWJ//+dmm5psMl0KA2+AFRx9jMe2WbC4jQxnikd4DU8TwUjRVacgdlhmr3bpddzuJ9zXqr2xnxJfzP29RexdtjDVZqzkqa6PyvcojGrfkXiJ8SEtml/nYskicv0ivlxbqjemwUjMw5evdg8fUX9nOiC/lf94Q2i7MURk9nW1MSj5j8eAyV6y5CN2S6qbnw3vdA1Iwq+XOSCl663udN3IzLnrt+us25cI1+Z83SXQUldqQq0b5XOT17bGpLd6ssN1VMPf8c+jG8L3NeCnMdF+Ra3fRa9dft39/LuZ/3vwHoHrqGmQFafmiQw6eyzMxS05K4bL9uA+SKUQzCnSDkqOGokXyJvbgJ/BHI+qvY69//4rl20NsmK2ou2dTsyIALv/91/8n3P2Aao71WFGi8KKv1fRC5+J67Q/507/E/SOshqN5TsmYIjVt+kcjAx98iz/4SaojbIV1rexE7/C29HcYD/DX4a0rBOF5VTu7omsb11L/AWcVlcVZHSsqGuXLLp9ha8I//w3Mv+T4Ew7nTBsmgapoCrNFObIcN4pf/Ob/mrvHTGqqgAupL8qWjWPS9m/31jAe4DjA+4+uCoQoT/zOzlrNd3qd4SdphFxsUvYwGWbTWtISc3wNOWH+kHBMfc6kpmpwPgHWwqaSUG2ZWWheYOGQGaHB+eQ/kn6b3pOgLV+ODSn94wDvr8Bvb70/LLuiPPEr8OGVWfDmr45PZyccEmsVXZGe1pRNX9SU5+AVQkNTIVPCHF/jGmyDC9j4R9LfWcQvfiETmgMMUCMN1uNCakkweZsowdYobiMSlnKA93u7NzTXlSfe+SVbfnPQXmg9LpYAQxpwEtONyEyaueWM4FPjjyjG3uOaFmBTWDNgBXGEiQpsaWhnAqIijB07Dlsy3fUGeP989xbWkyf+FF2SNEtT1E0f4DYYVlxFlbaSMPIRMk/3iMU5pME2SIWJvjckciebkQuIRRyhUvkHg/iUljG5kzVog5hV7vIlCuBrmlhvgPfNHQM8lCf+FEGsYbMIBC0qC9a0uuy2wLXVbLBaP5kjHokCRxapkQyzI4QEcwgYHRZBp+XEFTqXFuNVzMtjXLJgX4gAid24Hjwc4N3dtVSe+NNiwTrzH4WVUOlDobUqr1FuAgYllc8pmzoVrELRHSIW8ViPxNy4xwjBpyR55I6J220qQTZYR4guvUICJiSpr9gFFle4RcF/OMB7BRiX8sSfhpNSO3lvEZCQfLUVTKT78Ek1LRLhWN+yLyTnp8qWUZ46b6vxdRGXfHVqx3eI75YaLa4iNNiK4NOW7wPW6lhbSOF9/M9qw8e/aoB3d156qTzxp8pXx5BKAsYSTOIIiPkp68GmTq7sZtvyzBQaRLNxIZ+paozHWoLFeExIhRBrWitHCAHrCF7/thhD8JhYz84wg93QRV88wLuLY8zF8sQ36qF1J455bOlgnELfshKVxYOXKVuKx0jaj22sczTQqPqtV/XDgpswmGTWWMSDw3ssyUunLLrVPGjYRsH5ggHeHSWiV8kT33ycFSfMgkoOK8apCye0J6VW6GOYvffgU9RWsukEi2kUV2nl4dOYUzRik9p7bcA4ggdJ53LxKcEe17B1R8eqAd7dOepV8sTXf5lhejoL85hUdhDdknPtKHFhljOT+bdq0hxbm35p2nc8+Ja1Iw+tJykgp0EWuAAZYwMVwac5KzYMslhvgHdHRrxKnvhTYcfKsxTxtTETkjHO7rr3zjoV25lAQHrqpV7bTiy2aXMmUhTBnKS91jhtR3GEoF0oLnWhWNnYgtcc4N0FxlcgT7yz3TgNIKkscx9jtV1ZKpWW+Ub1tc1eOv5ucdgpx+FJy9pgbLE7xDyXb/f+hLHVGeitHOi6A7ybo3sF8sS7w7cgdk0nJaOn3hLj3uyD0Zp5pazFIUXUpuTTU18d1EPkDoX8SkmWTnVIozEdbTcZjoqxhNHf1JrSS/AcvHjZ/SMHhL/7i5z+POsTUh/8BvNfYMTA8n+yU/MlTZxSJDRStqvEuLQKWwDctMTQogUDyQRoTQG5Kc6oQRE1yV1jCA7ri7jdZyK0sYTRjCR0Hnnd+y7nHxNgTULqw+8wj0mQKxpYvhjm9uSUxg+TTy7s2GtLUGcywhXSKZN275GsqlclX90J6bRI1aouxmgL7Q0Nen5ziM80SqMIo8cSOo+8XplT/5DHNWsSUr/6lLN/QQ3rDyzLruEW5enpf7KqZoShEduuSFOV7DLX7Ye+GmXb6/hnNNqKsVXuMDFpb9Y9eH3C6NGEzuOuI3gpMH/I6e+zDiH1fXi15t3vA1czsLws0TGEtmPEJdiiFPwlwKbgLHAFk4P6ZyPdymYYHGE0dutsChQBl2JcBFlrEkY/N5bQeXQ18gjunuMfMfsBlxJSx3niO485fwO4fGD5T/+3fPQqkneWVdwnw/3bMPkW9Wbqg+iC765Zk+xcT98ibKZc2EdgHcLoF8cSOo/Oc8fS+OyEULF4g4sJqXVcmfMfsc7A8v1/yfGXmL9I6Fn5pRwZhsPv0TxFNlAfZCvG+Oohi82UC5f/2IsJo0cTOm9YrDoKhFPEUr/LBYTUNht9zelHXDqwfPCIw4owp3mOcIQcLttWXFe3VZ/j5H3cIc0G6oPbCR+6Y2xF2EC5cGUm6wKC5tGEzhsWqw5hNidUiKX5gFWE1GXh4/Qplw4sVzOmx9QxU78g3EF6wnZlEN4FzJ1QPSLEZz1KfXC7vd8ssGdIbNUYpVx4UapyFUHzJoTOo1McSkeNn1M5MDQfs4qQuhhX5vQZFw8suwWTcyYTgioISk2YdmkhehG4PkE7w51inyAGGaU+uCXADabGzJR1fn3lwkty0asIo8cROm9Vy1g0yDxxtPvHDAmpu+PKnM8Ix1wwsGw91YJqhteaWgjYBmmQiebmSpwKKzE19hx7jkzSWOm66oPbzZ8Yj6kxVSpYjVAuvLzYMCRo3oTQecOOjjgi3NQ4l9K5/hOGhNTdcWVOTrlgYNkEXINbpCkBRyqhp+LdRB3g0OU6rMfW2HPCFFMV9nSp+uB2woepdbLBuJQyaw/ZFysXrlXwHxI0b0LovEkiOpXGA1Ijagf+KUNC6rKNa9bQnLFqYNkEnMc1uJrg2u64ELPBHpkgWbmwKpJoDhMwNbbGzAp7Yg31wS2T5rGtzit59PrKhesWG550CZpHEzpv2NGRaxlNjbMqpmEIzygJqQfjypycs2pg2cS2RY9r8HUqkqdEgKTWtWTKoRvOBPDYBltja2SO0RGjy9UHtxwRjA11ujbKF+ti5cIR9eCnxUg6owidtyoU5tK4NLji5Q3HCtiyF2IqLGYsHViOXTXOYxucDqG0HyttqYAKqYo3KTY1ekyDXRAm2AWh9JmsVh/ccg9WJ2E8YjG201sPq5ULxxX8n3XLXuMInbft2mk80rRGjCGctJ8/GFdmEQ9Ug4FlE1ll1Y7jtiraqm5Fe04VV8lvSVBL8hiPrfFVd8+7QH3Qbu2ipTVi8cvSGivc9cj8yvH11YMHdNSERtuOslM97feYFOPKzGcsI4zW0YGAbTAOaxCnxdfiYUmVWslxiIblCeAYr9VYR1gM7GmoPrilunSxxeT3DN/2eBQ9H11+nk1adn6VK71+5+Jfct4/el10/7KBZfNryUunWSCPxPECk1rdOv1WVSrQmpC+Tl46YD3ikQYcpunSQgzVB2VHFhxHVGKDgMEY5GLlQnP7FMDzw7IacAWnO6sBr12u+XanW2AO0wQ8pknnFhsL7KYIqhkEPmEXFkwaN5KQphbkUmG72wgw7WSm9RiL9QT925hkjiVIIhphFS9HKI6/8QAjlpXqg9W2C0apyaVDwKQwrwLY3j6ADR13ZyUNByQXHQu6RY09Hu6zMqXRaNZGS/KEJs0cJEe9VH1QdvBSJv9h09eiRmy0V2uJcqHcShcdvbSNg5fxkenkVprXM9rDVnX24/y9MVtncvbKY706anNl3ASll9a43UiacVquXGhvq4s2FP62NGKfQLIQYu9q1WmdMfmUrDGt8eDS0cXozH/fjmUH6Jruvm50hBDSaEU/2Ru2LEN/dl006TSc/g7tfJERxGMsgDUEr104pfWH9lQaN+M4KWQjwZbVc2rZVNHsyHal23wZtIs2JJqtIc/WLXXRFCpJkfE9jvWlfFbsNQ9pP5ZBS0zKh4R0aMFj1IjTcTnvi0Zz2rt7NdvQb2mgbju1plsH8MmbnEk7KbK0b+wC2iy3aX3szW8xeZvDwET6hWZYwqTXSSG+wMETKum0Dq/q+x62gt2ua2ppAo309TRk9TPazfV3qL9H8z7uhGqGqxNVg/FKx0HBl9OVUORn8Q8Jx9gFttGQUDr3tzcXX9xGgN0EpzN9mdZ3GATtPhL+CjxFDmkeEU6x56kqZRusLzALXVqkCN7zMEcqwjmywDQ6OhyUe0Xao1Qpyncrg6wKp9XfWDsaZplElvQ/b3sdweeghorwBDlHzgk1JmMc/wiERICVy2VJFdMjFuLQSp3S0W3+sngt2njwNgLssFGVQdJ0tu0KH4ky1LW4yrbkuaA6Iy9oz/qEMMXMMDWyIHhsAyFZc2peV9hc7kiKvfULxCl9iddfRK1f8kk9qvbdOoBtOg7ZkOZ5MsGrSHsokgLXUp9y88smniwWyuFSIRVmjplga3yD8Uij5QS1ZiM4U3Qw5QlSm2bXjFe6jzzBFtpg+/YBbLAWG7OPynNjlCw65fukGNdkJRf7yM1fOxVzbxOJVocFoYIaGwH22mIQkrvu1E2nGuebxIgW9U9TSiukPGU+Lt++c3DJPKhyhEEbXCQLUpae2exiKy6tMPe9mDRBFCEMTWrtwxN8qvuGnt6MoihKWS5NSyBhbH8StXoAz8PLOrRgLtOT/+4vcu+7vDLnqNvztOq7fmd8sMmY9Xzn1zj8Dq8+XVdu2Nv0IIySgEdQo3xVHps3Q5i3fLFsV4aiqzAiBhbgMDEd1uh8qZZ+lwhjkgokkOIv4xNJmyncdfUUzgB4oFMBtiu71Xumpz/P+cfUP+SlwFExwWW62r7b+LSPxqxn/gvMZ5z9C16t15UbNlq+jbGJtco7p8wbYlL4alSyfWdeuu0j7JA3JFNuVAwtst7F7FhWBbPFNKIUORndWtLraFLmMu7KFVDDOzqkeaiN33YAW/r76wR4XDN/yN1z7hejPau06EddkS/6XThfcz1fI/4K736fO48vlxt2PXJYFaeUkFS8U15XE3428xdtn2kc8GQlf1vkIaNRRnOMvLTWrZbElEHeLWi1o0dlKPAh1MVgbbVquPJ5+Cr8LU5/H/+I2QlHIU2ClXM9G8v7Rr7oc/hozfUUgsPnb3D+I+7WF8kNO92GY0SNvuxiE+2Bt8prVJTkzE64sfOstxuwfxUUoyk8VjcTlsqe2qITSFoSj6Epd4KsT6BZOWmtgE3hBfir8IzZDwgV4ZTZvD8VvPHERo8v+vL1DASHTz/i9OlKueHDjK5Rnx/JB1Vb1ioXdBra16dmt7dgik10yA/FwJSVY6XjA3oy4SqM2frqDPPSRMex9qs3XQtoWxMj7/Er8GWYsXgjaVz4OYumP2+9kbxvny/6kvWsEBw+fcb5bInc8APdhpOSs01tEqIkoiZjbAqKMruLbJYddHuHFRIyJcbdEdbl2sVLaySygunutBg96Y2/JjKRCdyHV+AEFtTvIpbKIXOamknYSiB6KV/0JetZITgcjjk5ZdaskBtWO86UF0ap6ozGXJk2WNiRUlCPFir66lzdm/SLSuK7EUdPz8f1z29Skq6F1fXg8+5UVR6bszncP4Tn4KUkkdJ8UFCY1zR1i8RmL/qQL3rlei4THG7OODlnKko4oI01kd3CaM08Ia18kC3GNoVaO9iDh+hWxSyTXFABXoau7Q6q9OxYg/OVEMw6jdbtSrJ9cBcewGmaZmg+bvkUnUUaGr+ZfnMH45Ivevl61hMcXsxYLFTu1hTm2zViCp7u0o5l+2PSUh9bDj6FgYypufBDhqK2+oXkiuHFHR3zfj+9PtA8oR0xnqX8qn+sx3bFODSbbF0X8EUvWQ8jBIcjo5bRmLOljDNtcqNtOe756h3l0VhKa9hDd2l1eqmsnh0MNMT/Cqnx6BInumhLT8luljzQ53RiJeA/0dxe5NK0o2fA1+GLXr6eNQWHNUOJssQaTRlGpLHKL9fD+IrQzTOMZS9fNQD4AnRNVxvTdjC+fJdcDDWQcyB00B0t9BDwTxXgaAfzDZ/DBXzRnfWMFRwuNqocOmX6OKNkY63h5n/fFcB28McVHqnXZVI27K0i4rDLNE9lDKV/rT+udVbD8dFFu2GGZ8mOt0kAXcoX3ZkIWVtw+MNf5NjR2FbivROHmhV1/pj2egv/fMGIOWTIWrV3Av8N9imV9IWml36H6cUjqEWNv9aNc+veb2sH46PRaHSuMBxvtW+twxctq0z+QsHhux8Q7rCY4Ct8lqsx7c6Sy0dl5T89rIeEuZKoVctIk1hNpfavER6yyH1Vvm3MbsUHy4ab4hWr/OZPcsRBphnaV65/ZcdYPNNwsjN/djlf9NqCw9U5ExCPcdhKxUgLSmfROpLp4WSUr8ojdwbncbvCf+a/YzRaEc6QOvXcGO256TXc5Lab9POvB+AWY7PigWYjzhifbovuunzRawsO24ZqQQAqguBtmpmPB7ysXJfyDDaV/aPGillgz1MdQg4u5MYaEtBNNHFjkRlSpd65lp4hd2AVPTfbV7FGpyIOfmNc/XVsPfg7vzaS/3nkvLL593ANLvMuRMGpQIhiF7kUEW9QDpAUbTWYBcbp4WpacHHY1aacqQyjGZS9HI3yCBT9kUZJhVOD+zUDvEH9ddR11fzPcTDQ5TlgB0KwqdXSavk9BC0pKp0WmcuowSw07VXmXC5guzSa4p0UvRw2lbDiYUx0ExJJRzWzi6Gm8cnEkfXXsdcG/M/jAJa0+bmCgdmQ9CYlNlSYZOKixmRsgiFxkrmW4l3KdFKv1DM8tk6WxPYJZhUUzcd8Kdtgrw/gkfXXDT7+avmfVak32qhtkg6NVdUS5wgkru1YzIkSduTW1FDwVWV3JQVJVuieTc0y4iDpFwc7/BvSalvKdQM8sv662cevz/+8sQVnjVAT0W2wLllw1JiMhJRxgDjCjLQsOzSFSgZqx7lAW1JW0e03yAD3asC+GD3NbQhbe+mN5GXH1F83KDOM4n/e5JIuH4NpdQARrFPBVptUNcjj4cVMcFSRTE2NpR1LEYbYMmfWpXgP9KejaPsLUhuvLCsVXznAG9dfx9SR1ud/3hZdCLHb1GMdPqRJgqDmm76mHbvOXDtiO2QPUcKo/TWkQ0i2JFXpBoo7vij1i1Lp3ADAo+qvG3V0rM//vFnnTE4hxd5Ka/Cor5YEdsLVJyKtDgVoHgtW11pWSjolPNMnrlrVj9Fv2Qn60twMwKPqr+N/wvr8z5tZcDsDrv06tkqyzESM85Ycv6XBWA2birlNCXrI6VbD2lx2L0vQO0QVTVVLH4SE67fgsfVXv8n7sz7/85Z7cMtbE6f088wSaR4kCkCm10s6pKbJhfqiUNGLq+0gLWC6eUAZFPnLjwqtKd8EwGvWX59t7iPW4X/eAN1svgRVSY990YZg06BD1ohLMtyFTI4pKTJsS9xREq9EOaPWiO2gpms7397x6nQJkbh+Fz2q/rqRROX6/M8bJrqlVW4l6JEptKeUFuMYUbtCQ7CIttpGc6MY93x1r1vgAnRXvY5cvwWPqb9uWQm+lP95QxdNMeWhOq1x0Db55C7GcUv2ZUuN6n8iKzsvOxibC//Yfs9Na8r2Rlz02vXXDT57FP/zJi66/EJSmsJKa8QxnoqW3VLQ+jZVUtJwJ8PNX1NQCwfNgdhhHD9on7PdRdrdGPF28rJr1F+3LBdeyv+8yYfLoMYet1vX4upNAjVvwOUWnlNXJXlkzk5Il6kqeoiL0C07qno+/CYBXq/+utlnsz7/Mzvy0tmI4zm4ag23PRN3t/CWryoUVJGm+5+K8RJ0V8Hc88/XHUX/HfiAq7t+BH+x6v8t438enWmdJwFA6ZINriLGKv/95f8lT9/FnyA1NMVEvQyaXuu+gz36f/DD73E4pwqpLcvm/o0Vle78n//+L/NPvoefp1pTJye6e4A/D082FERa5/opeH9zpvh13cNm19/4v/LDe5xMWTi8I0Ta0qKlK27AS/v3/r+/x/2GO9K2c7kVMonDpq7//jc5PKCxeNPpFVzaRr01wF8C4Pu76hXuX18H4LduTr79guuFD3n5BHfI+ZRFhY8w29TYhbbLi/bvBdqKE4fUgg1pBKnV3FEaCWOWyA+m3WpORZr/j+9TKJtW8yBTF2/ZEODI9/QavHkVdGFp/Pjn4Q+u5hXapsP5sOH+OXXA1LiKuqJxiMNbhTkbdJTCy4llEt6NnqRT4dhg1V3nbdrm6dYMecA1yTOL4PWTE9L5VzPFlLBCvlG58AhehnN4uHsAYinyJ+AZ/NkVvELbfOBUuOO5syBIEtiqHU1k9XeISX5bsimrkUUhnGDxourN8SgUsCZVtKyGbyGzHXdjOhsAvOAswSRyIBddRdEZWP6GZhNK/yjwew9ehBo+3jEADu7Ay2n8mDc+TS7awUHg0OMzR0LABhqLD4hJEh/BEGyBdGlSJoXYXtr+3HS4ijzVpgi0paWXtdruGTknXBz+11qT1Q2inxaTzQCO46P3lfLpyS4fou2PH/PupwZgCxNhGlj4IvUuWEsTkqMWm6i4xCSMc9N1RDQoCVcuGItJ/MRWefais+3synowi/dESgJjkilnWnBTGvRWmaw8oR15257t7CHmCf8HOn7cwI8+NQBXMBEmAa8PMRemrNCEhLGEhDQKcGZWS319BX9PFBEwGTbRBhLbDcaV3drFcDqk5kCTd2JF1Wp0HraqBx8U0wwBTnbpCadwBA/gTH/CDrcCs93LV8E0YlmmcyQRQnjBa8JESmGUfIjK/7fkaDJpmD2QptFNVJU1bbtIAjjWQizepOKptRjbzR9Kag6xZmMLLjHOtcLT3Tx9o/0EcTT1XN3E45u24AiwEypDJXihKjQxjLprEwcmRKclaDNZCVqr/V8mYWyFADbusiY5hvgFoU2vio49RgJLn5OsReRFN6tabeetiiy0V7KFHT3HyZLx491u95sn4K1QQSPKM9hNT0wMVvAWbzDSVdrKw4zRjZMyJIHkfq1VAVCDl/bUhNKlGq0zGr05+YAceXVPCttVk0oqjVwMPt+BBefx4yPtGVkUsqY3CHDPiCM5ngupUwCdbkpd8kbPrCWHhkmtIKLEetF2499eS1jZlIPGYnlcPXeM2KD9vLS0bW3ktYNqUllpKLn5ZrsxlIzxvDu5eHxzGLctkZLEY4PgSOg2IUVVcUONzUDBEpRaMoXNmUc0tFZrTZquiLyKxrSm3DvIW9Fil+AkhXu5PhEPx9mUNwqypDvZWdKlhIJQY7vn2OsnmBeOWnYZ0m1iwbbw1U60by5om47iHRV6fOgzjMf/DAZrlP40Z7syxpLK0lJ0gqaAK1c2KQKu7tabTXkLFz0sCftuwX++MyNeNn68k5Buq23YQhUh0SNTJa1ioQ0p4nUG2y0XilF1JqODqdImloPS4Bp111DEWT0jJjVv95uX9BBV7eB3bUWcu0acSVM23YZdd8R8UbQUxJ9wdu3oMuhdt929ME+mh6JXJ8di2RxbTi6TbrDquqV4aUKR2iwT6aZbyOwEXN3DUsWr8Hn4EhwNyHuXHh7/pdaUjtR7vnDh/d8c9xD/s5f501eQ1+CuDiCvGhk1AN/4Tf74RfxPwD3toLarR0zNtsnPzmS64KIRk861dMWCU8ArasG9T9H0ZBpsDGnjtAOM2+/LuIb2iIUGXNgl5ZmKD/Tw8TlaAuihaFP5yrw18v4x1898zIdP+DDAX1bM3GAMvPgRP/cJn3zCW013nrhHkrITyvYuwOUkcHuKlRSW5C6rzIdY4ppnF7J8aAJbQepgbJYBjCY9usGXDKQxq7RZfh9eg5d1UHMVATRaD/4BHK93/1iAgYZ/+jqPn8Dn4UExmWrpa3+ZOK6MvM3bjwfzxNWA2dhs8+51XHSPJiaAhGSpWevEs5xHLXcEGFXYiCONySH3fPWq93JIsBiSWvWyc3CAN+EcXoT7rCSANloPPoa31rt/5PUA/gp8Q/jDD3hyrjzlR8VkanfOvB1XPubt17vzxAfdSVbD1pzAnfgyF3ycadOTOTXhpEUoLC1HZyNGW3dtmjeXgr2r56JNmRwdNNWaQVBddd6rh4MhviEB9EFRD/7RGvePvCbwAL4Mx/D6M541hHO4D3e7g6PafdcZVw689z7NGTwo5om7A8sPhccT6qKcl9NJl9aM/9kX+e59Hh1yPqGuCCZxuITcsmNaJ5F7d0q6J3H48TO1/+M57085q2icdu2U+W36Ldllz9Agiv4YGljoEN908EzvDOrBF98/vtJwCC/BF2AG75xxEmjmMIcjxbjoaxqOK3/4hPOZzhMPBpYPG44CM0dTVm1LjLtUWWVz1Bcf8tEx0zs8O2A2YVHRxKYOiy/aOVoAaMu0i7ubu43njjmd4ibMHU1sIDHaQNKrZND/FZYdk54oCXetjq7E7IVl9eAL7t+oHnwXXtLx44czzoRFHBztYVwtH1d+NOMkupZ5MTM+gUmq90X+Bh9zjRlmaQ+m7YMqUL/veemcecAtOJ0yq1JnVlN27di2E0+Klp1tAJ4KRw1eMI7aJjsO3R8kPSI3fUFXnIOfdQe86sIIVtWDL7h//Ok6vj8vwDk08NEcI8zz7OhBy+WwalzZeZ4+0XniRfst9pAJqQHDGLzVQ2pheZnnv1OWhwO43/AgcvAEXEVVpa4db9sGvNK8wjaENHkfFQ4Ci5i7dqnQlPoLQrHXZDvO3BIXZbJOBrOaEbML6sFL798I4FhKihjHMsPjBUZYCMFr6nvaArxqXPn4lCa+cHfSa2cP27g3Z3ziYTRrcbQNGLQmGF3F3cBdzzzX7AILx0IB9rbwn9kx2G1FW3Inic+ZLIsVvKR8Zwfj0l1fkqo8LWY1M3IX14OX3r9RKTIO+d9XzAI8qRPGPn/4NC2n6o4rN8XJ82TOIvuVA8zLKUHRFgBCetlDZlqR1gLKjS39xoE7Bt8UvA6BxuEDjU3tFsEijgA+615tmZkXKqiEENrh41iLDDZNq4pKTWR3LZfnos81LOuNa15cD956vLMsJd1rqYp51gDUQqMYm2XsxnUhD2jg1DM7SeuJxxgrmpfISSXVIJIS5qJJSvJPEQ49DQTVIbYWJ9QWa/E2+c/oPK1drmC7WSfJRNKBO5Yjvcp7Gc3dmmI/Xh1kDTEuiSnWqQf37h+fTMhGnDf6dsS8SQfQWlqqwXXGlc/PEZ/SC5mtzIV0nAshlQdM/LvUtYutrEZ/Y+EAFtq1k28zQhOwLr1AIeANzhF8t9qzTdZf2qRKO6MWE9ohBYwibbOmrFtNmg3mcS+tB28xv2uKd/agYCvOP+GkSc+0lr7RXzyufL7QbkUpjLjEWFLqOIkAGu2B0tNlO9Eau2W1qcOUvVRgKzypKIQZ5KI3q0MLzqTNRYqiZOqmtqloIRlmkBHVpHmRYV6/HixbO6UC47KOFJnoMrVyr7wYz+SlW6GUaghYbY1I6kkxA2W1fSJokUdSh2LQ1GAimRGm0MT+uu57H5l7QgOWxERpO9moLRPgTtquWCfFlGlIjQaRly9odmzMOWY+IBO5tB4sW/0+VWGUh32qYk79EidWKrjWuiLpiVNGFWFRJVktyeXWmbgBBzVl8anPuXyNJlBJOlKLTgAbi/EYHVHxWiDaVR06GnHQNpJcWcK2jJtiCfG2sEHLzuI66sGrMK47nPIInPnu799935aOK2cvmvubrE38ZzZjrELCmXM2hM7UcpXD2oC3+ECVp7xtIuxptJ0jUr3sBmBS47TVxlvJ1Sqb/E0uLdvLj0lLr29ypdd/eMX3f6lrxGlKwKQxEGvw0qHbkbwrF3uHKwVENbIV2wZ13kNEF6zD+x24aLNMfDTCbDPnEikZFyTNttxWBXDaBuM8KtI2rmaMdUY7cXcUPstqTGvBGSrFWIpNMfbdea990bvAOC1YX0qbc6smDS1mPxSJoW4fwEXvjMmhlijDRq6qale6aJEuFGoppYDoBELQzLBuh/mZNx7jkinv0EtnUp50lO9hbNK57lZaMAWuWR5Yo9/kYwcYI0t4gWM47Umnl3YmpeBPqSyNp3K7s2DSAS/39KRuEN2bS4xvowV3dFRMx/VFcp2Yp8w2nTO9hCXtHG1kF1L4KlrJr2wKfyq77R7MKpFKzWlY9UkhYxyHWW6nBWPaudvEAl3CGcNpSXPZ6R9BbBtIl6cHL3gIBi+42CYXqCx1gfGWe7Ap0h3luyXdt1MKy4YUT9xSF01G16YEdWsouW9mgDHd3veyA97H+Ya47ZmEbqMY72oPztCGvK0onL44AvgC49saZKkWRz4veWljE1FHjbRJaWv6ZKKtl875h4CziFCZhG5rx7tefsl0aRT1bMHZjm8dwL/6u7wCRysaQblQoG5yAQN5zpatMNY/+yf8z+GLcH/Qn0iX2W2oEfXP4GvwQHuIL9AYGnaO3zqAX6946nkgqZNnUhx43DIdQtMFeOPrgy/y3Yd85HlJWwjLFkU3kFwq28xPnuPhMWeS+tDLV9Otllq7pQCf3uXJDN9wFDiUTgefHaiYbdfi3b3u8+iY6TnzhgehI1LTe8lcd7s1wJSzKbahCRxKKztTLXstGAiu3a6rPuQs5pk9TWAan5f0BZmGf7Ylxzzk/A7PAs4QPPPAHeFQ2hbFHszlgZuKZsJcUmbDC40sEU403cEjczstOEypa+YxevL4QBC8oRYqWdK6b7sK25tfE+oDZgtOQ2Jg8T41HGcBE6fTWHn4JtHcu9S7uYgU5KSCkl/mcnq+5/YBXOEr6lCUCwOTOM1taOI8mSxx1NsCXBEmLKbMAg5MkwbLmpBaFOPrNSlO2HnLiEqW3tHEwd8AeiQLmn+2gxjC3k6AxREqvKcJbTEzlpLiw4rNZK6oJdidbMMGX9FULKr0AkW+2qDEPBNNm5QAt2Ik2nftNWHetubosHLo2nG4vQA7GkcVCgVCgaDixHqo9UUn1A6OshapaNR/LPRYFV8siT1cCtJE0k/3WtaNSuUZYKPnsVIW0xXWnMUxq5+En4Kvw/MqQmVXnAXj9Z+9zM98zM/Agy7F/qqj2Nh67b8HjFnPP3iBn/tkpdzwEJX/whIcQUXOaikeliCRGUk7tiwF0rItwMEhjkZ309hikFoRAmLTpEXWuHS6y+am/KB/fM50aLEhGnSMwkpxzOov4H0AvgovwJ1iGzDLtJn/9BU+fAINfwUe6FHSLhu83viV/+/HrOePX+STT2B9uWGbrMHHLldRBlhS/CJQmcRxJFqZica01XixAZsYiH1uolZxLrR/SgxVIJjkpQP4PE9sE59LKLr7kltSBogS5tyszzH8Fvw8/AS8rNOg0xUS9fIaHwb+6et8Q/gyvKRjf5OusOzGx8evA/BP4IP11uN/grca5O0lcsPLJ5YjwI4QkJBOHa0WdMZYGxPbh2W2nR9v3WxEWqgp/G3+6VZbRLSAAZ3BhdhAaUL33VUSw9yjEsvbaQ9u4A/gGXwZXoEHOuU1GSj2chf+Mo+f8IcfcAxfIKVmyunRbYQVnoevwgfw3TXXcw++xNuP4fhyueEUNttEduRVaDttddoP0eSxLe2LENk6itYxlrxBNBYrNNKSQmeaLcm9c8UsaB5WyO6675yyQIAWSDpBVoA/gxmcwEvwoDv0m58UE7gHn+fJOa8/Ywan8EKRfjsopF83eCglX/Sfr7OeaRoQfvt1CGvIDccH5BCvw1sWIzRGC/66t0VTcLZQZtm6PlAasbOJ9iwWtUo7biktTSIPxnR24jxP1ZKaqq+2RcXM9OrBAm/AAs7hDJ5bNmGb+KIfwCs8a3jnjBrOFeMjHSCdbKr+2uOLfnOd9eiA8Hvvwwq54VbP2OqwkB48Ytc4YEOiH2vTXqodabfWEOzso4qxdbqD5L6tbtNPECqbhnA708DZH4QOJUXqScmUlks7Ot6FBuZw3n2mEbaUX7kDzxHOOQk8nKWMzAzu6ZZ8sOFw4RK+6PcuXo9tB4SbMz58ApfKDXf3szjNIIbGpD5TKTRxGkEMLjLl+K3wlWXBsCUxIDU+jbOiysESqAy1MGUJpXgwbTWzNOVEziIXZrJ+VIztl1PUBxTSo0dwn2bOmfDRPD3TRTGlfbCJvO9KvuhL1hMHhB9wPuPRLGHcdOWG2xc0U+5bQtAJT0nRTewXL1pgk2+rZAdeWmz3jxAqfNQQdzTlbF8uJ5ecEIWvTkevAHpwz7w78QujlD/Lr491bD8/1vhM2yrUQRrWXNQY4fGilfctMWYjL72UL/qS9eiA8EmN88nbNdour+PBbbAjOjIa4iBhfFg6rxeKdEGcL6p3EWR1Qq2Qkhs2DrnkRnmN9tG2EAqmgPw6hoL7Oza7B+3SCrR9tRftko+Lsf2F/mkTndN2LmzuMcKTuj/mX2+4Va3ki16+nnJY+S7MefpkidxwnV+4wkXH8TKnX0tsYzYp29DOOoSW1nf7nTh2akYiWmcJOuTidSaqESrTYpwjJJNVGQr+rLI7WsqerHW6Kp/oM2pKuV7T1QY9gjqlZp41/WfKpl56FV/0kvXQFRyeQ83xaTu5E8p5dNP3dUF34ihyI3GSpeCsywSh22ZJdWto9winhqifb7VRvgktxp13vyjrS0EjvrRfZ62uyqddSWaWYlwTPAtJZ2oZ3j/Sgi/mi+6vpzesfAcWNA0n8xVyw90GVFGuZjTXEQy+6GfLGLMLL523f5E0OmxVjDoOuRiH91RKU+vtoCtH7TgmvBLvtFXWLW15H9GTdVw8ow4IlRLeHECN9ym1e9K0I+Cbnhgv4Yu+aD2HaQJ80XDqOzSGAV4+4yCqBxrsJAX6ZTIoX36QnvzhhzzMfFW2dZVLOJfo0zbce5OvwXMFaZ81mOnlTVXpDZsQNuoYWveketKb5+6JOOsgX+NTm7H49fUTlx+WLuWL7qxnOFh4BxpmJx0p2gDzA/BUARuS6phR+pUsY7MMboAHx5xNsSVfVZcYSwqCKrqon7zM+8ecCkeS4nm3rINuaWvVNnMRI1IRpxTqx8PZUZ0Br/UEduo3B3hNvmgZfs9gQPj8vIOxd2kndir3awvJ6BLvoUuOfFWNYB0LR1OQJoUySKb9IlOBx74q1+ADC2G6rOdmFdJcD8BkfualA+BdjOOzP9uUhGUEX/TwhZsUduwRr8wNuXKurCixLBgpQI0mDbJr9dIqUuV+92ngkJZ7xduCk2yZKbfWrH1VBiTg9VdzsgRjW3CVXCvAwDd+c1z9dWw9+B+8MJL/eY15ZQ/HqvTwVdsZn5WQsgRRnMaWaecu3jFvMBEmgg+FJFZsnSl0zjB9OqPYaBD7qmoVyImFvzi41usesV0julaAR9dfR15Xzv9sEruRDyk1nb+QaLU67T885GTls6YgcY+UiMa25M/pwGrbCfzkvR3e0jjtuaFtnwuagHTSb5y7boBH119HXhvwP487jJLsLJ4XnUkHX5sLbS61dpiAXRoZSCrFJ+EjpeU3puVfitngYNo6PJrAigKktmwjyQdZpfq30mmtulaAx9Zfx15Xzv+cyeuiBFUs9zq8Kq+XB9a4PVvph3GV4E3y8HENJrN55H1X2p8VyqSKwVusJDKzXOZzplWdzBUFK9e+B4+uv468xvI/b5xtSAkBHQaPvtqWzllVvEOxPbuiE6+j2pvjcKsbvI7txnRErgfH7LdXqjq0IokKzga14GzQ23SSbCQvO6r+Or7SMIr/efOkkqSdMnj9mBx2DRsiY29Uj6+qK9ZrssCKaptR6HKURdwUYeUWA2kPzVKQO8ku2nU3Anhs/XWkBx3F/7wJtCTTTIKftthue1ty9xvNYLY/zo5KSbIuKbXpbEdSyeRyYdAIwKY2neyoc3+k1XUaufYga3T9daMUx/r8z1s10ITknIO0kuoMt+TB8jK0lpayqqjsJ2qtXAYwBU932zinimgmd6mTRDnQfr88q36NAI+tv24E8Pr8zxtasBqx0+xHH9HhlrwsxxNUfKOHQaZBITNf0uccj8GXiVmXAuPEAKSdN/4GLHhs/XWj92dN/uetNuBMnVR+XWDc25JLjo5Mg5IZIq226tmCsip2zZliL213YrTlL2hcFjpCduyim3M7/eB16q/blQsv5X/esDRbtJeabLIosWy3ycavwLhtxdWzbMmHiBTiVjJo6lCLjXZsi7p9PEPnsq6X6wd4bP11i0rD5fzPm/0A6brrIsllenZs0lCJlU4abakR59enZKrKe3BZihbTxlyZ2zl1+g0wvgmA166/bhwDrcn/7Ddz0eWZuJvfSESug6NzZsox3Z04FIxz0mUjMwVOOVTq1CQ0AhdbBGVdjG/CgsfUX7esJl3K/7ytWHRv683praW/8iDOCqWLLhpljDY1ZpzK75QiaZoOTpLKl60auHS/97oBXrv+umU9+FL+5+NtLFgjqVLCdbmj7pY5zPCPLOHNCwXGOcLquOhi8CmCWvbcuO73XmMUPab+ug3A6/A/78Bwe0bcS2+tgHn4J5pyS2WbOck0F51Vq3LcjhLvZ67p1ABbaL2H67bg78BfjKi/jr3+T/ABV3ilLmNXTI2SpvxWBtt6/Z//D0z/FXaGbSBgylzlsEGp+5//xrd4/ae4d8DUUjlslfIYS3t06HZpvfQtvv0N7AHWqtjP2pW08QD/FLy//da38vo8PNlKHf5y37Dxdfe/oj4kVIgFq3koLReSR76W/bx//n9k8jonZxzWTANVwEniDsg87sOSd/z7//PvMp3jQiptGVWFX2caezzAXwfgtzYUvbr0iozs32c3Uge7varH+CNE6cvEYmzbPZ9hMaYDdjK4V2iecf6EcEbdUDVUARda2KzO/JtCuDbNQB/iTeL0EG1JSO1jbXS+nLxtPMDPw1fh5+EPrgSEKE/8Gry5A73ui87AmxwdatyMEBCPNOCSKUeRZ2P6Myb5MRvgCHmA9ywsMifU+AYXcB6Xa5GibUC5TSyerxyh0j6QgLVpdyhfArRTTLqQjwe4HOD9s92D4Ap54odXAPBWLAwB02igG5Kkc+piN4lvODIFGAZgT+EO4Si1s7fjSR7vcQETUkRm9O+MXyo9OYhfe4xt9STQ2pcZRLayCV90b4D3jR0DYAfyxJ+eywg2IL7NTMXna7S/RpQ63JhWEM8U41ZyQGjwsVS0QBrEKLu8xwZsbi4wLcCT+OGidPIOCe1PiSc9Qt+go+vYqB7cG+B9d8cAD+WJPz0Am2gxXgU9IneOqDpAAXOsOltVuMzpdakJXrdPCzXiNVUpCeOos5cxnpQT39G+XVLhs1osQVvJKPZyNq8HDwd4d7pNDuWJPxVX7MSzqUDU6gfadKiNlUFTzLeFHHDlzO4kpa7aiKhBPGKwOqxsBAmYkOIpipyXcQSPlRTf+Tii0U3EJGaZsDER2qoB3h2hu0qe+NNwUooYU8y5mILbJe6OuX+2FTKy7bieTDAemaQyQ0CPthljSWO+xmFDIYiESjM5xKd6Ik5lvLq5GrQ3aCMLvmCA9wowLuWJb9xF59hVVP6O0CrBi3ZjZSNOvRy+I6klNVRJYRBaEzdN+imiUXQ8iVF8fsp+W4JXw7WISW7fDh7lptWkCwZ4d7QTXyBPfJMYK7SijjFppGnlIVJBJBYj7eUwtiP1IBXGI1XCsjNpbjENVpSAJ2hq2LTywEly3hUYazt31J8w2+aiLx3g3fohXixPfOMYm6zCGs9LVo9MoW3MCJE7R5u/WsOIjrqBoHUO0bJE9vxBpbhsd3+Nb4/vtPCZ4oZYCitNeYuC/8UDvDvy0qvkiW/cgqNqRyzqSZa/s0mqNGjtKOoTm14zZpUauiQgVfqtQiZjq7Q27JNaSK5ExRcrGCXO1FJYh6jR6CFqK7bZdQZ4t8g0rSlPfP1RdBtqaa9diqtzJkQ9duSryi2brQXbxDwbRUpFMBHjRj8+Nt7GDKgvph9okW7LX47gu0SpGnnFQ1S1lYldOsC7hYteR574ZuKs7Ei1lBsfdz7IZoxzzCVmmVqaSySzQbBVAWDek+N4jh9E/4VqZrJjPwiv9BC1XcvOWgO8275CVyBPvAtTVlDJfZkaZGU7NpqBogAj/xEHkeAuJihWYCxGN6e8+9JtSegFXF1TrhhLGP1fak3pebgPz192/8gB4d/6WT7+GdYnpH7hH/DJzzFiYPn/vjW0SgNpTNuPIZoAEZv8tlGw4+RLxy+ZjnKa5NdFoC7UaW0aduoYse6+bXg1DLg6UfRYwmhGEjqPvF75U558SANrElK/+MdpXvmqBpaXOa/MTZaa1DOcSiLaw9j0NNNst3c+63c7EKTpkvKHzu6bPbP0RkuHAVcbRY8ijP46MIbQeeT1mhA+5PV/inyDdQipf8LTvMXbwvoDy7IruDNVZKTfV4CTSRUYdybUCnGU7KUTDxLgCknqUm5aAW6/1p6eMsOYsphLzsHrE0Y/P5bQedx1F/4yPHnMB3/IOoTU9+BL8PhtjuFKBpZXnYNJxTuv+2XqolKR2UQgHhS5novuxVySJhBNRF3SoKK1XZbbXjVwWNyOjlqWJjrWJIy+P5bQedyldNScP+HZ61xKSK3jyrz+NiHG1hcOLL/+P+PDF2gOkekKGiNWKgJ+8Z/x8Iv4DdQHzcpZyF4v19I27w9/yPGDFQvmEpKtqv/TLiWMfn4sofMm9eAH8Ao0zzh7h4sJqYtxZd5/D7hkYPneDzl5idlzNHcIB0jVlQ+8ULzw/nc5/ojzl2juE0apD7LRnJxe04dMz2iOCFNtGFpTuXA5AhcTRo8mdN4kz30nVjEC4YTZQy4gpC7GlTlrePKhGsKKgeXpCYeO0MAd/GH7yKQUlXPLOasOH3FnSphjHuDvEu4gB8g66oNbtr6eMbFIA4fIBJkgayoXriw2XEDQPJrQeROAlY6aeYOcMf+IVYTU3XFlZufMHinGywaW3YLpObVBAsbjF4QJMsVUSayjk4voPsHJOQfPWDhCgDnmDl6XIRerD24HsGtw86RMHOLvVSHrKBdeVE26gKB5NKHzaIwLOmrqBWJYZDLhASG16c0Tn+CdRhWDgWXnqRZUTnPIHuMJTfLVpkoYy5CzylHVTGZMTwkGAo2HBlkQplrJX6U+uF1wZz2uwS1SQ12IqWaPuO4baZaEFBdukksJmkcTOm+YJSvoqPFzxFA/YUhIvWxcmSdPWTWwbAKVp6rxTtPFUZfKIwpzm4IoMfaYQLWgmlG5FME2gdBgm+J7J+rtS/XBbaVLsR7bpPQnpMFlo2doWaVceHk9+MkyguZNCJ1He+kuHTWyQAzNM5YSUg/GlTk9ZunAsg1qELVOhUSAK0LABIJHLKbqaEbHZLL1VA3VgqoiOKXYiS+HRyaEKgsfIqX64HYWbLRXy/qWoylIV9gudL1OWBNgBgTNmxA6b4txDT4gi3Ri7xFSLxtXpmmYnzAcWDZgY8d503LFogz5sbonDgkKcxGsWsE1OI+rcQtlgBBCSOKD1mtqYpIU8cTvBmAT0yZe+zUzeY92fYjTtGipXLhuR0ePoHk0ofNWBX+lo8Z7pAZDk8mEw5L7dVyZZoE/pTewbI6SNbiAL5xeygW4xPRuLCGbhcO4RIeTMFYHEJkYyEO9HmJfXMDEj/LaH781wHHZEtqSQ/69UnGpzH7LKIAZEDSPJnTesJTUa+rwTepI9dLJEawYV+ZkRn9g+QirD8vF8Mq0jFQ29js6kCS3E1+jZIhgPNanHdHFqFvPJLHqFwQqbIA4jhDxcNsOCCQLDomaL/dr5lyJaJU6FxPFjO3JOh3kVMcROo8u+C+jo05GjMF3P3/FuDLn5x2M04xXULPwaS6hBYki+MrMdZJSgPHlcB7nCR5bJ9Kr5ACUn9jk5kivdd8tk95SOGrtqu9lr2IhK65ZtEl7ZKrp7DrqwZfRUSN1el7+7NJxZbywOC8neNKTch5vsTEMNsoCCqHBCqIPRjIPkm0BjvFODGtto99rCl+d3wmHkW0FPdpZtC7MMcVtGFQjJLX5bdQ2+x9ypdc313uj8xlsrfuLgWXz1cRhZvJYX0iNVBRcVcmCXZs6aEf3RQF2WI/TcCbKmGU3IOoDJGDdDub0+hYckt6PlGu2BcxmhbTdj/klhccLGJMcqRjMJP1jW2ETqLSWJ/29MAoORluJ+6LPffBZbi5gqi5h6catQpmOT7/OFf5UorRpLzCqcMltBLhwd1are3kztrSzXO0LUbXRQcdLh/RdSZ+swRm819REDrtqzC4es6Gw4JCKlSnjYVpo0xeq33PrADbFLL3RuCmObVmPN+24kfa+AojDuM4umKe2QwCf6EN906HwjujaitDs5o0s1y+k3lgbT2W2i7FJdnwbLXhJUBq/9liTctSmFC/0OqUinb0QddTWamtjbHRFuWJJ6NpqZ8vO3fZJ37Db+2GkaPYLGHs7XTTdiFQJ68SkVJFVmY6McR5UycflNCsccHFaV9FNbR4NttLxw4pQ7wJd066Z0ohVbzihaxHVExd/ay04oxUKWt+AsdiQ9OUyZ2krzN19IZIwafSTFgIBnMV73ADj7V/K8u1MaY2sJp2HWm0f41tqwajEvdHWOJs510MaAqN4aoSiPCXtN2KSi46dUxHdaMquar82O1x5jqhDGvqmoE9LfxcY3zqA7/x3HA67r9ZG4O6Cuxu12/+TP+eLP+I+HErqDDCDVmBDO4larujNe7x8om2rMug0MX0rL1+IWwdwfR+p1TNTyNmVJ85ljWzbWuGv8/C7HD/izjkHNZNYlhZcUOKVzKFUxsxxN/kax+8zPWPSFKw80rJr9Tizyj3o1gEsdwgWGoxPezDdZ1TSENE1dLdNvuKL+I84nxKesZgxXVA1VA1OcL49dFlpFV5yJMhzyCmNQ+a4BqusPJ2bB+xo8V9u3x48VVIEPS/mc3DvAbXyoYr6VgDfh5do5hhHOCXMqBZUPhWYbWZECwVJljLgMUWOCB4MUuMaxGNUQDVI50TQ+S3kFgIcu2qKkNSHVoM0SHsgoZxP2d5HH8B9woOk4x5bPkKtAHucZsdykjxuIpbUrSILgrT8G7G5oCW+K0990o7E3T6AdW4TilH5kDjds+H64kS0mz24grtwlzDHBJqI8YJQExotPvoC4JBq0lEjjQkyBZ8oH2LnRsQ4Hu1QsgDTJbO8fQDnllitkxuVskoiKbRF9VwzMDvxHAdwB7mD9yCplhHFEyUWHx3WtwCbSMMTCUCcEmSGlg4gTXkHpZXWQ7kpznK3EmCHiXInqndkQjunG5kxTKEeGye7jWz9cyMR2mGiFQ15ENRBTbCp+Gh86vAyASdgmJq2MC6hoADQ3GosP0QHbnMHjyBQvQqfhy/BUbeHd5WY/G/9LK/8Ka8Jd7UFeNWEZvzPb458Dn8DGLOe3/wGL/4xP+HXlRt+M1PE2iLhR8t+lfgxsuh7AfO2AOf+owWhSZRYQbd622hbpKWKuU+XuvNzP0OseRDa+mObgDHJUSc/pKx31QdKffQ5OIJpt8GWjlgTwMc/w5MPCR/yl1XC2a2Yut54SvOtMev55Of45BOat9aWG27p2ZVORRvnEk1hqWMVUmqa7S2YtvlIpspuF1pt0syuZS2NV14mUidCSfzQzg+KqvIYCMljIx2YK2AO34fX4GWdu5xcIAb8MzTw+j/lyWM+Dw/gjs4GD6ehNgA48kX/AI7XXM/XAN4WHr+9ntywqoCakCqmKP0rmQrJJEErG2Upg1JObr01lKQy4jskWalKYfJ/EDLMpjNSHFEUAde2fltaDgmrNaWQ9+AAb8I5vKjz3L1n1LriB/BXkG/wwR9y/oRX4LlioHA4LzP2inzRx/DWmutRweFjeP3tNeSGlaE1Fde0OS11yOpmbIp2u/jF1n2RRZviJM0yBT3IZl2HWImKjQOxIyeU325b/qWyU9Moj1o07tS0G7qJDoGHg5m8yeCxMoEH8GU45tnrNM84D2l297DQ9t1YP7jki/7RmutRweEA77/HWXOh3HCxkRgldDQkAjNTMl2Iloc1qN5JfJeeTlyTRzxURTdn1Ixv2uKjs12AbdEWlBtmVdk2k7FFwj07PCZ9XAwW3dG+8xKzNFr4EnwBZpy9Qzhh3jDXebBpYcpuo4fQ44u+fD1dweEnHzI7v0xuuOALRUV8rXpFyfSTQYkhd7IHm07jpyhlkCmI0ALYqPTpUxXS+z4jgDj1Pflvmz5ecuItpIBxyTHpSTGWd9g1ApfD/bvwUhL4nT1EzqgX7cxfCcNmb3mPL/qi9SwTHJ49oj5ZLjccbTG3pRmlYi6JCG0mQrAt1+i2UXTZ2dv9IlQpN5naMYtviaXlTrFpoMsl3bOAFEa8sqPj2WCMrx3Yjx99qFwO59Aw/wgx+HlqNz8oZvA3exRDvuhL1jMQHPaOJ0+XyA3fp1OfM3qObEVdhxjvynxNMXQV4+GJyvOEFqeQBaIbbO7i63rpxCltdZShPFxkjM2FPVkn3TG+Rp9pO3l2RzFegGfxGDHIAh8SteR0C4HopXzRF61nheDw6TFN05Ebvq8M3VKKpGjjO6r7nhudTEGMtYM92HTDaR1FDMXJ1eThsbKfywyoWwrzRSXkc51flG3vIid62h29bIcFbTGhfV+faaB+ohj7dPN0C2e2lC96+XouFByen9AsunLDJZ9z7NExiUc0OuoYW6UZkIyx2YUR2z6/TiRjyKMx5GbbjLHvHuf7YmtKghf34LJfx63Yg8vrvN2zC7lY0x0tvKezo4HmGYDU+Gab6dFL+KI761lDcNifcjLrrr9LWZJctG1FfU1uwhoQE22ObjdfkSzY63CbU5hzs21WeTddH2BaL11Gi7lVdlxP1nkxqhnKhVY6knS3EPgVGg1JpN5cP/hivujOelhXcPj8HC/LyI6MkteVjlolBdMmF3a3DbsuAYhL44dxzthWSN065xxUd55Lmf0wRbOYOqH09/o9WbO2VtFdaMb4qBgtFJoT1SqoN8wPXMoXLb3p1PUEhxfnnLzGzBI0Ku7FxrKsNJj/8bn/H8fPIVOd3rfrklUB/DOeO+nkghgSPzrlPxluCMtOnDL4Yml6dK1r3vsgMxgtPOrMFUZbEUbTdIzii5beq72G4PD0DKnwjmBULUVFmy8t+k7fZ3pKc0Q4UC6jpVRqS9Umv8bxw35flZVOU1X7qkjnhZlsMbk24qQ6Hz7QcuL6sDC0iHHki96Uh2UdvmgZnjIvExy2TeJdMDZNSbdZyAHe/Yd1xsQhHiKzjh7GxQ4yqMPaywPkjMamvqrYpmO7Knad+ZQC5msCuAPWUoxrxVhrGv7a+KLXFhyONdTMrZ7ke23qiO40ZJUyzgYyX5XyL0mV7NiUzEs9mjtbMN0dERqwyAJpigad0B3/zRV7s4PIfXSu6YV/MK7+OrYe/JvfGMn/PHJe2fyUdtnFrKRNpXV0Y2559aWPt/G4BlvjTMtXlVIWCnNyA3YQBDmYIodFz41PvXPSa6rq9lWZawZ4dP115HXV/M/tnFkkrBOdzg6aP4pID+MZnTJ1SuuB6iZlyiox4HT2y3YBtkUKWooacBQUDTpjwaDt5poBHl1/HXltwP887lKKXxNUEyPqpGTyA699UqY/lt9yGdlUKra0fFWS+36iylVWrAyd7Uw0CZM0z7xKTOduznLIjG2Hx8cDPLb+OvK6Bv7n1DYci4CxUuRxrjBc0bb4vD3rN5Zz36ntLb83eVJIB8LiIzCmn6SMPjlX+yNlTjvIGjs+QzHPf60Aj62/jrzG8j9vYMFtm1VoRWCJdmw7z9N0t+c8cxZpPeK4aTRicS25QhrVtUp7U578chk4q04Wx4YoQSjFryUlpcQ1AbxZ/XVMknIU//OGl7Q6z9Zpxi0+3yFhSkjUDpnCIUhLWVX23KQ+L9vKvFKI0ZWFQgkDLvBoylrHNVmaw10zwCPrr5tlodfnf94EWnQ0lFRWy8pW9LbkLsyUVDc2NSTHGDtnD1uMtchjbCeb1mpxFP0YbcClhzdLu6lfO8Bj6q+bdT2sz/+8SZCV7VIxtt0DUn9L7r4cLYWDSXnseEpOGFuty0qbOVlS7NNzs5FOGJUqQpl2Q64/yBpZf90sxbE+//PGdZ02HSipCbmD6NItmQ4Lk5XUrGpDMkhbMm2ZVheNYV+VbUWTcv99+2NyX1VoafSuC+AN6q9bFIMv5X/eagNWXZxEa9JjlMwNWb00akGUkSoepp1/yRuuqHGbUn3UdBSTxBU6SEVklzWRUkPndVvw2PrrpjvxOvzPmwHc0hpmq82npi7GRro8dXp0KXnUQmhZbRL7NEVp1uuZmO45vuzKsHrktS3GLWXODVjw+vXXLYx4Hf7njRPd0i3aoAGX6W29GnaV5YdyDj9TFkakje7GHYzDoObfddHtOSpoi2SmzJHrB3hM/XUDDEbxP2/oosszcRlehWXUvzHv4TpBVktHqwenFo8uLVmy4DKLa5d3RtLrmrM3aMFr1183E4sewf+85VWeg1c5ag276NZrM9IJVNcmLEvDNaV62aq+14IAOGFsBt973Ra8Xv11YzXwNfmft7Jg2oS+XOyoC8/cwzi66Dhmgk38kUmP1CUiYWOX1bpD2zWXt2FCp7uq8703APAa9dfNdscR/M/bZLIyouVxqJfeWvG9Je+JVckHQ9+CI9NWxz+blX/KYYvO5n2tAP/vrlZ7+8/h9y+9qeB/Hnt967e5mevX10rALDWK//FaAT5MXdBXdP0C/BAes792c40H+AiAp1e1oH8HgH94g/Lttx1gp63op1eyoM/Bvw5/G/7xFbqJPcCXnmBiwDPb/YKO4FX4OjyCb289db2/Noqicw4i7N6TVtoz8tNwDH+8x/i6Ae7lmaQVENzJFb3Di/BFeAwz+Is9SjeQySpPqbLFlNmyz47z5a/AF+AYFvDmHqibSXTEzoT4Gc3OALaqAP4KPFUJ6n+1x+rGAM6Zd78bgJ0a8QN4GU614vxwD9e1Amy6CcskNrczLx1JIp6HE5UZD/DBHrFr2oNlgG4Odv226BodoryjGJ9q2T/AR3vQrsOCS0ctXZi3ruLlhpFDJYl4HmYtjQCP9rhdn4suySLKDt6wLcC52h8xPlcjju1fn+yhuw4LZsAGUuo2b4Fx2UwQu77uqRHXGtg92aN3tQCbFexc0uk93vhTXbct6y7MulLycoUljx8ngDMBg1tvJjAazpEmOtxlzclvj1vQf1Tx7QlPDpGpqgtdSKz/d9/hdy1vTfFHSmC9dGDZbLiezz7Ac801HirGZsWjydfZyPvHXL/Y8Mjzg8BxTZiuwKz4Eb8sBE9zznszmjvFwHKPIWUnwhqfVRcd4Ck0K6ate48m1oOfrX3/yOtvAsJ8zsPAM89sjnddmuLuDPjX9Bu/L7x7xpMzFk6nWtyQfPg278Gn4Aekz2ZgOmU9eJ37R14vwE/BL8G3aibCiWMWWDQ0ZtkPMnlcGeAu/Ag+8ZyecU5BPuy2ILD+sQqyZhAKmn7XZd+jIMTN9eBL7x95xVLSX4On8EcNlXDqmBlqS13jG4LpmGbkF/0CnOi3H8ETOIXzmnmtb0a16Tzxj1sUvQCBiXZGDtmB3KAefPH94xcUa/6vwRn80GOFyjEXFpba4A1e8KQfFF+259tx5XS4egYn8fQsLGrqGrHbztr+uByTahWuL1NUGbDpsnrwBfePPwHHIf9X4RnM4Z2ABWdxUBlqQ2PwhuDxoS0vvqB1JzS0P4h2nA/QgTrsJFn+Y3AOjs9JFC07CGWX1oNX3T/yHOzgDjwPn1PM3g9Jk9lZrMEpxnlPmBbjyo2+KFXRU52TJM/2ALcY57RUzjObbjqxVw++4P6RAOf58pcVsw9Daje3htriYrpDOonre3CudSe6bfkTEgHBHuDiyu5MCsc7BHhYDx7ePxLjqigXZsw+ijMHFhuwBmtoTPtOxOrTvYJDnC75dnUbhfwu/ZW9AgYd+peL68HD+0emKquiXHhWjJg/UrkJYzuiaL3E9aI/ytrCvAd4GcYZMCkSQxfUg3v3j8c4e90j5ZTPdvmJJGHnOCI2nHS8081X013pHuBlV1gB2MX1YNmWLHqqGN/TWmG0y6clJWthxNUl48q38Bi8vtMKyzzpFdSDhxZ5WBA5ZLt8Jv3895DduBlgbPYAj8C4B8hO68FDkoh5lydC4FiWvBOVqjYdqjiLv92t8yPDjrDaiHdUD15qkSURSGmXJwOMSxWAXYwr3zaAufJ66l+94vv3AO+vPcD7aw/w/toDvL/2AO+vPcD7aw/wHuD9tQd4f+0B3l97gPfXHuD9tQd4f+0B3l97gG8LwP8G/AL8O/A5OCq0Ys2KIdv/qOIXG/4mvFAMF16gZD+2Xvu/B8as5+8bfllWyg0zaNO5bfXj6vfhhwD86/Aq3NfRS9t9WPnhfnvCIw/CT8GLcFTMnpntdF/z9V+PWc/vWoIH+FL3Znv57PitcdGP4R/C34avw5fgRVUInCwbsn1yyA8C8zm/BH8NXoXnVE6wVPjdeCI38kX/3+Ct9dbz1pTmHFRu+Hm4O9Ch3clr99negxfwj+ER/DR8EV6B5+DuQOnTgUw5rnkY+FbNU3gNXh0o/JYTuWOvyBf9FvzX663HH/HejO8LwAl8Hl5YLTd8q7sqA3wbjuExfAFegQdwfyDoSkWY8swzEf6o4Qyewefg+cHNbqMQruSL/u/WWc+E5g7vnnEXgDmcDeSGb/F4cBcCgT+GGRzDU3hZYburAt9TEtHgbM6JoxJ+6NMzzTcf6c2bycv2+KK/f+l6LBzw5IwfqZJhA3M472pWT/ajKxnjv4AFnMEpnBTPND6s2J7qHbPAqcMK74T2mZ4VGB9uJA465It+/eL1WKhYOD7xHOkr1ajK7d0C4+ke4Hy9qXZwpgLr+Znm/uNFw8xQOSy8H9IzjUrd9+BIfenYaylf9FsXr8fBAadnPIEDna8IBcwlxnuA0/Wv6GAWPd7dDIKjMdSWueAsBj4M7TOd06qBbwDwKr7oleuxMOEcTuEZTHWvDYUO7aHqAe0Bbq+HEFRzOz7WVoTDQkVds7A4sIIxfCQdCefFRoIOF/NFL1mPab/nvOakSL/Q1aFtNpUb/nFOVX6gzyg/1nISyDfUhsokIzaBR9Kxm80s5mK+6P56il1jXic7nhQxsxSm3OwBHl4fFdLqi64nDQZvqE2at7cWAp/IVvrN6/BFL1mPhYrGMBfOi4PyjuSGf6wBBh7p/FZTghCNWGgMzlBbrNJoPJX2mW5mwZfyRffXo7OFi5pZcS4qZUrlViptrXtw+GQoyhDPS+ANjcGBNRiLCQDPZPMHuiZfdFpPSTcQwwKYdRNqpkjm7AFeeT0pJzALgo7g8YYGrMHS0iocy+YTm2vyRUvvpXCIpQ5pe666TJrcygnScUf/p0NDs/iAI/nqDHC8TmQT8x3NF91l76oDdQGwu61Z6E0ABv7uO1dbf/37Zlv+Zw/Pbh8f1s4Avur6657/+YYBvur6657/+YYBvur6657/+YYBvur6657/+aYBvuL6657/+VMA8FXWX/f8zzcN8BXXX/f8zzcNMFdbf93zP38KLPiK6697/uebtuArrr/u+Z9vGmCusP6653/+1FjwVdZf9/zPN7oHX339dc//fNMu+irrr3v+50+Bi+Zq6697/uebA/jz8Pudf9ht/fWv517J/XUzAP8C/BAeX9WCDrUpZ3/dEMBxgPcfbtTVvsYV5Yn32u03B3Ac4P3b8I+vxNBKeeL9dRMAlwO83959qGO78sT769oB7g3w/vGVYFzKE++v6wV4OMD7F7tckFkmT7y/rhHgpQO8b+4Y46XyxPvrugBeNcB7BRiX8sT767oAvmCA9woAHsoT76+rBJjLBnh3txOvkifeX1dswZcO8G6N7sXyxPvr6i340gHe3TnqVfLE++uKAb50gHcXLnrX8sR7gNdPRqwzwLu7Y/FO5Yn3AK9jXCMGeHdgxDuVJ75VAI8ljP7PAb3/RfjcZfePHBB+79dpfpH1CanN30d+mT1h9GqAxxJGM5LQeeQ1+Tb+EQJrElLb38VHQ94TRq900aMIo8cSOo+8Dp8QfsB8zpqE1NO3OI9Zrj1h9EV78PqE0WMJnUdeU6E+Jjyk/hbrEFIfeWbvId8H9oTRFwdZaxJGvziW0Hn0gqYB/wyZ0PwRlxJST+BOw9m77Amj14ii1yGM/txYQudN0qDzGe4EqfA/5GJCagsHcPaEPWH0esekSwmjRxM6b5JEcZ4ww50ilvAOFxBSx4yLW+A/YU8YvfY5+ALC6NGEzhtmyZoFZoarwBLeZxUhtY4rc3bKnjB6TKJjFUHzJoTOozF2YBpsjcyxDgzhQ1YRUse8+J4wenwmaylB82hC5w0zoRXUNXaRBmSMQUqiWSWkLsaVqc/ZE0aPTFUuJWgeTei8SfLZQeMxNaZSIzbII4aE1Nmr13P2hNHjc9E9guYNCZ032YlNwESMLcZiLQHkE4aE1BFg0yAR4z1h9AiAGRA0jyZ03tyIxWMajMPWBIsxYJCnlITU5ShiHYdZ94TR4wCmSxg9jtB5KyPGYzymAYexWEMwAPIsAdYdV6aObmNPGD0aYLoEzaMJnTc0Ygs+YDw0GAtqxBjkuP38bMRWCHn73xNGjz75P73WenCEJnhwyVe3AEe8TtKdJcYhBl97wuhNAObK66lvD/9J9NS75v17wuitAN5fe4D31x7g/bUHeH/tAd5fe4D3AO+vPcD7aw/w/toDvL/2AO+vPcD7aw/w/toDvAd4f/24ABzZ8o+KLsSLS+Pv/TqTb3P4hKlQrTGh+fbIBT0Axqznnb+L/V2mb3HkN5Mb/nEHeK7d4IcDld6lmDW/iH9E+AH1MdOw/Jlu2T1xNmY98sv4wHnD7D3uNHu54WUuOsBTbQuvBsPT/UfzNxGYzwkP8c+Yz3C+r/i6DcyRL/rZ+utRwWH5PmfvcvYEt9jLDS/bg0/B64DWKrQM8AL8FPwS9beQCe6EMKNZYJol37jBMy35otdaz0Bw2H/C2Smc7+WGB0HWDELBmOByA3r5QONo4V+DpzR/hFS4U8wMW1PXNB4TOqYz9urxRV++ntWCw/U59Ty9ebdWbrgfRS9AYKKN63ZokZVygr8GZ/gfIhZXIXPsAlNjPOLBby5c1eOLvmQ9lwkOy5x6QV1j5TYqpS05JtUgUHUp5toHGsVfn4NX4RnMCe+AxTpwmApTYxqMxwfCeJGjpXzRF61nbcHhUBPqWze9svwcHJ+S6NPscKrEjug78Dx8Lj3T8D4YxGIdxmJcwhi34fzZUr7olevZCw5vkOhoClq5zBPZAnygD/Tl9EzDh6kl3VhsHYcDEb+hCtJSvuiV69kLDm+WycrOTArHmB5/VYyP6jOVjwgGawk2zQOaTcc1L+aLXrKeveDwZqlKrw8U9Y1p66uK8dEzdYwBeUQAY7DbyYNezBfdWQ97weEtAKYQg2xJIkuveAT3dYeLGH+ShrWNwZgN0b2YL7qznr3g8JYAo5bQBziPjx7BPZ0d9RCQp4UZbnFdzBddor4XHN4KYMrB2qHFRIzzcLAHQZ5the5ovui94PCWAPefaYnxIdzRwdHCbuR4B+tbiy96Lzi8E4D7z7S0mEPd+eqO3cT53Z0Y8SV80XvB4Z0ADJi/f7X113f+7p7/+UYBvur6657/+YYBvur6657/+aYBvuL6657/+aYBvuL6657/+aYBvuL6657/+aYBvuL6657/+VMA8FXWX/f8z58OgK+y/rrnf75RgLna+uue//lTA/CV1V/3/M837aKvvv6653++UQvmauuve/7nTwfAV1N/3fM/fzr24Cuuv+75nz8FFnxl9dc9//MOr/8/glixwRuUfM4AAAAASUVORK5CYII='; - }, + } - getSearchTexture: function () { + getSearchTexture() { return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII='; } -} ); +} export { SMAAPass }; diff --git a/examples/jsm/postprocessing/SSAARenderPass.js b/examples/jsm/postprocessing/SSAARenderPass.js index 21e5d7fb1c4fd0..fe404b1715a19f 100644 --- a/examples/jsm/postprocessing/SSAARenderPass.js +++ b/examples/jsm/postprocessing/SSAARenderPass.js @@ -7,7 +7,7 @@ import { UniformsUtils, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; /** @@ -20,46 +20,44 @@ import { CopyShader } from '../shaders/CopyShader.js'; * */ -var SSAARenderPass = function ( scene, camera, clearColor, clearAlpha ) { +class SSAARenderPass extends Pass { - Pass.call( this ); + constructor( scene, camera, clearColor, clearAlpha ) { - this.scene = scene; - this.camera = camera; + super(); - this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. - this.unbiased = true; + this.scene = scene; + this.camera = camera; - // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black. - this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000; - this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; - this._oldClearColor = new Color(); + this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. + this.unbiased = true; - if ( CopyShader === undefined ) console.error( 'THREE.SSAARenderPass relies on CopyShader' ); + // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black. + this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000; + this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; + this._oldClearColor = new Color(); - var copyShader = CopyShader; - this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); + if ( CopyShader === undefined ) console.error( 'THREE.SSAARenderPass relies on CopyShader' ); - this.copyMaterial = new ShaderMaterial( { - uniforms: this.copyUniforms, - vertexShader: copyShader.vertexShader, - fragmentShader: copyShader.fragmentShader, - premultipliedAlpha: true, - transparent: true, - blending: AdditiveBlending, - depthTest: false, - depthWrite: false - } ); + const copyShader = CopyShader; + this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); - this.fsQuad = new Pass.FullScreenQuad( this.copyMaterial ); + this.copyMaterial = new ShaderMaterial( { + uniforms: this.copyUniforms, + vertexShader: copyShader.vertexShader, + fragmentShader: copyShader.fragmentShader, + premultipliedAlpha: true, + transparent: true, + blending: AdditiveBlending, + depthTest: false, + depthWrite: false + } ); -}; + this.fsQuad = new FullScreenQuad( this.copyMaterial ); -SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: SSAARenderPass, + } - dispose: function () { + dispose() { if ( this.sampleRenderTarget ) { @@ -68,15 +66,15 @@ SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { if ( this.sampleRenderTarget ) this.sampleRenderTarget.setSize( width, height ); - }, + } - render: function ( renderer, writeBuffer, readBuffer ) { + render( renderer, writeBuffer, readBuffer ) { if ( ! this.sampleRenderTarget ) { @@ -85,24 +83,24 @@ SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - var jitterOffsets = SSAARenderPass.JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ]; + const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ]; - var autoClear = renderer.autoClear; + const autoClear = renderer.autoClear; renderer.autoClear = false; renderer.getClearColor( this._oldClearColor ); - var oldClearAlpha = renderer.getClearAlpha(); + const oldClearAlpha = renderer.getClearAlpha(); - var baseSampleWeight = 1.0 / jitterOffsets.length; - var roundingRange = 1 / 32; + const baseSampleWeight = 1.0 / jitterOffsets.length; + const roundingRange = 1 / 32; this.copyUniforms[ 'tDiffuse' ].value = this.sampleRenderTarget.texture; - var width = readBuffer.width, height = readBuffer.height; + const width = readBuffer.width, height = readBuffer.height; // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. - for ( var i = 0; i < jitterOffsets.length; i ++ ) { + for ( let i = 0; i < jitterOffsets.length; i ++ ) { - var jitterOffset = jitterOffsets[ i ]; + const jitterOffset = jitterOffsets[ i ]; if ( this.camera.setViewOffset ) { @@ -112,7 +110,7 @@ SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - var sampleWeight = baseSampleWeight; + let sampleWeight = baseSampleWeight; if ( this.unbiased ) { @@ -120,7 +118,7 @@ SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { // The following equation varies the sampleWeight per sample so that it is uniformly distributed // across a range of values whose rounding errors cancel each other out. - var uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length ); + const uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length ); sampleWeight += roundingRange * uniformCenteredDistribution; } @@ -151,7 +149,7 @@ SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} // These jitter vectors are specified in integers because it is easier. @@ -159,7 +157,7 @@ SSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), { // before being used, thus these integers need to be scaled by 1/16. // // Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 -SSAARenderPass.JitterVectors = [ +const _JitterVectors = [ [ [ 0, 0 ] ], diff --git a/examples/jsm/postprocessing/SSAOPass.js b/examples/jsm/postprocessing/SSAOPass.js index 419e0f6a310107..b7280193398be3 100644 --- a/examples/jsm/postprocessing/SSAOPass.js +++ b/examples/jsm/postprocessing/SSAOPass.js @@ -21,155 +21,153 @@ import { WebGLRenderTarget, ZeroFactor } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { SimplexNoise } from '../math/SimplexNoise.js'; import { SSAOShader } from '../shaders/SSAOShader.js'; import { SSAOBlurShader } from '../shaders/SSAOShader.js'; import { SSAODepthShader } from '../shaders/SSAOShader.js'; import { CopyShader } from '../shaders/CopyShader.js'; -var SSAOPass = function ( scene, camera, width, height ) { +class SSAOPass extends Pass { - Pass.call( this ); + constructor( scene, camera, width, height ) { - this.width = ( width !== undefined ) ? width : 512; - this.height = ( height !== undefined ) ? height : 512; + super(); - this.clear = true; + this.width = ( width !== undefined ) ? width : 512; + this.height = ( height !== undefined ) ? height : 512; - this.camera = camera; - this.scene = scene; + this.clear = true; - this.kernelRadius = 8; - this.kernelSize = 32; - this.kernel = []; - this.noiseTexture = null; - this.output = 0; + this.camera = camera; + this.scene = scene; - this.minDistance = 0.005; - this.maxDistance = 0.1; + this.kernelRadius = 8; + this.kernelSize = 32; + this.kernel = []; + this.noiseTexture = null; + this.output = 0; - this._visibilityCache = new Map(); + this.minDistance = 0.005; + this.maxDistance = 0.1; - // + this._visibilityCache = new Map(); - this.generateSampleKernel(); - this.generateRandomKernelRotations(); + // - // beauty render target + this.generateSampleKernel(); + this.generateRandomKernelRotations(); - var depthTexture = new DepthTexture(); - depthTexture.type = UnsignedShortType; + // beauty render target - this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat - } ); + const depthTexture = new DepthTexture(); + depthTexture.type = UnsignedShortType; - // normal render target with depth buffer + this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBAFormat + } ); - this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat, - depthTexture: depthTexture - } ); + // normal render target with depth buffer - // ssao render target + this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + depthTexture: depthTexture + } ); - this.ssaoRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat - } ); + // ssao render target - this.blurRenderTarget = this.ssaoRenderTarget.clone(); + this.ssaoRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: LinearFilter, + magFilter: LinearFilter, + format: RGBAFormat + } ); - // ssao material + this.blurRenderTarget = this.ssaoRenderTarget.clone(); - if ( SSAOShader === undefined ) { + // ssao material - console.error( 'THREE.SSAOPass: The pass relies on SSAOShader.' ); + if ( SSAOShader === undefined ) { - } + console.error( 'THREE.SSAOPass: The pass relies on SSAOShader.' ); - this.ssaoMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSAOShader.defines ), - uniforms: UniformsUtils.clone( SSAOShader.uniforms ), - vertexShader: SSAOShader.vertexShader, - fragmentShader: SSAOShader.fragmentShader, - blending: NoBlending - } ); - - this.ssaoMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; - this.ssaoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture; - this.ssaoMaterial.uniforms[ 'tDepth' ].value = this.normalRenderTarget.depthTexture; - this.ssaoMaterial.uniforms[ 'tNoise' ].value = this.noiseTexture; - this.ssaoMaterial.uniforms[ 'kernel' ].value = this.kernel; - this.ssaoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; - this.ssaoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; - this.ssaoMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); - this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); - this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); - - // normal material - - this.normalMaterial = new MeshNormalMaterial(); - this.normalMaterial.blending = NoBlending; - - // blur material - - this.blurMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSAOBlurShader.defines ), - uniforms: UniformsUtils.clone( SSAOBlurShader.uniforms ), - vertexShader: SSAOBlurShader.vertexShader, - fragmentShader: SSAOBlurShader.fragmentShader - } ); - this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture; - this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); - - // material for rendering the depth - - this.depthRenderMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSAODepthShader.defines ), - uniforms: UniformsUtils.clone( SSAODepthShader.uniforms ), - vertexShader: SSAODepthShader.vertexShader, - fragmentShader: SSAODepthShader.fragmentShader, - blending: NoBlending - } ); - this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.normalRenderTarget.depthTexture; - this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; - this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; - - // material for rendering the content of a render target - - this.copyMaterial = new ShaderMaterial( { - uniforms: UniformsUtils.clone( CopyShader.uniforms ), - vertexShader: CopyShader.vertexShader, - fragmentShader: CopyShader.fragmentShader, - transparent: true, - depthTest: false, - depthWrite: false, - blendSrc: DstColorFactor, - blendDst: ZeroFactor, - blendEquation: AddEquation, - blendSrcAlpha: DstAlphaFactor, - blendDstAlpha: ZeroFactor, - blendEquationAlpha: AddEquation - } ); - - this.fsQuad = new Pass.FullScreenQuad( null ); - - this.originalClearColor = new Color(); + } -}; + this.ssaoMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSAOShader.defines ), + uniforms: UniformsUtils.clone( SSAOShader.uniforms ), + vertexShader: SSAOShader.vertexShader, + fragmentShader: SSAOShader.fragmentShader, + blending: NoBlending + } ); -SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.ssaoMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; + this.ssaoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture; + this.ssaoMaterial.uniforms[ 'tDepth' ].value = this.normalRenderTarget.depthTexture; + this.ssaoMaterial.uniforms[ 'tNoise' ].value = this.noiseTexture; + this.ssaoMaterial.uniforms[ 'kernel' ].value = this.kernel; + this.ssaoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; + this.ssaoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; + this.ssaoMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); + this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); + this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); + + // normal material - constructor: SSAOPass, + this.normalMaterial = new MeshNormalMaterial(); + this.normalMaterial.blending = NoBlending; - dispose: function () { + // blur material + + this.blurMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSAOBlurShader.defines ), + uniforms: UniformsUtils.clone( SSAOBlurShader.uniforms ), + vertexShader: SSAOBlurShader.vertexShader, + fragmentShader: SSAOBlurShader.fragmentShader + } ); + this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture; + this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); + + // material for rendering the depth + + this.depthRenderMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSAODepthShader.defines ), + uniforms: UniformsUtils.clone( SSAODepthShader.uniforms ), + vertexShader: SSAODepthShader.vertexShader, + fragmentShader: SSAODepthShader.fragmentShader, + blending: NoBlending + } ); + this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.normalRenderTarget.depthTexture; + this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; + this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; + + // material for rendering the content of a render target + + this.copyMaterial = new ShaderMaterial( { + uniforms: UniformsUtils.clone( CopyShader.uniforms ), + vertexShader: CopyShader.vertexShader, + fragmentShader: CopyShader.fragmentShader, + transparent: true, + depthTest: false, + depthWrite: false, + blendSrc: DstColorFactor, + blendDst: ZeroFactor, + blendEquation: AddEquation, + blendSrcAlpha: DstAlphaFactor, + blendDstAlpha: ZeroFactor, + blendEquationAlpha: AddEquation + } ); + + this.fsQuad = new FullScreenQuad( null ); + + this.originalClearColor = new Color(); + + } + + dispose() { // dispose render targets @@ -189,9 +187,9 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.fsQuad.dispose(); - }, + } - render: function ( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { + render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { // render beauty @@ -275,14 +273,14 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { + renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { // save original state renderer.getClearColor( this.originalClearColor ); - var originalClearAlpha = renderer.getClearAlpha(); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha(); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); @@ -304,13 +302,13 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { + renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { renderer.getClearColor( this.originalClearColor ); - var originalClearAlpha = renderer.getClearAlpha(); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha(); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); renderer.autoClear = false; @@ -336,9 +334,9 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.width = width; this.height = height; @@ -354,23 +352,23 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height ); - }, + } - generateSampleKernel: function () { + generateSampleKernel() { - var kernelSize = this.kernelSize; - var kernel = this.kernel; + const kernelSize = this.kernelSize; + const kernel = this.kernel; - for ( var i = 0; i < kernelSize; i ++ ) { + for ( let i = 0; i < kernelSize; i ++ ) { - var sample = new Vector3(); + const sample = new Vector3(); sample.x = ( Math.random() * 2 ) - 1; sample.y = ( Math.random() * 2 ) - 1; sample.z = Math.random(); sample.normalize(); - var scale = i / kernelSize; + let scale = i / kernelSize; scale = MathUtils.lerp( 0.1, 1, scale * scale ); sample.multiplyScalar( scale ); @@ -378,11 +376,11 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - generateRandomKernelRotations: function () { + generateRandomKernelRotations() { - var width = 4, height = 4; + const width = 4, height = 4; if ( SimplexNoise === undefined ) { @@ -390,20 +388,20 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - var simplex = new SimplexNoise(); + const simplex = new SimplexNoise(); - var size = width * height; - var data = new Float32Array( size * 4 ); + const size = width * height; + const data = new Float32Array( size * 4 ); - for ( var i = 0; i < size; i ++ ) { + for ( let i = 0; i < size; i ++ ) { - var stride = i * 4; + const stride = i * 4; - var x = ( Math.random() * 2 ) - 1; - var y = ( Math.random() * 2 ) - 1; - var z = 0; + const x = ( Math.random() * 2 ) - 1; + const y = ( Math.random() * 2 ) - 1; + const z = 0; - var noise = simplex.noise3d( x, y, z ); + const noise = simplex.noise3d( x, y, z ); data[ stride ] = noise; data[ stride + 1 ] = noise; @@ -416,12 +414,12 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.noiseTexture.wrapS = RepeatWrapping; this.noiseTexture.wrapT = RepeatWrapping; - }, + } - overrideVisibility: function () { + overrideVisibility() { - var scene = this.scene; - var cache = this._visibilityCache; + const scene = this.scene; + const cache = this._visibilityCache; scene.traverse( function ( object ) { @@ -431,16 +429,16 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } ); - }, + } - restoreVisibility: function () { + restoreVisibility() { - var scene = this.scene; - var cache = this._visibilityCache; + const scene = this.scene; + const cache = this._visibilityCache; scene.traverse( function ( object ) { - var visible = cache.get( object ); + const visible = cache.get( object ); object.visible = visible; } ); @@ -449,7 +447,7 @@ SSAOPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} SSAOPass.OUTPUT = { 'Default': 0, diff --git a/examples/jsm/postprocessing/SSRPass.js b/examples/jsm/postprocessing/SSRPass.js index 6483d4082e4b99..8adfc1306187c2 100644 --- a/examples/jsm/postprocessing/SSRPass.js +++ b/examples/jsm/postprocessing/SSRPass.js @@ -5,7 +5,6 @@ import { DepthTexture, SrcAlphaFactor, OneMinusSrcAlphaFactor, - LinearFilter, MeshNormalMaterial, MeshBasicMaterial, NearestFilter, @@ -17,320 +16,317 @@ import { WebGLRenderTarget, HalfFloatType, } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { SSRShader } from '../shaders/SSRShader.js'; import { SSRBlurShader } from '../shaders/SSRShader.js'; import { SSRDepthShader } from '../shaders/SSRShader.js'; import { CopyShader } from '../shaders/CopyShader.js'; -var SSRPass = function ( { renderer, scene, camera, width, height, selects, encoding, bouncing = false, morphTargets = false, groundReflector } ) { +class SSRPass extends Pass { - Pass.call( this ); + constructor( { renderer, scene, camera, width, height, selects, encoding, bouncing = false, morphTargets = false, groundReflector } ) { - this.width = ( width !== undefined ) ? width : 512; - this.height = ( height !== undefined ) ? height : 512; + super(); - this.clear = true; + this.width = ( width !== undefined ) ? width : 512; + this.height = ( height !== undefined ) ? height : 512; - this.renderer = renderer; - this.scene = scene; - this.camera = camera; - this.groundReflector = groundReflector; + this.clear = true; - this.opacity = SSRShader.uniforms.opacity.value; - this.output = 0; + this.renderer = renderer; + this.scene = scene; + this.camera = camera; + this.groundReflector = groundReflector; - this.maxDistance = SSRShader.uniforms.maxDistance.value; - this.surfDist = SSRShader.uniforms.surfDist.value; + this.opacity = SSRShader.uniforms.opacity.value; + this.output = 0; - this.encoding = encoding; + this.maxDistance = SSRShader.uniforms.maxDistance.value; + this.thickness = SSRShader.uniforms.thickness.value; - this.tempColor = new Color(); + this.encoding = encoding; - this._selects = selects; - this.selective = Array.isArray( this._selects ); - Object.defineProperty( this, 'selects', { - get() { + this.tempColor = new Color(); - return this._selects; + this._selects = selects; + this.selective = Array.isArray( this._selects ); + Object.defineProperty( this, 'selects', { + get() { - }, - set( val ) { + return this._selects; - if ( this._selects === val ) return; - this._selects = val; - if ( Array.isArray( val ) ) { + }, + set( val ) { - this.selective = true; - this.ssrMaterial.defines.SELECTIVE = true; - this.ssrMaterial.needsUpdate = true; + if ( this._selects === val ) return; + this._selects = val; + if ( Array.isArray( val ) ) { - } else { + this.selective = true; + this.ssrMaterial.defines.SELECTIVE = true; + this.ssrMaterial.needsUpdate = true; - this.selective = false; - this.ssrMaterial.defines.SELECTIVE = false; - this.ssrMaterial.needsUpdate = true; + } else { + + this.selective = false; + this.ssrMaterial.defines.SELECTIVE = false; + this.ssrMaterial.needsUpdate = true; + + } } + } ); - } - } ); + this._bouncing = bouncing; + Object.defineProperty( this, 'bouncing', { + get() { - this._bouncing = bouncing; - Object.defineProperty( this, 'bouncing', { - get() { + return this._bouncing; - return this._bouncing; + }, + set( val ) { - }, - set( val ) { + if ( this._bouncing === val ) return; + this._bouncing = val; + if ( val ) { - if ( this._bouncing === val ) return; - this._bouncing = val; - if ( val ) { + this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture; - this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture; + } else { - } else { + this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; - this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; + } } + } ); - } - } ); + this.blur = true; - this.blur = true; + this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION; + Object.defineProperty( this, 'distanceAttenuation', { + get() { - this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION; - Object.defineProperty( this, 'distanceAttenuation', { - get() { + return this._distanceAttenuation; - return this._distanceAttenuation; + }, + set( val ) { - }, - set( val ) { + if ( this._distanceAttenuation === val ) return; + this._distanceAttenuation = val; + this.ssrMaterial.defines.DISTANCE_ATTENUATION = val; + this.ssrMaterial.needsUpdate = true; - if ( this._distanceAttenuation === val ) return; - this._distanceAttenuation = val; - this.ssrMaterial.defines.DISTANCE_ATTENUATION = val; - this.ssrMaterial.needsUpdate = true; + } + } ); - } - } ); + this._fresnel = SSRShader.defines.FRESNEL; + Object.defineProperty( this, 'fresnel', { + get() { - this._fresnel = SSRShader.defines.FRESNEL; - Object.defineProperty( this, 'fresnel', { - get() { + return this._fresnel; - return this._fresnel; + }, + set( val ) { - }, - set( val ) { + if ( this._fresnel === val ) return; + this._fresnel = val; + this.ssrMaterial.defines.FRESNEL = val; + this.ssrMaterial.needsUpdate = true; - if ( this._fresnel === val ) return; - this._fresnel = val; - this.ssrMaterial.defines.FRESNEL = val; - this.ssrMaterial.needsUpdate = true; + } + } ); - } - } ); + this._infiniteThick = SSRShader.defines.INFINITE_THICK; + Object.defineProperty( this, 'infiniteThick', { + get() { - this._infiniteThick = SSRShader.defines.INFINITE_THICK; - Object.defineProperty( this, 'infiniteThick', { - get() { + return this._infiniteThick; - return this._infiniteThick; + }, + set( val ) { - }, - set( val ) { + if ( this._infiniteThick === val ) return; + this._infiniteThick = val; + this.ssrMaterial.defines.INFINITE_THICK = val; + this.ssrMaterial.needsUpdate = true; - if ( this._infiniteThick === val ) return; - this._infiniteThick = val; - this.ssrMaterial.defines.INFINITE_THICK = val; - this.ssrMaterial.needsUpdate = true; + } + } ); - } - } ); - this.thickTolerance = SSRShader.uniforms.thickTolerance.value; + // beauty render target with depth buffer - // beauty render target with depth buffer + const depthTexture = new DepthTexture(); + depthTexture.type = UnsignedShortType; + depthTexture.minFilter = NearestFilter; + depthTexture.magFilter = NearestFilter; - var depthTexture = new DepthTexture(); - depthTexture.type = UnsignedShortType; - depthTexture.minFilter = NearestFilter; - depthTexture.magFilter = NearestFilter; + this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + depthTexture: depthTexture, + depthBuffer: true + } ); - this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat, - depthTexture: depthTexture, - depthBuffer: true - } ); + //for bouncing + this.prevRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + } ); - //for bouncing - this.prevRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat, - } ); + // normal render target - // normal render target + this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + type: HalfFloatType, + } ); - this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat, - type: HalfFloatType, - } ); + // metalness render target - // metalness render target + this.metalnessRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat + } ); - this.metalnessRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat - } ); + // ssr render target - // ssr render target + this.ssrRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat + } ); - this.ssrRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: LinearFilter, - magFilter: LinearFilter, - format: RGBAFormat - } ); + this.blurRenderTarget = this.ssrRenderTarget.clone(); + this.blurRenderTarget2 = this.ssrRenderTarget.clone(); + // this.blurRenderTarget3 = this.ssrRenderTarget.clone(); - this.blurRenderTarget = this.ssrRenderTarget.clone(); - this.blurRenderTarget2 = this.ssrRenderTarget.clone(); - // this.blurRenderTarget3 = this.ssrRenderTarget.clone(); + // ssr material - // ssr material + if ( SSRShader === undefined ) { - if ( SSRShader === undefined ) { + console.error( 'THREE.SSRPass: The pass relies on SSRShader.' ); - console.error( 'THREE.SSRPass: The pass relies on SSRShader.' ); + } - } + this.ssrMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSRShader.defines, { + MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height ) + } ), + uniforms: UniformsUtils.clone( SSRShader.uniforms ), + vertexShader: SSRShader.vertexShader, + fragmentShader: SSRShader.fragmentShader, + blending: NoBlending + } ); + + this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; + this.ssrMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture; + this.ssrMaterial.defines.SELECTIVE = this.selective; + this.ssrMaterial.needsUpdate = true; + this.ssrMaterial.uniforms[ 'tMetalness' ].value = this.metalnessRenderTarget.texture; + this.ssrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; + this.ssrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; + this.ssrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; + this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness; + this.ssrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); + this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); + this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); - this.ssrMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSRShader.defines, { - MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height ) - } ), - uniforms: UniformsUtils.clone( SSRShader.uniforms ), - vertexShader: SSRShader.vertexShader, - fragmentShader: SSRShader.fragmentShader, - blending: NoBlending - } ); - - this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; - this.ssrMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture; - this.ssrMaterial.defines.SELECTIVE = this.selective; - this.ssrMaterial.needsUpdate = true; - this.ssrMaterial.uniforms[ 'tMetalness' ].value = this.metalnessRenderTarget.texture; - this.ssrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; - this.ssrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; - this.ssrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; - this.ssrMaterial.uniforms[ 'surfDist' ].value = this.surfDist; - this.ssrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); - this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); - this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); - - // normal material - - this.normalMaterial = new MeshNormalMaterial( { morphTargets } ); - this.normalMaterial.blending = NoBlending; - - // metalnessOn material - - this.metalnessOnMaterial = new MeshBasicMaterial( { - color: 'white' - } ); - - // metalnessOff material - - this.metalnessOffMaterial = new MeshBasicMaterial( { - color: 'black' - } ); - - // blur material - - this.blurMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSRBlurShader.defines ), - uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ), - vertexShader: SSRBlurShader.vertexShader, - fragmentShader: SSRBlurShader.fragmentShader - } ); - this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture; - this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); - - // blur material 2 - - this.blurMaterial2 = new ShaderMaterial( { - defines: Object.assign( {}, SSRBlurShader.defines ), - uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ), - vertexShader: SSRBlurShader.vertexShader, - fragmentShader: SSRBlurShader.fragmentShader - } ); - this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture; - this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height ); - - // // blur material 3 - - // this.blurMaterial3 = new ShaderMaterial({ - // defines: Object.assign({}, SSRBlurShader.defines), - // uniforms: UniformsUtils.clone(SSRBlurShader.uniforms), - // vertexShader: SSRBlurShader.vertexShader, - // fragmentShader: SSRBlurShader.fragmentShader - // }); - // this.blurMaterial3.uniforms['tDiffuse'].value = this.blurRenderTarget2.texture; - // this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height); - - // material for rendering the depth - - this.depthRenderMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSRDepthShader.defines ), - uniforms: UniformsUtils.clone( SSRDepthShader.uniforms ), - vertexShader: SSRDepthShader.vertexShader, - fragmentShader: SSRDepthShader.fragmentShader, - blending: NoBlending - } ); - this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; - this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; - this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; - - // material for rendering the content of a render target - - this.copyMaterial = new ShaderMaterial( { - uniforms: UniformsUtils.clone( CopyShader.uniforms ), - vertexShader: CopyShader.vertexShader, - fragmentShader: CopyShader.fragmentShader, - transparent: true, - depthTest: false, - depthWrite: false, - blendSrc: SrcAlphaFactor, - blendDst: OneMinusSrcAlphaFactor, - blendEquation: AddEquation, - blendSrcAlpha: SrcAlphaFactor, - blendDstAlpha: OneMinusSrcAlphaFactor, - blendEquationAlpha: AddEquation, - // premultipliedAlpha:true, - } ); - - this.fsQuad = new Pass.FullScreenQuad( null ); - - this.originalClearColor = new Color(); + // normal material -}; + this.normalMaterial = new MeshNormalMaterial( { morphTargets } ); + this.normalMaterial.blending = NoBlending; + + // metalnessOn material + + this.metalnessOnMaterial = new MeshBasicMaterial( { + color: 'white' + } ); + + // metalnessOff material + + this.metalnessOffMaterial = new MeshBasicMaterial( { + color: 'black' + } ); + + // blur material -SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.blurMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSRBlurShader.defines ), + uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ), + vertexShader: SSRBlurShader.vertexShader, + fragmentShader: SSRBlurShader.fragmentShader + } ); + this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture; + this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); + + // blur material 2 + + this.blurMaterial2 = new ShaderMaterial( { + defines: Object.assign( {}, SSRBlurShader.defines ), + uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ), + vertexShader: SSRBlurShader.vertexShader, + fragmentShader: SSRBlurShader.fragmentShader + } ); + this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture; + this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height ); + + // // blur material 3 + + // this.blurMaterial3 = new ShaderMaterial({ + // defines: Object.assign({}, SSRBlurShader.defines), + // uniforms: UniformsUtils.clone(SSRBlurShader.uniforms), + // vertexShader: SSRBlurShader.vertexShader, + // fragmentShader: SSRBlurShader.fragmentShader + // }); + // this.blurMaterial3.uniforms['tDiffuse'].value = this.blurRenderTarget2.texture; + // this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height); + + // material for rendering the depth + + this.depthRenderMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSRDepthShader.defines ), + uniforms: UniformsUtils.clone( SSRDepthShader.uniforms ), + vertexShader: SSRDepthShader.vertexShader, + fragmentShader: SSRDepthShader.fragmentShader, + blending: NoBlending + } ); + this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; + this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; + this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; + + // material for rendering the content of a render target + + this.copyMaterial = new ShaderMaterial( { + uniforms: UniformsUtils.clone( CopyShader.uniforms ), + vertexShader: CopyShader.vertexShader, + fragmentShader: CopyShader.fragmentShader, + transparent: true, + depthTest: false, + depthWrite: false, + blendSrc: SrcAlphaFactor, + blendDst: OneMinusSrcAlphaFactor, + blendEquation: AddEquation, + blendSrcAlpha: SrcAlphaFactor, + blendDstAlpha: OneMinusSrcAlphaFactor, + blendEquationAlpha: AddEquation, + // premultipliedAlpha:true, + } ); - constructor: SSRPass, + this.fsQuad = new FullScreenQuad( null ); - dispose: function () { + this.originalClearColor = new Color(); + + } + + dispose() { // dispose render targets @@ -357,9 +353,9 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.fsQuad.dispose(); - }, + } - render: function ( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { + render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { // render beauty and depth @@ -393,8 +389,7 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.ssrMaterial.uniforms[ 'opacity' ].value = this.opacity; this.ssrMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance; - this.ssrMaterial.uniforms[ 'surfDist' ].value = this.surfDist; - this.ssrMaterial.uniforms[ 'thickTolerance' ].value = this.thickTolerance; + this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness; this.renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget ); @@ -508,14 +503,14 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { + renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { // save original state this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) ); - var originalClearAlpha = renderer.getClearAlpha( this.tempColor ); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha( this.tempColor ); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); @@ -537,13 +532,13 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { + renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) ); - var originalClearAlpha = renderer.getClearAlpha( this.tempColor ); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha( this.tempColor ); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); renderer.autoClear = false; @@ -569,13 +564,13 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - renderMetalness: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { + renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) ); - var originalClearAlpha = renderer.getClearAlpha( this.tempColor ); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha( this.tempColor ); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); renderer.autoClear = false; @@ -618,9 +613,9 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.width = width; this.height = height; @@ -643,9 +638,9 @@ SSRPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height ); this.blurMaterial2.uniforms[ 'resolution' ].value.set( width, height ); - }, + } -} ); +} SSRPass.OUTPUT = { 'Default': 0, diff --git a/examples/jsm/postprocessing/SSRrPass.js b/examples/jsm/postprocessing/SSRrPass.js index ae036e4814cf2c..51273fec511fe5 100644 --- a/examples/jsm/postprocessing/SSRrPass.js +++ b/examples/jsm/postprocessing/SSRrPass.js @@ -17,238 +17,236 @@ import { HalfFloatType, MeshStandardMaterial } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { SSRrShader } from '../shaders/SSRrShader.js'; import { SSRrDepthShader } from '../shaders/SSRrShader.js'; import { CopyShader } from '../shaders/CopyShader.js'; -var SSRrPass = function ( { renderer, scene, camera, width, height, selects, encoding, morphTargets = false } ) { +class SSRrPass extends Pass { - Pass.call( this ); + constructor( { renderer, scene, camera, width, height, selects, encoding, morphTargets = false } ) { - this.width = ( width !== undefined ) ? width : 512; - this.height = ( height !== undefined ) ? height : 512; + super(); - this.clear = true; + this.width = ( width !== undefined ) ? width : 512; + this.height = ( height !== undefined ) ? height : 512; - this.renderer = renderer; - this.scene = scene; - this.camera = camera; + this.clear = true; - this.output = 0; - // this.output = 1; + this.renderer = renderer; + this.scene = scene; + this.camera = camera; - this.ior = SSRrShader.uniforms.ior.value; - this.maxDistance = SSRrShader.uniforms.maxDistance.value; - this.surfDist = SSRrShader.uniforms.surfDist.value; + this.output = 0; + // this.output = 1; - this.encoding = encoding; + this.ior = SSRrShader.uniforms.ior.value; + this.maxDistance = SSRrShader.uniforms.maxDistance.value; + this.surfDist = SSRrShader.uniforms.surfDist.value; - this.tempColor = new Color(); + this.encoding = encoding; - this.selects = selects; + this.tempColor = new Color(); - this._specular = SSRrShader.defines.SPECULAR; - Object.defineProperty( this, 'specular', { - get() { + this.selects = selects; - return this._specular; + this._specular = SSRrShader.defines.SPECULAR; + Object.defineProperty( this, 'specular', { + get() { - }, - set( val ) { + return this._specular; - if ( this._specular === val ) return; - this._specular = val; - this.ssrrMaterial.defines.SPECULAR = val; - this.ssrrMaterial.needsUpdate = true; + }, + set( val ) { - } - } ); + if ( this._specular === val ) return; + this._specular = val; + this.ssrrMaterial.defines.SPECULAR = val; + this.ssrrMaterial.needsUpdate = true; - this._fillHole = SSRrShader.defines.FILL_HOLE; - Object.defineProperty( this, 'fillHole', { - get() { + } + } ); - return this._fillHole; + this._fillHole = SSRrShader.defines.FILL_HOLE; + Object.defineProperty( this, 'fillHole', { + get() { - }, - set( val ) { + return this._fillHole; - if ( this._fillHole === val ) return; - this._fillHole = val; - this.ssrrMaterial.defines.FILL_HOLE = val; - this.ssrrMaterial.needsUpdate = true; + }, + set( val ) { - } - } ); + if ( this._fillHole === val ) return; + this._fillHole = val; + this.ssrrMaterial.defines.FILL_HOLE = val; + this.ssrrMaterial.needsUpdate = true; - this._infiniteThick = SSRrShader.defines.INFINITE_THICK; - Object.defineProperty( this, 'infiniteThick', { - get() { + } + } ); - return this._infiniteThick; + this._infiniteThick = SSRrShader.defines.INFINITE_THICK; + Object.defineProperty( this, 'infiniteThick', { + get() { - }, - set( val ) { + return this._infiniteThick; - if ( this._infiniteThick === val ) return; - this._infiniteThick = val; - this.ssrrMaterial.defines.INFINITE_THICK = val; - this.ssrrMaterial.needsUpdate = true; + }, + set( val ) { - } - } ); + if ( this._infiniteThick === val ) return; + this._infiniteThick = val; + this.ssrrMaterial.defines.INFINITE_THICK = val; + this.ssrrMaterial.needsUpdate = true; - // beauty render target with depth buffer + } + } ); - var depthTexture = new DepthTexture(); - depthTexture.type = UnsignedShortType; - depthTexture.minFilter = NearestFilter; - depthTexture.magFilter = NearestFilter; + // beauty render target with depth buffer - this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat, - depthTexture: depthTexture, - depthBuffer: true - } ); + const depthTexture = new DepthTexture(); + depthTexture.type = UnsignedShortType; + depthTexture.minFilter = NearestFilter; + depthTexture.magFilter = NearestFilter; - this.specularRenderTarget = new WebGLRenderTarget( this.width, this.height, { // TODO: Can merge with refractiveRenderTarget? - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat, - } ); + this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + depthTexture: depthTexture, + depthBuffer: true + } ); - // normalSelects render target + this.specularRenderTarget = new WebGLRenderTarget( this.width, this.height, { // TODO: Can merge with refractiveRenderTarget? + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + } ); - var depthTextureSelects = new DepthTexture(); - depthTextureSelects.type = UnsignedShortType; - depthTextureSelects.minFilter = NearestFilter; - depthTextureSelects.magFilter = NearestFilter; + // normalSelects render target - this.normalSelectsRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat, - type: HalfFloatType, - depthTexture: depthTextureSelects, - depthBuffer: true - } ); + const depthTextureSelects = new DepthTexture(); + depthTextureSelects.type = UnsignedShortType; + depthTextureSelects.minFilter = NearestFilter; + depthTextureSelects.magFilter = NearestFilter; - // refractive render target + this.normalSelectsRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat, + type: HalfFloatType, + depthTexture: depthTextureSelects, + depthBuffer: true + } ); - this.refractiveRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat - } ); + // refractive render target - // ssrr render target + this.refractiveRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat + } ); - this.ssrrRenderTarget = new WebGLRenderTarget( this.width, this.height, { - minFilter: NearestFilter, - magFilter: NearestFilter, - format: RGBAFormat - } ); + // ssrr render target - // ssrr material + this.ssrrRenderTarget = new WebGLRenderTarget( this.width, this.height, { + minFilter: NearestFilter, + magFilter: NearestFilter, + format: RGBAFormat + } ); - if ( SSRrShader === undefined ) { + // ssrr material - console.error( 'THREE.SSRrPass: The pass relies on SSRrShader.' ); + if ( SSRrShader === undefined ) { - } + console.error( 'THREE.SSRrPass: The pass relies on SSRrShader.' ); - this.ssrrMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSRrShader.defines, { - MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height ) - } ), - uniforms: UniformsUtils.clone( SSRrShader.uniforms ), - vertexShader: SSRrShader.vertexShader, - fragmentShader: SSRrShader.fragmentShader, - blending: NoBlending - } ); - - this.ssrrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; - this.ssrrMaterial.uniforms[ 'tSpecular' ].value = this.specularRenderTarget.texture; - this.ssrrMaterial.uniforms[ 'tNormalSelects' ].value = this.normalSelectsRenderTarget.texture; - this.ssrrMaterial.needsUpdate = true; - this.ssrrMaterial.uniforms[ 'tRefractive' ].value = this.refractiveRenderTarget.texture; - this.ssrrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; - this.ssrrMaterial.uniforms[ 'tDepthSelects' ].value = this.normalSelectsRenderTarget.depthTexture; - this.ssrrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; - this.ssrrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; - this.ssrrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); - this.ssrrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); - this.ssrrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); - - // normal material - - this.normalMaterial = new MeshNormalMaterial( { morphTargets } ); - this.normalMaterial.blending = NoBlending; - - // refractiveOn material - - this.refractiveOnMaterial = new MeshBasicMaterial( { - color: 'white' - } ); - - // refractiveOff material - - this.refractiveOffMaterial = new MeshBasicMaterial( { - color: 'black' - } ); - - // specular material - this.specularMaterial = new MeshStandardMaterial( { - color: 'black', - metalness: 0, - roughness: .2, - } ); - - // material for rendering the depth - - this.depthRenderMaterial = new ShaderMaterial( { - defines: Object.assign( {}, SSRrDepthShader.defines ), - uniforms: UniformsUtils.clone( SSRrDepthShader.uniforms ), - vertexShader: SSRrDepthShader.vertexShader, - fragmentShader: SSRrDepthShader.fragmentShader, - blending: NoBlending - } ); - this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; - this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; - this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; - - // material for rendering the content of a render target - - this.copyMaterial = new ShaderMaterial( { - uniforms: UniformsUtils.clone( CopyShader.uniforms ), - vertexShader: CopyShader.vertexShader, - fragmentShader: CopyShader.fragmentShader, - transparent: true, - depthTest: false, - depthWrite: false, - blendSrc: SrcAlphaFactor, - blendDst: OneMinusSrcAlphaFactor, - blendEquation: AddEquation, - blendSrcAlpha: SrcAlphaFactor, - blendDstAlpha: OneMinusSrcAlphaFactor, - blendEquationAlpha: AddEquation, - // premultipliedAlpha:true, - } ); - - this.fsQuad = new Pass.FullScreenQuad( null ); - - this.originalClearColor = new Color(); + } -}; + this.ssrrMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSRrShader.defines, { + MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height ) + } ), + uniforms: UniformsUtils.clone( SSRrShader.uniforms ), + vertexShader: SSRrShader.vertexShader, + fragmentShader: SSRrShader.fragmentShader, + blending: NoBlending + } ); + + this.ssrrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture; + this.ssrrMaterial.uniforms[ 'tSpecular' ].value = this.specularRenderTarget.texture; + this.ssrrMaterial.uniforms[ 'tNormalSelects' ].value = this.normalSelectsRenderTarget.texture; + this.ssrrMaterial.needsUpdate = true; + this.ssrrMaterial.uniforms[ 'tRefractive' ].value = this.refractiveRenderTarget.texture; + this.ssrrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; + this.ssrrMaterial.uniforms[ 'tDepthSelects' ].value = this.normalSelectsRenderTarget.depthTexture; + this.ssrrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; + this.ssrrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; + this.ssrrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height ); + this.ssrrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); + this.ssrrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); -SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { + // normal material - constructor: SSRrPass, + this.normalMaterial = new MeshNormalMaterial( { morphTargets } ); + this.normalMaterial.blending = NoBlending; - dispose: function () { + // refractiveOn material + + this.refractiveOnMaterial = new MeshBasicMaterial( { + color: 'white' + } ); + + // refractiveOff material + + this.refractiveOffMaterial = new MeshBasicMaterial( { + color: 'black' + } ); + + // specular material + this.specularMaterial = new MeshStandardMaterial( { + color: 'black', + metalness: 0, + roughness: .2, + } ); + + // material for rendering the depth + + this.depthRenderMaterial = new ShaderMaterial( { + defines: Object.assign( {}, SSRrDepthShader.defines ), + uniforms: UniformsUtils.clone( SSRrDepthShader.uniforms ), + vertexShader: SSRrDepthShader.vertexShader, + fragmentShader: SSRrDepthShader.fragmentShader, + blending: NoBlending + } ); + this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture; + this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near; + this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far; + + // material for rendering the content of a render target + + this.copyMaterial = new ShaderMaterial( { + uniforms: UniformsUtils.clone( CopyShader.uniforms ), + vertexShader: CopyShader.vertexShader, + fragmentShader: CopyShader.fragmentShader, + transparent: true, + depthTest: false, + depthWrite: false, + blendSrc: SrcAlphaFactor, + blendDst: OneMinusSrcAlphaFactor, + blendEquation: AddEquation, + blendSrcAlpha: SrcAlphaFactor, + blendDstAlpha: OneMinusSrcAlphaFactor, + blendEquationAlpha: AddEquation, + // premultipliedAlpha:true, + } ); + + this.fsQuad = new FullScreenQuad( null ); + + this.originalClearColor = new Color(); + + } + + dispose() { // dispose render targets @@ -270,9 +268,9 @@ SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.fsQuad.dispose(); - }, + } - render: function ( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { + render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) { // render beauty and depth @@ -426,14 +424,14 @@ SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - renderPass: function ( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { + renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) { // save original state this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) ); - var originalClearAlpha = renderer.getClearAlpha( this.tempColor ); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha( this.tempColor ); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); @@ -455,13 +453,13 @@ SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - renderOverride: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { + renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) ); - var originalClearAlpha = renderer.getClearAlpha( this.tempColor ); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha( this.tempColor ); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); renderer.autoClear = false; @@ -487,14 +485,13 @@ SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, - + } - renderRefractive: function ( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { + renderRefractive( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) { this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) ); - var originalClearAlpha = renderer.getClearAlpha( this.tempColor ); - var originalAutoClear = renderer.autoClear; + const originalClearAlpha = renderer.getClearAlpha( this.tempColor ); + const originalAutoClear = renderer.autoClear; renderer.setRenderTarget( renderTarget ); renderer.autoClear = false; @@ -548,9 +545,9 @@ SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this.originalClearColor ); renderer.setClearAlpha( originalClearAlpha ); - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { this.width = width; this.height = height; @@ -567,9 +564,9 @@ SSRrPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.ssrrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); this.ssrrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); - }, + } -} ); +} SSRrPass.OUTPUT = { 'Default': 0, diff --git a/examples/jsm/postprocessing/SavePass.js b/examples/jsm/postprocessing/SavePass.js index 9a420a6682b950..c8d2c061f262af 100644 --- a/examples/jsm/postprocessing/SavePass.js +++ b/examples/jsm/postprocessing/SavePass.js @@ -5,50 +5,47 @@ import { UniformsUtils, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; -var SavePass = function ( renderTarget ) { +class SavePass extends Pass { - Pass.call( this ); + constructor( renderTarget ) { - if ( CopyShader === undefined ) - console.error( 'THREE.SavePass relies on CopyShader' ); + super(); - var shader = CopyShader; + if ( CopyShader === undefined ) console.error( 'THREE.SavePass relies on CopyShader' ); - this.textureID = 'tDiffuse'; + const shader = CopyShader; - this.uniforms = UniformsUtils.clone( shader.uniforms ); + this.textureID = 'tDiffuse'; - this.material = new ShaderMaterial( { + this.uniforms = UniformsUtils.clone( shader.uniforms ); - uniforms: this.uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + this.material = new ShaderMaterial( { - } ); + uniforms: this.uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader - this.renderTarget = renderTarget; + } ); - if ( this.renderTarget === undefined ) { + this.renderTarget = renderTarget; - this.renderTarget = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBFormat } ); - this.renderTarget.texture.name = 'SavePass.rt'; + if ( this.renderTarget === undefined ) { - } - - this.needsSwap = false; + this.renderTarget = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBFormat } ); + this.renderTarget.texture.name = 'SavePass.rt'; - this.fsQuad = new Pass.FullScreenQuad( this.material ); + } -}; + this.needsSwap = false; -SavePass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.fsQuad = new FullScreenQuad( this.material ); - constructor: SavePass, + } - render: function ( renderer, writeBuffer, readBuffer ) { + render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive */ ) { if ( this.uniforms[ this.textureID ] ) { @@ -62,6 +59,6 @@ SavePass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { SavePass }; diff --git a/examples/jsm/postprocessing/ShaderPass.js b/examples/jsm/postprocessing/ShaderPass.js index 7bfcf69f7e65fc..cd6913b4bccdf3 100644 --- a/examples/jsm/postprocessing/ShaderPass.js +++ b/examples/jsm/postprocessing/ShaderPass.js @@ -2,44 +2,42 @@ import { ShaderMaterial, UniformsUtils } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; -var ShaderPass = function ( shader, textureID ) { +class ShaderPass extends Pass { - Pass.call( this ); + constructor( shader, textureID ) { - this.textureID = ( textureID !== undefined ) ? textureID : 'tDiffuse'; + super(); - if ( shader instanceof ShaderMaterial ) { + this.textureID = ( textureID !== undefined ) ? textureID : 'tDiffuse'; - this.uniforms = shader.uniforms; + if ( shader instanceof ShaderMaterial ) { - this.material = shader; + this.uniforms = shader.uniforms; - } else if ( shader ) { + this.material = shader; - this.uniforms = UniformsUtils.clone( shader.uniforms ); + } else if ( shader ) { - this.material = new ShaderMaterial( { + this.uniforms = UniformsUtils.clone( shader.uniforms ); - defines: Object.assign( {}, shader.defines ), - uniforms: this.uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader + this.material = new ShaderMaterial( { - } ); + defines: Object.assign( {}, shader.defines ), + uniforms: this.uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader - } - - this.fsQuad = new Pass.FullScreenQuad( this.material ); + } ); -}; + } -ShaderPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.fsQuad = new FullScreenQuad( this.material ); - constructor: ShaderPass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { if ( this.uniforms[ this.textureID ] ) { @@ -65,6 +63,6 @@ ShaderPass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { ShaderPass }; diff --git a/examples/jsm/postprocessing/TAARenderPass.js b/examples/jsm/postprocessing/TAARenderPass.js index a9fe20f34ad7b4..73f8e7dc9427dc 100644 --- a/examples/jsm/postprocessing/TAARenderPass.js +++ b/examples/jsm/postprocessing/TAARenderPass.js @@ -15,39 +15,29 @@ import { SSAARenderPass } from '../postprocessing/SSAARenderPass.js'; * */ -var TAARenderPass = function ( scene, camera, clearColor, clearAlpha ) { +class TAARenderPass extends SSAARenderPass { - if ( SSAARenderPass === undefined ) { + constructor( scene, camera, clearColor, clearAlpha ) { - console.error( 'THREE.TAARenderPass relies on SSAARenderPass' ); + super( scene, camera, clearColor, clearAlpha ); - } - - SSAARenderPass.call( this, scene, camera, clearColor, clearAlpha ); - - this.sampleLevel = 0; - this.accumulate = false; - -}; + this.sampleLevel = 0; + this.accumulate = false; -TAARenderPass.JitterVectors = SSAARenderPass.JitterVectors; - -TAARenderPass.prototype = Object.assign( Object.create( SSAARenderPass.prototype ), { - - constructor: TAARenderPass, + } - render: function ( renderer, writeBuffer, readBuffer, deltaTime ) { + render( renderer, writeBuffer, readBuffer, deltaTime ) { if ( ! this.accumulate ) { - SSAARenderPass.prototype.render.call( this, renderer, writeBuffer, readBuffer, deltaTime ); + super.render( renderer, writeBuffer, readBuffer, deltaTime ); this.accumulateIndex = - 1; return; } - var jitterOffsets = TAARenderPass.JitterVectors[ 5 ]; + const jitterOffsets = _JitterVectors[ 5 ]; if ( ! this.sampleRenderTarget ) { @@ -65,16 +55,16 @@ TAARenderPass.prototype = Object.assign( Object.create( SSAARenderPass.prototype if ( this.accumulate && this.accumulateIndex === - 1 ) { - SSAARenderPass.prototype.render.call( this, renderer, this.holdRenderTarget, readBuffer, deltaTime ); + super.render( renderer, this.holdRenderTarget, readBuffer, deltaTime ); this.accumulateIndex = 0; } - var autoClear = renderer.autoClear; + const autoClear = renderer.autoClear; renderer.autoClear = false; - var sampleWeight = 1.0 / ( jitterOffsets.length ); + const sampleWeight = 1.0 / ( jitterOffsets.length ); if ( this.accumulateIndex >= 0 && this.accumulateIndex < jitterOffsets.length ) { @@ -82,11 +72,11 @@ TAARenderPass.prototype = Object.assign( Object.create( SSAARenderPass.prototype this.copyUniforms[ 'tDiffuse' ].value = writeBuffer.texture; // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. - var numSamplesPerFrame = Math.pow( 2, this.sampleLevel ); - for ( var i = 0; i < numSamplesPerFrame; i ++ ) { + const numSamplesPerFrame = Math.pow( 2, this.sampleLevel ); + for ( let i = 0; i < numSamplesPerFrame; i ++ ) { - var j = this.accumulateIndex; - var jitterOffset = jitterOffsets[ j ]; + const j = this.accumulateIndex; + const jitterOffset = jitterOffsets[ j ]; if ( this.camera.setViewOffset ) { @@ -114,7 +104,7 @@ TAARenderPass.prototype = Object.assign( Object.create( SSAARenderPass.prototype } - var accumulationWeight = this.accumulateIndex * sampleWeight; + const accumulationWeight = this.accumulateIndex * sampleWeight; if ( accumulationWeight > 0 ) { @@ -140,6 +130,38 @@ TAARenderPass.prototype = Object.assign( Object.create( SSAARenderPass.prototype } -} ); +} + +const _JitterVectors = [ + [ + [ 0, 0 ] + ], + [ + [ 4, 4 ], [ - 4, - 4 ] + ], + [ + [ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ] + ], + [ + [ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], + [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ] + ], + [ + [ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], + [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], + [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], + [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ] + ], + [ + [ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], + [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], + [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], + [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], + [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], + [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], + [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], + [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ] + ] +]; export { TAARenderPass }; diff --git a/examples/jsm/postprocessing/TexturePass.js b/examples/jsm/postprocessing/TexturePass.js index 37272df9544636..29d67057d67ad4 100644 --- a/examples/jsm/postprocessing/TexturePass.js +++ b/examples/jsm/postprocessing/TexturePass.js @@ -2,46 +2,43 @@ import { ShaderMaterial, UniformsUtils } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; -var TexturePass = function ( map, opacity ) { +class TexturePass extends Pass { - Pass.call( this ); + constructor( map, opacity ) { - if ( CopyShader === undefined ) - console.error( 'THREE.TexturePass relies on CopyShader' ); + super(); - var shader = CopyShader; + if ( CopyShader === undefined ) console.error( 'THREE.TexturePass relies on CopyShader' ); - this.map = map; - this.opacity = ( opacity !== undefined ) ? opacity : 1.0; + const shader = CopyShader; - this.uniforms = UniformsUtils.clone( shader.uniforms ); + this.map = map; + this.opacity = ( opacity !== undefined ) ? opacity : 1.0; - this.material = new ShaderMaterial( { + this.uniforms = UniformsUtils.clone( shader.uniforms ); - uniforms: this.uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader, - depthTest: false, - depthWrite: false + this.material = new ShaderMaterial( { - } ); + uniforms: this.uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + depthTest: false, + depthWrite: false - this.needsSwap = false; + } ); - this.fsQuad = new Pass.FullScreenQuad( null ); + this.needsSwap = false; -}; + this.fsQuad = new FullScreenQuad( null ); -TexturePass.prototype = Object.assign( Object.create( Pass.prototype ), { - - constructor: TexturePass, + } - render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { + render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) { - var oldAutoClear = renderer.autoClear; + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; this.fsQuad.material = this.material; @@ -58,6 +55,6 @@ TexturePass.prototype = Object.assign( Object.create( Pass.prototype ), { } -} ); +} export { TexturePass }; diff --git a/examples/jsm/postprocessing/UnrealBloomPass.js b/examples/jsm/postprocessing/UnrealBloomPass.js index d44897c1322049..c62f84f2beb75d 100644 --- a/examples/jsm/postprocessing/UnrealBloomPass.js +++ b/examples/jsm/postprocessing/UnrealBloomPass.js @@ -10,7 +10,7 @@ import { Vector3, WebGLRenderTarget } from '../../../build/three.module.js'; -import { Pass } from '../postprocessing/Pass.js'; +import { Pass, FullScreenQuad } from '../postprocessing/Pass.js'; import { CopyShader } from '../shaders/CopyShader.js'; import { LuminosityHighPassShader } from '../shaders/LuminosityHighPassShader.js'; @@ -23,152 +23,149 @@ import { LuminosityHighPassShader } from '../shaders/LuminosityHighPassShader.js * Reference: * - https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/ */ -var UnrealBloomPass = function ( resolution, strength, radius, threshold ) { +class UnrealBloomPass extends Pass { - Pass.call( this ); + constructor( resolution, strength, radius, threshold ) { - this.strength = ( strength !== undefined ) ? strength : 1; - this.radius = radius; - this.threshold = threshold; - this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); + super(); - // create color only once here, reuse it later inside the render function - this.clearColor = new Color( 0, 0, 0 ); + this.strength = ( strength !== undefined ) ? strength : 1; + this.radius = radius; + this.threshold = threshold; + this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); - // render targets - var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; - this.renderTargetsHorizontal = []; - this.renderTargetsVertical = []; - this.nMips = 5; - var resx = Math.round( this.resolution.x / 2 ); - var resy = Math.round( this.resolution.y / 2 ); + // create color only once here, reuse it later inside the render function + this.clearColor = new Color( 0, 0, 0 ); - this.renderTargetBright = new WebGLRenderTarget( resx, resy, pars ); - this.renderTargetBright.texture.name = 'UnrealBloomPass.bright'; - this.renderTargetBright.texture.generateMipmaps = false; + // render targets + const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat }; + this.renderTargetsHorizontal = []; + this.renderTargetsVertical = []; + this.nMips = 5; + let resx = Math.round( this.resolution.x / 2 ); + let resy = Math.round( this.resolution.y / 2 ); - for ( var i = 0; i < this.nMips; i ++ ) { + this.renderTargetBright = new WebGLRenderTarget( resx, resy, pars ); + this.renderTargetBright.texture.name = 'UnrealBloomPass.bright'; + this.renderTargetBright.texture.generateMipmaps = false; - var renderTargetHorizonal = new WebGLRenderTarget( resx, resy, pars ); + for ( let i = 0; i < this.nMips; i ++ ) { - renderTargetHorizonal.texture.name = 'UnrealBloomPass.h' + i; - renderTargetHorizonal.texture.generateMipmaps = false; + const renderTargetHorizonal = new WebGLRenderTarget( resx, resy, pars ); - this.renderTargetsHorizontal.push( renderTargetHorizonal ); + renderTargetHorizonal.texture.name = 'UnrealBloomPass.h' + i; + renderTargetHorizonal.texture.generateMipmaps = false; - var renderTargetVertical = new WebGLRenderTarget( resx, resy, pars ); + this.renderTargetsHorizontal.push( renderTargetHorizonal ); - renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i; - renderTargetVertical.texture.generateMipmaps = false; + const renderTargetVertical = new WebGLRenderTarget( resx, resy, pars ); - this.renderTargetsVertical.push( renderTargetVertical ); + renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i; + renderTargetVertical.texture.generateMipmaps = false; - resx = Math.round( resx / 2 ); + this.renderTargetsVertical.push( renderTargetVertical ); - resy = Math.round( resy / 2 ); - - } - - // luminosity high pass material + resx = Math.round( resx / 2 ); - if ( LuminosityHighPassShader === undefined ) - console.error( 'THREE.UnrealBloomPass relies on LuminosityHighPassShader' ); + resy = Math.round( resy / 2 ); - var highPassShader = LuminosityHighPassShader; - this.highPassUniforms = UniformsUtils.clone( highPassShader.uniforms ); + } - this.highPassUniforms[ 'luminosityThreshold' ].value = threshold; - this.highPassUniforms[ 'smoothWidth' ].value = 0.01; + // luminosity high pass material - this.materialHighPassFilter = new ShaderMaterial( { - uniforms: this.highPassUniforms, - vertexShader: highPassShader.vertexShader, - fragmentShader: highPassShader.fragmentShader, - defines: {} - } ); + if ( LuminosityHighPassShader === undefined ) + console.error( 'THREE.UnrealBloomPass relies on LuminosityHighPassShader' ); - // Gaussian Blur Materials - this.separableBlurMaterials = []; - var kernelSizeArray = [ 3, 5, 7, 9, 11 ]; - var resx = Math.round( this.resolution.x / 2 ); - var resy = Math.round( this.resolution.y / 2 ); + const highPassShader = LuminosityHighPassShader; + this.highPassUniforms = UniformsUtils.clone( highPassShader.uniforms ); - for ( var i = 0; i < this.nMips; i ++ ) { + this.highPassUniforms[ 'luminosityThreshold' ].value = threshold; + this.highPassUniforms[ 'smoothWidth' ].value = 0.01; - this.separableBlurMaterials.push( this.getSeperableBlurMaterial( kernelSizeArray[ i ] ) ); + this.materialHighPassFilter = new ShaderMaterial( { + uniforms: this.highPassUniforms, + vertexShader: highPassShader.vertexShader, + fragmentShader: highPassShader.fragmentShader, + defines: {} + } ); - this.separableBlurMaterials[ i ].uniforms[ 'texSize' ].value = new Vector2( resx, resy ); + // Gaussian Blur Materials + this.separableBlurMaterials = []; + const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; + resx = Math.round( this.resolution.x / 2 ); + resy = Math.round( this.resolution.y / 2 ); - resx = Math.round( resx / 2 ); + for ( let i = 0; i < this.nMips; i ++ ) { - resy = Math.round( resy / 2 ); + this.separableBlurMaterials.push( this.getSeperableBlurMaterial( kernelSizeArray[ i ] ) ); - } + this.separableBlurMaterials[ i ].uniforms[ 'texSize' ].value = new Vector2( resx, resy ); - // Composite material - this.compositeMaterial = this.getCompositeMaterial( this.nMips ); - this.compositeMaterial.uniforms[ 'blurTexture1' ].value = this.renderTargetsVertical[ 0 ].texture; - this.compositeMaterial.uniforms[ 'blurTexture2' ].value = this.renderTargetsVertical[ 1 ].texture; - this.compositeMaterial.uniforms[ 'blurTexture3' ].value = this.renderTargetsVertical[ 2 ].texture; - this.compositeMaterial.uniforms[ 'blurTexture4' ].value = this.renderTargetsVertical[ 3 ].texture; - this.compositeMaterial.uniforms[ 'blurTexture5' ].value = this.renderTargetsVertical[ 4 ].texture; - this.compositeMaterial.uniforms[ 'bloomStrength' ].value = strength; - this.compositeMaterial.uniforms[ 'bloomRadius' ].value = 0.1; - this.compositeMaterial.needsUpdate = true; + resx = Math.round( resx / 2 ); - var bloomFactors = [ 1.0, 0.8, 0.6, 0.4, 0.2 ]; - this.compositeMaterial.uniforms[ 'bloomFactors' ].value = bloomFactors; - this.bloomTintColors = [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), - new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ]; - this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors; + resy = Math.round( resy / 2 ); - // copy material - if ( CopyShader === undefined ) { + } - console.error( 'THREE.UnrealBloomPass relies on CopyShader' ); + // Composite material + this.compositeMaterial = this.getCompositeMaterial( this.nMips ); + this.compositeMaterial.uniforms[ 'blurTexture1' ].value = this.renderTargetsVertical[ 0 ].texture; + this.compositeMaterial.uniforms[ 'blurTexture2' ].value = this.renderTargetsVertical[ 1 ].texture; + this.compositeMaterial.uniforms[ 'blurTexture3' ].value = this.renderTargetsVertical[ 2 ].texture; + this.compositeMaterial.uniforms[ 'blurTexture4' ].value = this.renderTargetsVertical[ 3 ].texture; + this.compositeMaterial.uniforms[ 'blurTexture5' ].value = this.renderTargetsVertical[ 4 ].texture; + this.compositeMaterial.uniforms[ 'bloomStrength' ].value = strength; + this.compositeMaterial.uniforms[ 'bloomRadius' ].value = 0.1; + this.compositeMaterial.needsUpdate = true; + + const bloomFactors = [ 1.0, 0.8, 0.6, 0.4, 0.2 ]; + this.compositeMaterial.uniforms[ 'bloomFactors' ].value = bloomFactors; + this.bloomTintColors = [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ]; + this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors; - } + // copy material + if ( CopyShader === undefined ) { - var copyShader = CopyShader; + console.error( 'THREE.UnrealBloomPass relies on CopyShader' ); - this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); - this.copyUniforms[ 'opacity' ].value = 1.0; + } - this.materialCopy = new ShaderMaterial( { - uniforms: this.copyUniforms, - vertexShader: copyShader.vertexShader, - fragmentShader: copyShader.fragmentShader, - blending: AdditiveBlending, - depthTest: false, - depthWrite: false, - transparent: true - } ); + const copyShader = CopyShader; - this.enabled = true; - this.needsSwap = false; + this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); + this.copyUniforms[ 'opacity' ].value = 1.0; - this._oldClearColor = new Color(); - this.oldClearAlpha = 1; + this.materialCopy = new ShaderMaterial( { + uniforms: this.copyUniforms, + vertexShader: copyShader.vertexShader, + fragmentShader: copyShader.fragmentShader, + blending: AdditiveBlending, + depthTest: false, + depthWrite: false, + transparent: true + } ); - this.basic = new MeshBasicMaterial(); + this.enabled = true; + this.needsSwap = false; - this.fsQuad = new Pass.FullScreenQuad( null ); + this._oldClearColor = new Color(); + this.oldClearAlpha = 1; -}; + this.basic = new MeshBasicMaterial(); -UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { + this.fsQuad = new FullScreenQuad( null ); - constructor: UnrealBloomPass, + } - dispose: function () { + dispose() { - for ( var i = 0; i < this.renderTargetsHorizontal.length; i ++ ) { + for ( let i = 0; i < this.renderTargetsHorizontal.length; i ++ ) { this.renderTargetsHorizontal[ i ].dispose(); } - for ( var i = 0; i < this.renderTargetsVertical.length; i ++ ) { + for ( let i = 0; i < this.renderTargetsVertical.length; i ++ ) { this.renderTargetsVertical[ i ].dispose(); @@ -176,16 +173,16 @@ UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { this.renderTargetBright.dispose(); - }, + } - setSize: function ( width, height ) { + setSize( width, height ) { - var resx = Math.round( width / 2 ); - var resy = Math.round( height / 2 ); + let resx = Math.round( width / 2 ); + let resy = Math.round( height / 2 ); this.renderTargetBright.setSize( resx, resy ); - for ( var i = 0; i < this.nMips; i ++ ) { + for ( let i = 0; i < this.nMips; i ++ ) { this.renderTargetsHorizontal[ i ].setSize( resx, resy ); this.renderTargetsVertical[ i ].setSize( resx, resy ); @@ -197,13 +194,13 @@ UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { } - }, + } - render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { + render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { renderer.getClearColor( this._oldClearColor ); this.oldClearAlpha = renderer.getClearAlpha(); - var oldAutoClear = renderer.autoClear; + const oldAutoClear = renderer.autoClear; renderer.autoClear = false; renderer.setClearColor( this.clearColor, 0 ); @@ -235,9 +232,9 @@ UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { // 2. Blur All the mips progressively - var inputRenderTarget = this.renderTargetBright; + let inputRenderTarget = this.renderTargetBright; - for ( var i = 0; i < this.nMips; i ++ ) { + for ( let i = 0; i < this.nMips; i ++ ) { this.fsQuad.material = this.separableBlurMaterials[ i ]; @@ -292,9 +289,9 @@ UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { renderer.setClearColor( this._oldClearColor, this.oldClearAlpha ); renderer.autoClear = oldAutoClear; - }, + } - getSeperableBlurMaterial: function ( kernelRadius ) { + getSeperableBlurMaterial( kernelRadius ) { return new ShaderMaterial( { @@ -310,43 +307,43 @@ UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { }, vertexShader: - 'varying vec2 vUv;\n\ - void main() {\n\ - vUv = uv;\n\ - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ - }', + `varying vec2 vUv; + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, fragmentShader: - '#include \ - varying vec2 vUv;\n\ - uniform sampler2D colorTexture;\n\ - uniform vec2 texSize;\ - uniform vec2 direction;\ - \ - float gaussianPdf(in float x, in float sigma) {\ - return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\ - }\ - void main() {\n\ - vec2 invSize = 1.0 / texSize;\ - float fSigma = float(SIGMA);\ - float weightSum = gaussianPdf(0.0, fSigma);\ - vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\ - for( int i = 1; i < KERNEL_RADIUS; i ++ ) {\ - float x = float(i);\ - float w = gaussianPdf(x, fSigma);\ - vec2 uvOffset = direction * invSize * x;\ - vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;\ - vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;\ - diffuseSum += (sample1 + sample2) * w;\ - weightSum += 2.0 * w;\ - }\ - gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n\ - }' + `#include + varying vec2 vUv; + uniform sampler2D colorTexture; + uniform vec2 texSize; + uniform vec2 direction; + + float gaussianPdf(in float x, in float sigma) { + return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma; + } + void main() { + vec2 invSize = 1.0 / texSize; + float fSigma = float(SIGMA); + float weightSum = gaussianPdf(0.0, fSigma); + vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum; + for( int i = 1; i < KERNEL_RADIUS; i ++ ) { + float x = float(i); + float w = gaussianPdf(x, fSigma); + vec2 uvOffset = direction * invSize * x; + vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb; + vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb; + diffuseSum += (sample1 + sample2) * w; + weightSum += 2.0 * w; + } + gl_FragColor = vec4(diffuseSum/weightSum, 1.0); + }` } ); - }, + } - getCompositeMaterial: function ( nMips ) { + getCompositeMaterial( nMips ) { return new ShaderMaterial( { @@ -368,42 +365,42 @@ UnrealBloomPass.prototype = Object.assign( Object.create( Pass.prototype ), { }, vertexShader: - 'varying vec2 vUv;\n\ - void main() {\n\ - vUv = uv;\n\ - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ - }', + `varying vec2 vUv; + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, fragmentShader: - 'varying vec2 vUv;\ - uniform sampler2D blurTexture1;\ - uniform sampler2D blurTexture2;\ - uniform sampler2D blurTexture3;\ - uniform sampler2D blurTexture4;\ - uniform sampler2D blurTexture5;\ - uniform sampler2D dirtTexture;\ - uniform float bloomStrength;\ - uniform float bloomRadius;\ - uniform float bloomFactors[NUM_MIPS];\ - uniform vec3 bloomTintColors[NUM_MIPS];\ - \ - float lerpBloomFactor(const in float factor) { \ - float mirrorFactor = 1.2 - factor;\ - return mix(factor, mirrorFactor, bloomRadius);\ - }\ - \ - void main() {\ - gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) + \ - lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) + \ - lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) + \ - lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) + \ - lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) );\ - }' + `varying vec2 vUv; + uniform sampler2D blurTexture1; + uniform sampler2D blurTexture2; + uniform sampler2D blurTexture3; + uniform sampler2D blurTexture4; + uniform sampler2D blurTexture5; + uniform sampler2D dirtTexture; + uniform float bloomStrength; + uniform float bloomRadius; + uniform float bloomFactors[NUM_MIPS]; + uniform vec3 bloomTintColors[NUM_MIPS]; + + float lerpBloomFactor(const in float factor) { + float mirrorFactor = 1.2 - factor; + return mix(factor, mirrorFactor, bloomRadius); + } + + void main() { + gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) + + lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) + + lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) + + lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) + + lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) ); + }` } ); } -} ); +} UnrealBloomPass.BlurDirectionX = new Vector2( 1.0, 0.0 ); UnrealBloomPass.BlurDirectionY = new Vector2( 0.0, 1.0 ); diff --git a/examples/jsm/renderers/CSS2DRenderer.js b/examples/jsm/renderers/CSS2DRenderer.js index 4110728a35c0d9..2e8cb583909fbe 100644 --- a/examples/jsm/renderers/CSS2DRenderer.js +++ b/examples/jsm/renderers/CSS2DRenderer.js @@ -4,37 +4,35 @@ import { Vector3 } from '../../../build/three.module.js'; -var CSS2DObject = function ( element ) { +class CSS2DObject extends Object3D { - Object3D.call( this ); + constructor( element ) { - this.element = element || document.createElement( 'div' ); + super(); - this.element.style.position = 'absolute'; + this.element = element || document.createElement( 'div' ); - this.addEventListener( 'removed', function () { + this.element.style.position = 'absolute'; - this.traverse( function ( object ) { + this.addEventListener( 'removed', function () { - if ( object.element instanceof Element && object.element.parentNode !== null ) { + this.traverse( function ( object ) { - object.element.parentNode.removeChild( object.element ); + if ( object.element instanceof Element && object.element.parentNode !== null ) { - } - - } ); + object.element.parentNode.removeChild( object.element ); - } ); + } -}; + } ); -CSS2DObject.prototype = Object.assign( Object.create( Object3D.prototype ), { + } ); - constructor: CSS2DObject, + } - copy: function ( source, recursive ) { + copy( source, recursive ) { - Object3D.prototype.copy.call( this, source, recursive ); + super.copy( source, recursive ); this.element = source.element.cloneNode( true ); @@ -42,164 +40,165 @@ CSS2DObject.prototype = Object.assign( Object.create( Object3D.prototype ), { } -} ); +} + +CSS2DObject.prototype.isCSS2DObject = true; // -var CSS2DRenderer = function () { +const _vector = new Vector3(); +const _viewMatrix = new Matrix4(); +const _viewProjectionMatrix = new Matrix4(); +const _a = new Vector3(); +const _b = new Vector3(); - var _this = this; +class CSS2DRenderer { - var _width, _height; - var _widthHalf, _heightHalf; + constructor() { - var vector = new Vector3(); - var viewMatrix = new Matrix4(); - var viewProjectionMatrix = new Matrix4(); + const _this = this; - var cache = { - objects: new WeakMap() - }; + let _width, _height; + let _widthHalf, _heightHalf; - var domElement = document.createElement( 'div' ); - domElement.style.overflow = 'hidden'; + const cache = { + objects: new WeakMap() + }; - this.domElement = domElement; + const domElement = document.createElement( 'div' ); + domElement.style.overflow = 'hidden'; - this.getSize = function () { + this.domElement = domElement; - return { - width: _width, - height: _height - }; + this.getSize = function () { - }; - - this.setSize = function ( width, height ) { + return { + width: _width, + height: _height + }; - _width = width; - _height = height; + }; - _widthHalf = _width / 2; - _heightHalf = _height / 2; + this.render = function ( scene, camera ) { - domElement.style.width = width + 'px'; - domElement.style.height = height + 'px'; + if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); - }; + _viewMatrix.copy( camera.matrixWorldInverse ); + _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); - var renderObject = function ( object, scene, camera ) { + renderObject( scene, scene, camera ); + zOrder( scene ); - if ( object instanceof CSS2DObject ) { + }; - object.onBeforeRender( _this, scene, camera ); + this.setSize = function ( width, height ) { - vector.setFromMatrixPosition( object.matrixWorld ); - vector.applyMatrix4( viewProjectionMatrix ); + _width = width; + _height = height; - var element = object.element; + _widthHalf = _width / 2; + _heightHalf = _height / 2; - if ( /apple/i.test( navigator.vendor ) ) { + domElement.style.width = width + 'px'; + domElement.style.height = height + 'px'; - // https://github.com/mrdoob/three.js/issues/21415 - element.style.transform = 'translate(-50%,-50%) translate(' + Math.round( vector.x * _widthHalf + _widthHalf ) + 'px,' + Math.round( - vector.y * _heightHalf + _heightHalf ) + 'px)'; + }; - } else { + function renderObject( object, scene, camera ) { - element.style.transform = 'translate(-50%,-50%) translate(' + ( vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - vector.y * _heightHalf + _heightHalf ) + 'px)'; + if ( object.isCSS2DObject ) { - } + object.onBeforeRender( _this, scene, camera ); - element.style.display = ( object.visible && vector.z >= - 1 && vector.z <= 1 ) ? '' : 'none'; + _vector.setFromMatrixPosition( object.matrixWorld ); + _vector.applyMatrix4( _viewProjectionMatrix ); - var objectData = { - distanceToCameraSquared: getDistanceToSquared( camera, object ) - }; + const element = object.element; - cache.objects.set( object, objectData ); + if ( /apple/i.test( navigator.vendor ) ) { - if ( element.parentNode !== domElement ) { + // https://github.com/mrdoob/three.js/issues/21415 + element.style.transform = 'translate(-50%,-50%) translate(' + Math.round( _vector.x * _widthHalf + _widthHalf ) + 'px,' + Math.round( - _vector.y * _heightHalf + _heightHalf ) + 'px)'; - domElement.appendChild( element ); + } else { - } + element.style.transform = 'translate(-50%,-50%) translate(' + ( _vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - _vector.y * _heightHalf + _heightHalf ) + 'px)'; - object.onAfterRender( _this, scene, camera ); + } - } + element.style.display = ( object.visible && _vector.z >= - 1 && _vector.z <= 1 ) ? '' : 'none'; - for ( var i = 0, l = object.children.length; i < l; i ++ ) { + const objectData = { + distanceToCameraSquared: getDistanceToSquared( camera, object ) + }; - renderObject( object.children[ i ], scene, camera ); + cache.objects.set( object, objectData ); - } + if ( element.parentNode !== domElement ) { - }; + domElement.appendChild( element ); - var getDistanceToSquared = function () { + } - var a = new Vector3(); - var b = new Vector3(); + object.onAfterRender( _this, scene, camera ); - return function ( object1, object2 ) { + } - a.setFromMatrixPosition( object1.matrixWorld ); - b.setFromMatrixPosition( object2.matrixWorld ); + for ( let i = 0, l = object.children.length; i < l; i ++ ) { - return a.distanceToSquared( b ); + renderObject( object.children[ i ], scene, camera ); - }; + } - }(); + } - var filterAndFlatten = function ( scene ) { + function getDistanceToSquared( object1, object2 ) { - var result = []; + _a.setFromMatrixPosition( object1.matrixWorld ); + _b.setFromMatrixPosition( object2.matrixWorld ); - scene.traverse( function ( object ) { + return _a.distanceToSquared( _b ); - if ( object instanceof CSS2DObject ) result.push( object ); + } - } ); + function filterAndFlatten( scene ) { - return result; + const result = []; - }; + scene.traverse( function ( object ) { - var zOrder = function ( scene ) { + if ( object.isCSS2DObject ) result.push( object ); - var sorted = filterAndFlatten( scene ).sort( function ( a, b ) { + } ); - var distanceA = cache.objects.get( a ).distanceToCameraSquared; - var distanceB = cache.objects.get( b ).distanceToCameraSquared; + return result; - return distanceA - distanceB; + } - } ); + function zOrder( scene ) { - var zMax = sorted.length; + const sorted = filterAndFlatten( scene ).sort( function ( a, b ) { - for ( var i = 0, l = sorted.length; i < l; i ++ ) { + const distanceA = cache.objects.get( a ).distanceToCameraSquared; + const distanceB = cache.objects.get( b ).distanceToCameraSquared; - sorted[ i ].element.style.zIndex = zMax - i; + return distanceA - distanceB; - } + } ); - }; + const zMax = sorted.length; - this.render = function ( scene, camera ) { + for ( let i = 0, l = sorted.length; i < l; i ++ ) { - if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); - if ( camera.parent === null ) camera.updateMatrixWorld(); + sorted[ i ].element.style.zIndex = zMax - i; - viewMatrix.copy( camera.matrixWorldInverse ); - viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, viewMatrix ); + } - renderObject( scene, scene, camera ); - zOrder( scene ); + } - }; + } -}; +} export { CSS2DObject, CSS2DRenderer }; diff --git a/examples/jsm/renderers/CSS3DRenderer.js b/examples/jsm/renderers/CSS3DRenderer.js index c8d3222cca5411..50a510df545b0b 100644 --- a/examples/jsm/renderers/CSS3DRenderer.js +++ b/examples/jsm/renderers/CSS3DRenderer.js @@ -7,37 +7,35 @@ import { * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs */ -var CSS3DObject = function ( element ) { +class CSS3DObject extends Object3D { - Object3D.call( this ); + constructor( element ) { - this.element = element || document.createElement( 'div' ); - this.element.style.position = 'absolute'; - this.element.style.pointerEvents = 'auto'; + super(); - this.addEventListener( 'removed', function () { + this.element = element || document.createElement( 'div' ); + this.element.style.position = 'absolute'; + this.element.style.pointerEvents = 'auto'; - this.traverse( function ( object ) { + this.addEventListener( 'removed', function () { - if ( object.element instanceof Element && object.element.parentNode !== null ) { + this.traverse( function ( object ) { - object.element.parentNode.removeChild( object.element ); + if ( object.element instanceof Element && object.element.parentNode !== null ) { - } - - } ); + object.element.parentNode.removeChild( object.element ); - } ); + } -}; + } ); -CSS3DObject.prototype = Object.assign( Object.create( Object3D.prototype ), { + } ); - constructor: CSS3DObject, + } - copy: function ( source, recursive ) { + copy( source, recursive ) { - Object3D.prototype.copy.call( this, source, recursive ); + super.copy( source, recursive ); this.element = source.element.cloneNode( true ); @@ -45,228 +43,239 @@ CSS3DObject.prototype = Object.assign( Object.create( Object3D.prototype ), { } -} ); +} -var CSS3DSprite = function ( element ) { +CSS3DObject.prototype.isCSS3DObject = true; - CSS3DObject.call( this, element ); +class CSS3DSprite extends CSS3DObject { -}; + constructor( element ) { -CSS3DSprite.prototype = Object.create( CSS3DObject.prototype ); -CSS3DSprite.prototype.constructor = CSS3DSprite; + super( element ); + + } + +} + +CSS3DSprite.prototype.isCSS3DSprite = true; // -var CSS3DRenderer = function () { +const _matrix = new Matrix4(); - var _this = this; +class CSS3DRenderer { - var _width, _height; - var _widthHalf, _heightHalf; + constructor() { - var matrix = new Matrix4(); + const _this = this; - var cache = { - camera: { fov: 0, style: '' }, - objects: new WeakMap() - }; + let _width, _height; + let _widthHalf, _heightHalf; - var domElement = document.createElement( 'div' ); - domElement.style.overflow = 'hidden'; + const cache = { + camera: { fov: 0, style: '' }, + objects: new WeakMap() + }; - this.domElement = domElement; + const domElement = document.createElement( 'div' ); + domElement.style.overflow = 'hidden'; - var cameraElement = document.createElement( 'div' ); + this.domElement = domElement; - cameraElement.style.transformStyle = 'preserve-3d'; - cameraElement.style.pointerEvents = 'none'; + const cameraElement = document.createElement( 'div' ); - domElement.appendChild( cameraElement ); + cameraElement.style.transformStyle = 'preserve-3d'; + cameraElement.style.pointerEvents = 'none'; - this.getSize = function () { + domElement.appendChild( cameraElement ); + + this.getSize = function () { + + return { + width: _width, + height: _height + }; - return { - width: _width, - height: _height }; - }; + this.render = function ( scene, camera ) { - this.setSize = function ( width, height ) { + const fov = camera.projectionMatrix.elements[ 5 ] * _heightHalf; - _width = width; - _height = height; - _widthHalf = _width / 2; - _heightHalf = _height / 2; + if ( cache.camera.fov !== fov ) { - domElement.style.width = width + 'px'; - domElement.style.height = height + 'px'; + domElement.style.perspective = camera.isPerspectiveCamera ? fov + 'px' : ''; + cache.camera.fov = fov; - cameraElement.style.width = width + 'px'; - cameraElement.style.height = height + 'px'; + } - }; + if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); - function epsilon( value ) { + let tx, ty; - return Math.abs( value ) < 1e-10 ? 0 : value; + if ( camera.isOrthographicCamera ) { - } + tx = - ( camera.right + camera.left ) / 2; + ty = ( camera.top + camera.bottom ) / 2; - function getCameraCSSMatrix( matrix ) { - - var elements = matrix.elements; - - return 'matrix3d(' + - epsilon( elements[ 0 ] ) + ',' + - epsilon( - elements[ 1 ] ) + ',' + - epsilon( elements[ 2 ] ) + ',' + - epsilon( elements[ 3 ] ) + ',' + - epsilon( elements[ 4 ] ) + ',' + - epsilon( - elements[ 5 ] ) + ',' + - epsilon( elements[ 6 ] ) + ',' + - epsilon( elements[ 7 ] ) + ',' + - epsilon( elements[ 8 ] ) + ',' + - epsilon( - elements[ 9 ] ) + ',' + - epsilon( elements[ 10 ] ) + ',' + - epsilon( elements[ 11 ] ) + ',' + - epsilon( elements[ 12 ] ) + ',' + - epsilon( - elements[ 13 ] ) + ',' + - epsilon( elements[ 14 ] ) + ',' + - epsilon( elements[ 15 ] ) + - ')'; + } - } + const cameraCSSMatrix = camera.isOrthographicCamera ? + 'scale(' + fov + ')' + 'translate(' + epsilon( tx ) + 'px,' + epsilon( ty ) + 'px)' + getCameraCSSMatrix( camera.matrixWorldInverse ) : + 'translateZ(' + fov + 'px)' + getCameraCSSMatrix( camera.matrixWorldInverse ); - function getObjectCSSMatrix( matrix ) { - - var elements = matrix.elements; - var matrix3d = 'matrix3d(' + - epsilon( elements[ 0 ] ) + ',' + - epsilon( elements[ 1 ] ) + ',' + - epsilon( elements[ 2 ] ) + ',' + - epsilon( elements[ 3 ] ) + ',' + - epsilon( - elements[ 4 ] ) + ',' + - epsilon( - elements[ 5 ] ) + ',' + - epsilon( - elements[ 6 ] ) + ',' + - epsilon( - elements[ 7 ] ) + ',' + - epsilon( elements[ 8 ] ) + ',' + - epsilon( elements[ 9 ] ) + ',' + - epsilon( elements[ 10 ] ) + ',' + - epsilon( elements[ 11 ] ) + ',' + - epsilon( elements[ 12 ] ) + ',' + - epsilon( elements[ 13 ] ) + ',' + - epsilon( elements[ 14 ] ) + ',' + - epsilon( elements[ 15 ] ) + - ')'; - - return 'translate(-50%,-50%)' + matrix3d; + const style = cameraCSSMatrix + + 'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)'; - } + if ( cache.camera.style !== style ) { - function renderObject( object, scene, camera, cameraCSSMatrix ) { + cameraElement.style.transform = style; - if ( object instanceof CSS3DObject ) { + cache.camera.style = style; - object.onBeforeRender( _this, scene, camera ); + } - var style; + renderObject( scene, scene, camera, cameraCSSMatrix ); - if ( object instanceof CSS3DSprite ) { + }; - // http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/ + this.setSize = function ( width, height ) { - matrix.copy( camera.matrixWorldInverse ); - matrix.transpose(); - matrix.copyPosition( object.matrixWorld ); - matrix.scale( object.scale ); + _width = width; + _height = height; + _widthHalf = _width / 2; + _heightHalf = _height / 2; - matrix.elements[ 3 ] = 0; - matrix.elements[ 7 ] = 0; - matrix.elements[ 11 ] = 0; - matrix.elements[ 15 ] = 1; + domElement.style.width = width + 'px'; + domElement.style.height = height + 'px'; - style = getObjectCSSMatrix( matrix ); + cameraElement.style.width = width + 'px'; + cameraElement.style.height = height + 'px'; - } else { + }; - style = getObjectCSSMatrix( object.matrixWorld ); + function epsilon( value ) { - } + return Math.abs( value ) < 1e-10 ? 0 : value; - var element = object.element; - var cachedObject = cache.objects.get( object ); + } - if ( cachedObject === undefined || cachedObject.style !== style ) { + function getCameraCSSMatrix( matrix ) { + + const elements = matrix.elements; + + return 'matrix3d(' + + epsilon( elements[ 0 ] ) + ',' + + epsilon( - elements[ 1 ] ) + ',' + + epsilon( elements[ 2 ] ) + ',' + + epsilon( elements[ 3 ] ) + ',' + + epsilon( elements[ 4 ] ) + ',' + + epsilon( - elements[ 5 ] ) + ',' + + epsilon( elements[ 6 ] ) + ',' + + epsilon( elements[ 7 ] ) + ',' + + epsilon( elements[ 8 ] ) + ',' + + epsilon( - elements[ 9 ] ) + ',' + + epsilon( elements[ 10 ] ) + ',' + + epsilon( elements[ 11 ] ) + ',' + + epsilon( elements[ 12 ] ) + ',' + + epsilon( - elements[ 13 ] ) + ',' + + epsilon( elements[ 14 ] ) + ',' + + epsilon( elements[ 15 ] ) + + ')'; - element.style.transform = style; + } - var objectData = { style: style }; - cache.objects.set( object, objectData ); + function getObjectCSSMatrix( matrix ) { + + const elements = matrix.elements; + const matrix3d = 'matrix3d(' + + epsilon( elements[ 0 ] ) + ',' + + epsilon( elements[ 1 ] ) + ',' + + epsilon( elements[ 2 ] ) + ',' + + epsilon( elements[ 3 ] ) + ',' + + epsilon( - elements[ 4 ] ) + ',' + + epsilon( - elements[ 5 ] ) + ',' + + epsilon( - elements[ 6 ] ) + ',' + + epsilon( - elements[ 7 ] ) + ',' + + epsilon( elements[ 8 ] ) + ',' + + epsilon( elements[ 9 ] ) + ',' + + epsilon( elements[ 10 ] ) + ',' + + epsilon( elements[ 11 ] ) + ',' + + epsilon( elements[ 12 ] ) + ',' + + epsilon( elements[ 13 ] ) + ',' + + epsilon( elements[ 14 ] ) + ',' + + epsilon( elements[ 15 ] ) + + ')'; + + return 'translate(-50%,-50%)' + matrix3d; - } + } - element.style.display = object.visible ? '' : 'none'; + function renderObject( object, scene, camera, cameraCSSMatrix ) { - if ( element.parentNode !== cameraElement ) { + if ( object.isCSS3DObject ) { - cameraElement.appendChild( element ); + object.onBeforeRender( _this, scene, camera ); - } + let style; - object.onAfterRender( _this, scene, camera ); + if ( object.isCSS3DSprite ) { - } + // http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/ - for ( var i = 0, l = object.children.length; i < l; i ++ ) { + _matrix.copy( camera.matrixWorldInverse ); + _matrix.transpose(); + _matrix.copyPosition( object.matrixWorld ); + _matrix.scale( object.scale ); - renderObject( object.children[ i ], scene, camera, cameraCSSMatrix ); + _matrix.elements[ 3 ] = 0; + _matrix.elements[ 7 ] = 0; + _matrix.elements[ 11 ] = 0; + _matrix.elements[ 15 ] = 1; - } + style = getObjectCSSMatrix( _matrix ); - } + } else { - this.render = function ( scene, camera ) { + style = getObjectCSSMatrix( object.matrixWorld ); - var fov = camera.projectionMatrix.elements[ 5 ] * _heightHalf; + } - if ( cache.camera.fov !== fov ) { + const element = object.element; + const cachedObject = cache.objects.get( object ); - domElement.style.perspective = camera.isPerspectiveCamera ? fov + 'px' : ''; - cache.camera.fov = fov; + if ( cachedObject === undefined || cachedObject.style !== style ) { - } + element.style.transform = style; - if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); - if ( camera.parent === null ) camera.updateMatrixWorld(); + const objectData = { style: style }; + cache.objects.set( object, objectData ); - if ( camera.isOrthographicCamera ) { + } - var tx = - ( camera.right + camera.left ) / 2; - var ty = ( camera.top + camera.bottom ) / 2; + element.style.display = object.visible ? '' : 'none'; - } + if ( element.parentNode !== cameraElement ) { - var cameraCSSMatrix = camera.isOrthographicCamera ? - 'scale(' + fov + ')' + 'translate(' + epsilon( tx ) + 'px,' + epsilon( ty ) + 'px)' + getCameraCSSMatrix( camera.matrixWorldInverse ) : - 'translateZ(' + fov + 'px)' + getCameraCSSMatrix( camera.matrixWorldInverse ); + cameraElement.appendChild( element ); - var style = cameraCSSMatrix + - 'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)'; + } - if ( cache.camera.style !== style ) { + object.onAfterRender( _this, scene, camera ); - cameraElement.style.transform = style; + } - cache.camera.style = style; + for ( let i = 0, l = object.children.length; i < l; i ++ ) { - } + renderObject( object.children[ i ], scene, camera, cameraCSSMatrix ); - renderObject( scene, scene, camera, cameraCSSMatrix ); + } + + } - }; + } -}; +} export { CSS3DObject, CSS3DSprite, CSS3DRenderer }; diff --git a/examples/jsm/renderers/Projector.js b/examples/jsm/renderers/Projector.js index 62db05203da029..8c3e72dd6a5b3d 100644 --- a/examples/jsm/renderers/Projector.js +++ b/examples/jsm/renderers/Projector.js @@ -10,922 +10,950 @@ import { Vector4 } from '../../../build/three.module.js'; -var RenderableObject = function () { +class RenderableObject { - this.id = 0; + constructor() { - this.object = null; - this.z = 0; - this.renderOrder = 0; + this.id = 0; -}; + this.object = null; + this.z = 0; + this.renderOrder = 0; + + } + +} // -var RenderableFace = function () { +class RenderableFace { - this.id = 0; + constructor() { - this.v1 = new RenderableVertex(); - this.v2 = new RenderableVertex(); - this.v3 = new RenderableVertex(); + this.id = 0; - this.normalModel = new Vector3(); + this.v1 = new RenderableVertex(); + this.v2 = new RenderableVertex(); + this.v3 = new RenderableVertex(); - this.vertexNormalsModel = [ new Vector3(), new Vector3(), new Vector3() ]; - this.vertexNormalsLength = 0; + this.normalModel = new Vector3(); - this.color = new Color(); - this.material = null; - this.uvs = [ new Vector2(), new Vector2(), new Vector2() ]; + this.vertexNormalsModel = [ new Vector3(), new Vector3(), new Vector3() ]; + this.vertexNormalsLength = 0; - this.z = 0; - this.renderOrder = 0; + this.color = new Color(); + this.material = null; + this.uvs = [ new Vector2(), new Vector2(), new Vector2() ]; -}; + this.z = 0; + this.renderOrder = 0; + + } + +} // -var RenderableVertex = function () { +class RenderableVertex { + + constructor() { - this.position = new Vector3(); - this.positionWorld = new Vector3(); - this.positionScreen = new Vector4(); + this.position = new Vector3(); + this.positionWorld = new Vector3(); + this.positionScreen = new Vector4(); - this.visible = true; + this.visible = true; + + } -}; + copy( vertex ) { -RenderableVertex.prototype.copy = function ( vertex ) { + this.positionWorld.copy( vertex.positionWorld ); + this.positionScreen.copy( vertex.positionScreen ); - this.positionWorld.copy( vertex.positionWorld ); - this.positionScreen.copy( vertex.positionScreen ); + } -}; +} // -var RenderableLine = function () { +class RenderableLine { + + constructor() { - this.id = 0; + this.id = 0; - this.v1 = new RenderableVertex(); - this.v2 = new RenderableVertex(); + this.v1 = new RenderableVertex(); + this.v2 = new RenderableVertex(); - this.vertexColors = [ new Color(), new Color() ]; - this.material = null; + this.vertexColors = [ new Color(), new Color() ]; + this.material = null; - this.z = 0; - this.renderOrder = 0; + this.z = 0; + this.renderOrder = 0; -}; + } + +} // -var RenderableSprite = function () { +class RenderableSprite { - this.id = 0; + constructor() { - this.object = null; + this.id = 0; - this.x = 0; - this.y = 0; - this.z = 0; + this.object = null; - this.rotation = 0; - this.scale = new Vector2(); + this.x = 0; + this.y = 0; + this.z = 0; - this.material = null; - this.renderOrder = 0; + this.rotation = 0; + this.scale = new Vector2(); -}; + this.material = null; + this.renderOrder = 0; + + } + +} // -var Projector = function () { +class Projector { - var _object, _objectCount, _objectPool = [], _objectPoolLength = 0, - _vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0, - _face, _faceCount, _facePool = [], _facePoolLength = 0, - _line, _lineCount, _linePool = [], _linePoolLength = 0, - _sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0, + constructor() { - _renderData = { objects: [], lights: [], elements: [] }, + let _object, _objectCount, _objectPoolLength = 0, + _vertex, _vertexCount, _vertexPoolLength = 0, + _face, _faceCount, _facePoolLength = 0, + _line, _lineCount, _linePoolLength = 0, + _sprite, _spriteCount, _spritePoolLength = 0, + _modelMatrix; - _vector3 = new Vector3(), - _vector4 = new Vector4(), + const - _clipBox = new Box3( new Vector3( - 1, - 1, - 1 ), new Vector3( 1, 1, 1 ) ), - _boundingBox = new Box3(), - _points3 = new Array( 3 ), + _renderData = { objects: [], lights: [], elements: [] }, - _viewMatrix = new Matrix4(), - _viewProjectionMatrix = new Matrix4(), + _vector3 = new Vector3(), + _vector4 = new Vector4(), - _modelMatrix, - _modelViewProjectionMatrix = new Matrix4(), + _clipBox = new Box3( new Vector3( - 1, - 1, - 1 ), new Vector3( 1, 1, 1 ) ), + _boundingBox = new Box3(), + _points3 = new Array( 3 ), - _frustum = new Frustum(); + _viewMatrix = new Matrix4(), + _viewProjectionMatrix = new Matrix4(), - // + _modelViewProjectionMatrix = new Matrix4(), - this.projectVector = function ( vector, camera ) { + _frustum = new Frustum(), - console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); - vector.project( camera ); + _objectPool = [], _vertexPool = [], _facePool = [], _linePool = [], _spritePool = []; - }; + // - this.unprojectVector = function ( vector, camera ) { + this.projectVector = function ( vector, camera ) { - console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); - vector.unproject( camera ); + console.warn( 'THREE.Projector: .projectVector() is now vector.project().' ); + vector.project( camera ); - }; + }; - this.pickingRay = function () { + this.unprojectVector = function ( vector, camera ) { - console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' ); + console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' ); + vector.unproject( camera ); - }; + }; - // + this.pickingRay = function () { - var RenderList = function () { + console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' ); - var normals = []; - var colors = []; - var uvs = []; + }; - var object = null; + // - var normalMatrix = new Matrix3(); + function RenderList() { - function setObject( value ) { + const normals = []; + const colors = []; + const uvs = []; - object = value; + let object = null; - normalMatrix.getNormalMatrix( object.matrixWorld ); + const normalMatrix = new Matrix3(); - normals.length = 0; - colors.length = 0; - uvs.length = 0; + function setObject( value ) { - } + object = value; - function projectVertex( vertex ) { + normalMatrix.getNormalMatrix( object.matrixWorld ); - var position = vertex.position; - var positionWorld = vertex.positionWorld; - var positionScreen = vertex.positionScreen; + normals.length = 0; + colors.length = 0; + uvs.length = 0; - positionWorld.copy( position ).applyMatrix4( _modelMatrix ); - positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix ); + } - var invW = 1 / positionScreen.w; + function projectVertex( vertex ) { - positionScreen.x *= invW; - positionScreen.y *= invW; - positionScreen.z *= invW; + const position = vertex.position; + const positionWorld = vertex.positionWorld; + const positionScreen = vertex.positionScreen; - vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 && - positionScreen.y >= - 1 && positionScreen.y <= 1 && - positionScreen.z >= - 1 && positionScreen.z <= 1; + positionWorld.copy( position ).applyMatrix4( _modelMatrix ); + positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix ); - } + const invW = 1 / positionScreen.w; - function pushVertex( x, y, z ) { + positionScreen.x *= invW; + positionScreen.y *= invW; + positionScreen.z *= invW; - _vertex = getNextVertexInPool(); - _vertex.position.set( x, y, z ); + vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 && + positionScreen.y >= - 1 && positionScreen.y <= 1 && + positionScreen.z >= - 1 && positionScreen.z <= 1; - projectVertex( _vertex ); + } - } + function pushVertex( x, y, z ) { - function pushNormal( x, y, z ) { + _vertex = getNextVertexInPool(); + _vertex.position.set( x, y, z ); - normals.push( x, y, z ); + projectVertex( _vertex ); - } + } - function pushColor( r, g, b ) { + function pushNormal( x, y, z ) { - colors.push( r, g, b ); + normals.push( x, y, z ); - } + } - function pushUv( x, y ) { + function pushColor( r, g, b ) { - uvs.push( x, y ); + colors.push( r, g, b ); - } + } - function checkTriangleVisibility( v1, v2, v3 ) { + function pushUv( x, y ) { - if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true; + uvs.push( x, y ); - _points3[ 0 ] = v1.positionScreen; - _points3[ 1 ] = v2.positionScreen; - _points3[ 2 ] = v3.positionScreen; + } - return _clipBox.intersectsBox( _boundingBox.setFromPoints( _points3 ) ); + function checkTriangleVisibility( v1, v2, v3 ) { - } + if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true; - function checkBackfaceCulling( v1, v2, v3 ) { + _points3[ 0 ] = v1.positionScreen; + _points3[ 1 ] = v2.positionScreen; + _points3[ 2 ] = v3.positionScreen; - return ( ( v3.positionScreen.x - v1.positionScreen.x ) * - ( v2.positionScreen.y - v1.positionScreen.y ) - - ( v3.positionScreen.y - v1.positionScreen.y ) * - ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0; + return _clipBox.intersectsBox( _boundingBox.setFromPoints( _points3 ) ); - } + } - function pushLine( a, b ) { + function checkBackfaceCulling( v1, v2, v3 ) { - var v1 = _vertexPool[ a ]; - var v2 = _vertexPool[ b ]; + return ( ( v3.positionScreen.x - v1.positionScreen.x ) * + ( v2.positionScreen.y - v1.positionScreen.y ) - + ( v3.positionScreen.y - v1.positionScreen.y ) * + ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0; - // Clip + } - v1.positionScreen.copy( v1.position ).applyMatrix4( _modelViewProjectionMatrix ); - v2.positionScreen.copy( v2.position ).applyMatrix4( _modelViewProjectionMatrix ); + function pushLine( a, b ) { - if ( clipLine( v1.positionScreen, v2.positionScreen ) === true ) { + const v1 = _vertexPool[ a ]; + const v2 = _vertexPool[ b ]; - // Perform the perspective divide - v1.positionScreen.multiplyScalar( 1 / v1.positionScreen.w ); - v2.positionScreen.multiplyScalar( 1 / v2.positionScreen.w ); + // Clip - _line = getNextLineInPool(); - _line.id = object.id; - _line.v1.copy( v1 ); - _line.v2.copy( v2 ); - _line.z = Math.max( v1.positionScreen.z, v2.positionScreen.z ); - _line.renderOrder = object.renderOrder; + v1.positionScreen.copy( v1.position ).applyMatrix4( _modelViewProjectionMatrix ); + v2.positionScreen.copy( v2.position ).applyMatrix4( _modelViewProjectionMatrix ); - _line.material = object.material; + if ( clipLine( v1.positionScreen, v2.positionScreen ) === true ) { - if ( object.material.vertexColors ) { + // Perform the perspective divide + v1.positionScreen.multiplyScalar( 1 / v1.positionScreen.w ); + v2.positionScreen.multiplyScalar( 1 / v2.positionScreen.w ); - _line.vertexColors[ 0 ].fromArray( colors, a * 3 ); - _line.vertexColors[ 1 ].fromArray( colors, b * 3 ); + _line = getNextLineInPool(); + _line.id = object.id; + _line.v1.copy( v1 ); + _line.v2.copy( v2 ); + _line.z = Math.max( v1.positionScreen.z, v2.positionScreen.z ); + _line.renderOrder = object.renderOrder; - } + _line.material = object.material; + + if ( object.material.vertexColors ) { - _renderData.elements.push( _line ); + _line.vertexColors[ 0 ].fromArray( colors, a * 3 ); + _line.vertexColors[ 1 ].fromArray( colors, b * 3 ); + + } + + _renderData.elements.push( _line ); + + } } - } + function pushTriangle( a, b, c, material ) { - function pushTriangle( a, b, c, material ) { + const v1 = _vertexPool[ a ]; + const v2 = _vertexPool[ b ]; + const v3 = _vertexPool[ c ]; - var v1 = _vertexPool[ a ]; - var v2 = _vertexPool[ b ]; - var v3 = _vertexPool[ c ]; + if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return; - if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return; + if ( material.side === DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) { - if ( material.side === DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) { + _face = getNextFaceInPool(); - _face = getNextFaceInPool(); + _face.id = object.id; + _face.v1.copy( v1 ); + _face.v2.copy( v2 ); + _face.v3.copy( v3 ); + _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3; + _face.renderOrder = object.renderOrder; - _face.id = object.id; - _face.v1.copy( v1 ); - _face.v2.copy( v2 ); - _face.v3.copy( v3 ); - _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3; - _face.renderOrder = object.renderOrder; + // face normal + _vector3.subVectors( v3.position, v2.position ); + _vector4.subVectors( v1.position, v2.position ); + _vector3.cross( _vector4 ); + _face.normalModel.copy( _vector3 ); + _face.normalModel.applyMatrix3( normalMatrix ).normalize(); - // face normal - _vector3.subVectors( v3.position, v2.position ); - _vector4.subVectors( v1.position, v2.position ); - _vector3.cross( _vector4 ); - _face.normalModel.copy( _vector3 ); - _face.normalModel.applyMatrix3( normalMatrix ).normalize(); + for ( let i = 0; i < 3; i ++ ) { - for ( var i = 0; i < 3; i ++ ) { + const normal = _face.vertexNormalsModel[ i ]; + normal.fromArray( normals, arguments[ i ] * 3 ); + normal.applyMatrix3( normalMatrix ).normalize(); - var normal = _face.vertexNormalsModel[ i ]; - normal.fromArray( normals, arguments[ i ] * 3 ); - normal.applyMatrix3( normalMatrix ).normalize(); + const uv = _face.uvs[ i ]; + uv.fromArray( uvs, arguments[ i ] * 2 ); - var uv = _face.uvs[ i ]; - uv.fromArray( uvs, arguments[ i ] * 2 ); + } - } + _face.vertexNormalsLength = 3; - _face.vertexNormalsLength = 3; + _face.material = material; - _face.material = material; + if ( material.vertexColors ) { - if ( material.vertexColors ) { + _face.color.fromArray( colors, a * 3 ); - _face.color.fromArray( colors, a * 3 ); + } - } + _renderData.elements.push( _face ); - _renderData.elements.push( _face ); + } } - } + return { + setObject: setObject, + projectVertex: projectVertex, + checkTriangleVisibility: checkTriangleVisibility, + checkBackfaceCulling: checkBackfaceCulling, + pushVertex: pushVertex, + pushNormal: pushNormal, + pushColor: pushColor, + pushUv: pushUv, + pushLine: pushLine, + pushTriangle: pushTriangle + }; - return { - setObject: setObject, - projectVertex: projectVertex, - checkTriangleVisibility: checkTriangleVisibility, - checkBackfaceCulling: checkBackfaceCulling, - pushVertex: pushVertex, - pushNormal: pushNormal, - pushColor: pushColor, - pushUv: pushUv, - pushLine: pushLine, - pushTriangle: pushTriangle }; - }; + const renderList = new RenderList(); - var renderList = new RenderList(); + function projectObject( object ) { - function projectObject( object ) { + if ( object.visible === false ) return; - if ( object.visible === false ) return; + if ( object.isLight ) { - if ( object.isLight ) { + _renderData.lights.push( object ); - _renderData.lights.push( object ); + } else if ( object.isMesh || object.isLine || object.isPoints ) { - } else if ( object.isMesh || object.isLine || object.isPoints ) { + if ( object.material.visible === false ) return; + if ( object.frustumCulled === true && _frustum.intersectsObject( object ) === false ) return; - if ( object.material.visible === false ) return; - if ( object.frustumCulled === true && _frustum.intersectsObject( object ) === false ) return; + addObject( object ); - addObject( object ); + } else if ( object.isSprite ) { - } else if ( object.isSprite ) { + if ( object.material.visible === false ) return; + if ( object.frustumCulled === true && _frustum.intersectsSprite( object ) === false ) return; - if ( object.material.visible === false ) return; - if ( object.frustumCulled === true && _frustum.intersectsSprite( object ) === false ) return; + addObject( object ); - addObject( object ); + } - } + const children = object.children; - var children = object.children; + for ( let i = 0, l = children.length; i < l; i ++ ) { - for ( var i = 0, l = children.length; i < l; i ++ ) { + projectObject( children[ i ] ); - projectObject( children[ i ] ); + } } - } + function addObject( object ) { - function addObject( object ) { + _object = getNextObjectInPool(); + _object.id = object.id; + _object.object = object; - _object = getNextObjectInPool(); - _object.id = object.id; - _object.object = object; + _vector3.setFromMatrixPosition( object.matrixWorld ); + _vector3.applyMatrix4( _viewProjectionMatrix ); + _object.z = _vector3.z; + _object.renderOrder = object.renderOrder; - _vector3.setFromMatrixPosition( object.matrixWorld ); - _vector3.applyMatrix4( _viewProjectionMatrix ); - _object.z = _vector3.z; - _object.renderOrder = object.renderOrder; + _renderData.objects.push( _object ); - _renderData.objects.push( _object ); + } - } + this.projectScene = function ( scene, camera, sortObjects, sortElements ) { - this.projectScene = function ( scene, camera, sortObjects, sortElements ) { + _faceCount = 0; + _lineCount = 0; + _spriteCount = 0; - _faceCount = 0; - _lineCount = 0; - _spriteCount = 0; + _renderData.elements.length = 0; - _renderData.elements.length = 0; + if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); + if ( camera.parent === null ) camera.updateMatrixWorld(); - if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); - if ( camera.parent === null ) camera.updateMatrixWorld(); + _viewMatrix.copy( camera.matrixWorldInverse ); + _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); - _viewMatrix.copy( camera.matrixWorldInverse ); - _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); + _frustum.setFromProjectionMatrix( _viewProjectionMatrix ); - _frustum.setFromProjectionMatrix( _viewProjectionMatrix ); + // - // + _objectCount = 0; - _objectCount = 0; + _renderData.objects.length = 0; + _renderData.lights.length = 0; - _renderData.objects.length = 0; - _renderData.lights.length = 0; + projectObject( scene ); - projectObject( scene ); + if ( sortObjects === true ) { - if ( sortObjects === true ) { + _renderData.objects.sort( painterSort ); - _renderData.objects.sort( painterSort ); + } - } + // - // + const objects = _renderData.objects; - var objects = _renderData.objects; + for ( let o = 0, ol = objects.length; o < ol; o ++ ) { - for ( var o = 0, ol = objects.length; o < ol; o ++ ) { + const object = objects[ o ].object; + const geometry = object.geometry; - var object = objects[ o ].object; - var geometry = object.geometry; + renderList.setObject( object ); - renderList.setObject( object ); + _modelMatrix = object.matrixWorld; - _modelMatrix = object.matrixWorld; + _vertexCount = 0; - _vertexCount = 0; + if ( object.isMesh ) { - if ( object.isMesh ) { + if ( geometry.isBufferGeometry ) { - if ( geometry.isBufferGeometry ) { + let material = object.material; - var material = object.material; + const isMultiMaterial = Array.isArray( material ); - var isMultiMaterial = Array.isArray( material ); + const attributes = geometry.attributes; + const groups = geometry.groups; - var attributes = geometry.attributes; - var groups = geometry.groups; + if ( attributes.position === undefined ) continue; - if ( attributes.position === undefined ) continue; + const positions = attributes.position.array; - var positions = attributes.position.array; + for ( let i = 0, l = positions.length; i < l; i += 3 ) { - for ( var i = 0, l = positions.length; i < l; i += 3 ) { + let x = positions[ i ]; + let y = positions[ i + 1 ]; + let z = positions[ i + 2 ]; - var x = positions[ i ]; - var y = positions[ i + 1 ]; - var z = positions[ i + 2 ]; + if ( material.morphTargets === true ) { - if ( material.morphTargets === true ) { + const morphTargets = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; + const morphInfluences = object.morphTargetInfluences; - var morphTargets = geometry.morphAttributes.position; - var morphTargetsRelative = geometry.morphTargetsRelative; - var morphInfluences = object.morphTargetInfluences; + for ( let t = 0, tl = morphTargets.length; t < tl; t ++ ) { - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { + const influence = morphInfluences[ t ]; - var influence = morphInfluences[ t ]; + if ( influence === 0 ) continue; - if ( influence === 0 ) continue; + const target = morphTargets[ t ]; - var target = morphTargets[ t ]; + if ( morphTargetsRelative ) { - if ( morphTargetsRelative ) { + x += target.getX( i / 3 ) * influence; + y += target.getY( i / 3 ) * influence; + z += target.getZ( i / 3 ) * influence; - x += target.getX( i / 3 ) * influence; - y += target.getY( i / 3 ) * influence; - z += target.getZ( i / 3 ) * influence; + } else { - } else { + x += ( target.getX( i / 3 ) - positions[ i ] ) * influence; + y += ( target.getY( i / 3 ) - positions[ i + 1 ] ) * influence; + z += ( target.getZ( i / 3 ) - positions[ i + 2 ] ) * influence; - x += ( target.getX( i / 3 ) - positions[ i ] ) * influence; - y += ( target.getY( i / 3 ) - positions[ i + 1 ] ) * influence; - z += ( target.getZ( i / 3 ) - positions[ i + 2 ] ) * influence; + } } } - } + renderList.pushVertex( x, y, z ); - renderList.pushVertex( x, y, z ); + } - } + if ( attributes.normal !== undefined ) { - if ( attributes.normal !== undefined ) { + const normals = attributes.normal.array; - var normals = attributes.normal.array; + for ( let i = 0, l = normals.length; i < l; i += 3 ) { - for ( var i = 0, l = normals.length; i < l; i += 3 ) { + renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ); - renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ); + } } - } + if ( attributes.color !== undefined ) { - if ( attributes.color !== undefined ) { + const colors = attributes.color.array; - var colors = attributes.color.array; + for ( let i = 0, l = colors.length; i < l; i += 3 ) { - for ( var i = 0, l = colors.length; i < l; i += 3 ) { + renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ); - renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ); + } } - } + if ( attributes.uv !== undefined ) { - if ( attributes.uv !== undefined ) { + const uvs = attributes.uv.array; - var uvs = attributes.uv.array; + for ( let i = 0, l = uvs.length; i < l; i += 2 ) { - for ( var i = 0, l = uvs.length; i < l; i += 2 ) { + renderList.pushUv( uvs[ i ], uvs[ i + 1 ] ); - renderList.pushUv( uvs[ i ], uvs[ i + 1 ] ); + } } - } + if ( geometry.index !== null ) { - if ( geometry.index !== null ) { + const indices = geometry.index.array; - var indices = geometry.index.array; + if ( groups.length > 0 ) { - if ( groups.length > 0 ) { + for ( let g = 0; g < groups.length; g ++ ) { - for ( var g = 0; g < groups.length; g ++ ) { + const group = groups[ g ]; - var group = groups[ g ]; + material = isMultiMaterial === true + ? object.material[ group.materialIndex ] + : object.material; - material = isMultiMaterial === true - ? object.material[ group.materialIndex ] - : object.material; + if ( material === undefined ) continue; - if ( material === undefined ) continue; + for ( let i = group.start, l = group.start + group.count; i < l; i += 3 ) { - for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) { + renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material ); - renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material ); + } } - } + } else { - } else { + for ( let i = 0, l = indices.length; i < l; i += 3 ) { - for ( var i = 0, l = indices.length; i < l; i += 3 ) { + renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material ); - renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ], material ); + } } - } + } else { - } else { + if ( groups.length > 0 ) { - if ( groups.length > 0 ) { + for ( let g = 0; g < groups.length; g ++ ) { - for ( var g = 0; g < groups.length; g ++ ) { + const group = groups[ g ]; - var group = groups[ g ]; + material = isMultiMaterial === true + ? object.material[ group.materialIndex ] + : object.material; - material = isMultiMaterial === true - ? object.material[ group.materialIndex ] - : object.material; + if ( material === undefined ) continue; - if ( material === undefined ) continue; + for ( let i = group.start, l = group.start + group.count; i < l; i += 3 ) { - for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) { + renderList.pushTriangle( i, i + 1, i + 2, material ); - renderList.pushTriangle( i, i + 1, i + 2, material ); + } } - } + } else { - } else { + for ( let i = 0, l = positions.length / 3; i < l; i += 3 ) { - for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) { + renderList.pushTriangle( i, i + 1, i + 2, material ); - renderList.pushTriangle( i, i + 1, i + 2, material ); + } } } - } + } else if ( geometry.isGeometry ) { - } else if ( geometry.isGeometry ) { + console.error( 'THREE.Projector no longer supports Geometry. Use THREE.BufferGeometry instead.' ); + return; - console.error( 'THREE.Projector no longer supports Geometry. Use THREE.BufferGeometry instead.' ); - return; + } - } + } else if ( object.isLine ) { - } else if ( object.isLine ) { + _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix ); - _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix ); + if ( geometry.isBufferGeometry ) { - if ( geometry.isBufferGeometry ) { + const attributes = geometry.attributes; - var attributes = geometry.attributes; + if ( attributes.position !== undefined ) { - if ( attributes.position !== undefined ) { + const positions = attributes.position.array; - var positions = attributes.position.array; + for ( let i = 0, l = positions.length; i < l; i += 3 ) { - for ( var i = 0, l = positions.length; i < l; i += 3 ) { + renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ); - renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ); + } - } + if ( attributes.color !== undefined ) { - if ( attributes.color !== undefined ) { + const colors = attributes.color.array; - var colors = attributes.color.array; + for ( let i = 0, l = colors.length; i < l; i += 3 ) { - for ( var i = 0, l = colors.length; i < l; i += 3 ) { + renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ); - renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ); + } } - } + if ( geometry.index !== null ) { - if ( geometry.index !== null ) { + const indices = geometry.index.array; - var indices = geometry.index.array; + for ( let i = 0, l = indices.length; i < l; i += 2 ) { - for ( var i = 0, l = indices.length; i < l; i += 2 ) { + renderList.pushLine( indices[ i ], indices[ i + 1 ] ); - renderList.pushLine( indices[ i ], indices[ i + 1 ] ); + } - } + } else { - } else { + const step = object.isLineSegments ? 2 : 1; - var step = object.isLineSegments ? 2 : 1; + for ( let i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) { - for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) { + renderList.pushLine( i, i + 1 ); - renderList.pushLine( i, i + 1 ); + } } } - } + } else if ( geometry.isGeometry ) { - } else if ( geometry.isGeometry ) { + console.error( 'THREE.Projector no longer supports Geometry. Use THREE.BufferGeometry instead.' ); + return; - console.error( 'THREE.Projector no longer supports Geometry. Use THREE.BufferGeometry instead.' ); - return; + } - } + } else if ( object.isPoints ) { - } else if ( object.isPoints ) { + _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix ); - _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix ); + if ( geometry.isGeometry ) { - if ( geometry.isGeometry ) { + console.error( 'THREE.Projector no longer supports Geometry. Use THREE.BufferGeometry instead.' ); + return; - console.error( 'THREE.Projector no longer supports Geometry. Use THREE.BufferGeometry instead.' ); - return; + } else if ( geometry.isBufferGeometry ) { - } else if ( geometry.isBufferGeometry ) { + const attributes = geometry.attributes; - var attributes = geometry.attributes; + if ( attributes.position !== undefined ) { - if ( attributes.position !== undefined ) { + const positions = attributes.position.array; - var positions = attributes.position.array; + for ( let i = 0, l = positions.length; i < l; i += 3 ) { - for ( var i = 0, l = positions.length; i < l; i += 3 ) { + _vector4.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ], 1 ); + _vector4.applyMatrix4( _modelViewProjectionMatrix ); - _vector4.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ], 1 ); - _vector4.applyMatrix4( _modelViewProjectionMatrix ); + pushPoint( _vector4, object, camera ); - pushPoint( _vector4, object, camera ); + } } } - } + } else if ( object.isSprite ) { - } else if ( object.isSprite ) { + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + _vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 ); + _vector4.applyMatrix4( _viewProjectionMatrix ); - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - _vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 ); - _vector4.applyMatrix4( _viewProjectionMatrix ); + pushPoint( _vector4, object, camera ); - pushPoint( _vector4, object, camera ); + } } - } + if ( sortElements === true ) { - if ( sortElements === true ) { + _renderData.elements.sort( painterSort ); - _renderData.elements.sort( painterSort ); + } - } + return _renderData; - return _renderData; + }; - }; + function pushPoint( _vector4, object, camera ) { - function pushPoint( _vector4, object, camera ) { + const invW = 1 / _vector4.w; - var invW = 1 / _vector4.w; + _vector4.z *= invW; - _vector4.z *= invW; + if ( _vector4.z >= - 1 && _vector4.z <= 1 ) { - if ( _vector4.z >= - 1 && _vector4.z <= 1 ) { + _sprite = getNextSpriteInPool(); + _sprite.id = object.id; + _sprite.x = _vector4.x * invW; + _sprite.y = _vector4.y * invW; + _sprite.z = _vector4.z; + _sprite.renderOrder = object.renderOrder; + _sprite.object = object; - _sprite = getNextSpriteInPool(); - _sprite.id = object.id; - _sprite.x = _vector4.x * invW; - _sprite.y = _vector4.y * invW; - _sprite.z = _vector4.z; - _sprite.renderOrder = object.renderOrder; - _sprite.object = object; + _sprite.rotation = object.rotation; - _sprite.rotation = object.rotation; + _sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) ); + _sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) ); - _sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) ); - _sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) ); + _sprite.material = object.material; - _sprite.material = object.material; + _renderData.elements.push( _sprite ); - _renderData.elements.push( _sprite ); + } } - } + // Pools - // Pools + function getNextObjectInPool() { - function getNextObjectInPool() { + if ( _objectCount === _objectPoolLength ) { - if ( _objectCount === _objectPoolLength ) { + const object = new RenderableObject(); + _objectPool.push( object ); + _objectPoolLength ++; + _objectCount ++; + return object; - var object = new RenderableObject(); - _objectPool.push( object ); - _objectPoolLength ++; - _objectCount ++; - return object; + } + + return _objectPool[ _objectCount ++ ]; } - return _objectPool[ _objectCount ++ ]; + function getNextVertexInPool() { - } + if ( _vertexCount === _vertexPoolLength ) { - function getNextVertexInPool() { + const vertex = new RenderableVertex(); + _vertexPool.push( vertex ); + _vertexPoolLength ++; + _vertexCount ++; + return vertex; - if ( _vertexCount === _vertexPoolLength ) { + } - var vertex = new RenderableVertex(); - _vertexPool.push( vertex ); - _vertexPoolLength ++; - _vertexCount ++; - return vertex; + return _vertexPool[ _vertexCount ++ ]; } - return _vertexPool[ _vertexCount ++ ]; + function getNextFaceInPool() { - } + if ( _faceCount === _facePoolLength ) { - function getNextFaceInPool() { + const face = new RenderableFace(); + _facePool.push( face ); + _facePoolLength ++; + _faceCount ++; + return face; - if ( _faceCount === _facePoolLength ) { + } - var face = new RenderableFace(); - _facePool.push( face ); - _facePoolLength ++; - _faceCount ++; - return face; + return _facePool[ _faceCount ++ ]; - } - return _facePool[ _faceCount ++ ]; + } + function getNextLineInPool() { - } + if ( _lineCount === _linePoolLength ) { - function getNextLineInPool() { + const line = new RenderableLine(); + _linePool.push( line ); + _linePoolLength ++; + _lineCount ++; + return line; - if ( _lineCount === _linePoolLength ) { + } - var line = new RenderableLine(); - _linePool.push( line ); - _linePoolLength ++; - _lineCount ++; - return line; + return _linePool[ _lineCount ++ ]; } - return _linePool[ _lineCount ++ ]; + function getNextSpriteInPool() { - } + if ( _spriteCount === _spritePoolLength ) { - function getNextSpriteInPool() { + const sprite = new RenderableSprite(); + _spritePool.push( sprite ); + _spritePoolLength ++; + _spriteCount ++; + return sprite; - if ( _spriteCount === _spritePoolLength ) { + } - var sprite = new RenderableSprite(); - _spritePool.push( sprite ); - _spritePoolLength ++; - _spriteCount ++; - return sprite; + return _spritePool[ _spriteCount ++ ]; } - return _spritePool[ _spriteCount ++ ]; - - } + // - // + function painterSort( a, b ) { - function painterSort( a, b ) { + if ( a.renderOrder !== b.renderOrder ) { - if ( a.renderOrder !== b.renderOrder ) { + return a.renderOrder - b.renderOrder; - return a.renderOrder - b.renderOrder; + } else if ( a.z !== b.z ) { - } else if ( a.z !== b.z ) { + return b.z - a.z; - return b.z - a.z; + } else if ( a.id !== b.id ) { - } else if ( a.id !== b.id ) { + return a.id - b.id; - return a.id - b.id; + } else { - } else { + return 0; - return 0; + } } - } + function clipLine( s1, s2 ) { - function clipLine( s1, s2 ) { - - var alpha1 = 0, alpha2 = 1, + let alpha1 = 0, alpha2 = 1; // Calculate the boundary coordinate of each vertex for the near and far clip planes, // Z = -1 and Z = +1, respectively. - bc1near = s1.z + s1.w, - bc2near = s2.z + s2.w, - bc1far = - s1.z + s1.w, - bc2far = - s2.z + s2.w; + const bc1near = s1.z + s1.w, + bc2near = s2.z + s2.w, + bc1far = - s1.z + s1.w, + bc2far = - s2.z + s2.w; + + if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) { - if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) { + // Both vertices lie entirely within all clip planes. + return true; - // Both vertices lie entirely within all clip planes. - return true; + } else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) { - } else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) { + // Both vertices lie entirely outside one of the clip planes. + return false; - // Both vertices lie entirely outside one of the clip planes. - return false; + } else { - } else { + // The line segment spans at least one clip plane. - // The line segment spans at least one clip plane. + if ( bc1near < 0 ) { - if ( bc1near < 0 ) { + // v1 lies outside the near plane, v2 inside + alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) ); - // v1 lies outside the near plane, v2 inside - alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) ); + } else if ( bc2near < 0 ) { - } else if ( bc2near < 0 ) { + // v2 lies outside the near plane, v1 inside + alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) ); - // v2 lies outside the near plane, v1 inside - alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) ); + } - } + if ( bc1far < 0 ) { - if ( bc1far < 0 ) { + // v1 lies outside the far plane, v2 inside + alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) ); - // v1 lies outside the far plane, v2 inside - alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) ); + } else if ( bc2far < 0 ) { - } else if ( bc2far < 0 ) { + // v2 lies outside the far plane, v2 inside + alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) ); - // v2 lies outside the far plane, v2 inside - alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) ); + } - } + if ( alpha2 < alpha1 ) { - if ( alpha2 < alpha1 ) { + // The line segment spans two boundaries, but is outside both of them. + // (This can't happen when we're only clipping against just near/far but good + // to leave the check here for future usage if other clip planes are added.) + return false; - // The line segment spans two boundaries, but is outside both of them. - // (This can't happen when we're only clipping against just near/far but good - // to leave the check here for future usage if other clip planes are added.) - return false; + } else { - } else { + // Update the s1 and s2 vertices to match the clipped line segment. + s1.lerp( s2, alpha1 ); + s2.lerp( s1, 1 - alpha2 ); - // Update the s1 and s2 vertices to match the clipped line segment. - s1.lerp( s2, alpha1 ); - s2.lerp( s1, 1 - alpha2 ); + return true; - return true; + } } @@ -933,6 +961,6 @@ var Projector = function () { } -}; +} export { RenderableObject, RenderableFace, RenderableVertex, RenderableLine, RenderableSprite, Projector }; diff --git a/examples/jsm/renderers/SVGRenderer.js b/examples/jsm/renderers/SVGRenderer.js index 2c896783d24b36..c76c5cf18b1a71 100644 --- a/examples/jsm/renderers/SVGRenderer.js +++ b/examples/jsm/renderers/SVGRenderer.js @@ -12,520 +12,533 @@ import { RenderableFace } from '../renderers/Projector.js'; import { RenderableLine } from '../renderers/Projector.js'; import { RenderableSprite } from '../renderers/Projector.js'; -var SVGObject = function ( node ) { +class SVGObject extends Object3D { - Object3D.call( this ); + constructor( node ) { - this.node = node; + super(); -}; + this.node = node; -SVGObject.prototype = Object.create( Object3D.prototype ); -SVGObject.prototype.constructor = SVGObject; + } -var SVGRenderer = function () { +} - var _this = this, - _renderData, _elements, _lights, - _projector = new Projector(), - _svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ), - _svgWidth, _svgHeight, _svgWidthHalf, _svgHeightHalf, +SVGObject.prototype.isSVGObject = true; - _v1, _v2, _v3, +class SVGRenderer { - _clipBox = new Box2(), - _elemBox = new Box2(), + constructor() { - _color = new Color(), - _diffuseColor = new Color(), - _ambientLight = new Color(), - _directionalLights = new Color(), - _pointLights = new Color(), - _clearColor = new Color(), + let _renderData, _elements, _lights, + _svgWidth, _svgHeight, _svgWidthHalf, _svgHeightHalf, - _vector3 = new Vector3(), // Needed for PointLight - _centroid = new Vector3(), - _normal = new Vector3(), - _normalViewMatrix = new Matrix3(), + _v1, _v2, _v3, - _viewMatrix = new Matrix4(), - _viewProjectionMatrix = new Matrix4(), + _svgNode, + _pathCount = 0, - _svgPathPool = [], - _svgNode, _pathCount = 0, + _precision = null, + _quality = 1, - _currentPath, _currentStyle, + _currentPath, _currentStyle; - _quality = 1, _precision = null; + const _this = this, + _clipBox = new Box2(), + _elemBox = new Box2(), - this.domElement = _svg; + _color = new Color(), + _diffuseColor = new Color(), + _ambientLight = new Color(), + _directionalLights = new Color(), + _pointLights = new Color(), + _clearColor = new Color(), - this.autoClear = true; - this.sortObjects = true; - this.sortElements = true; + _vector3 = new Vector3(), // Needed for PointLight + _centroid = new Vector3(), + _normal = new Vector3(), + _normalViewMatrix = new Matrix3(), - this.overdraw = 0.5; + _viewMatrix = new Matrix4(), + _viewProjectionMatrix = new Matrix4(), - this.info = { + _svgPathPool = [], - render: { + _projector = new Projector(), + _svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ); - vertices: 0, - faces: 0 + this.domElement = _svg; - } + this.autoClear = true; + this.sortObjects = true; + this.sortElements = true; - }; + this.overdraw = 0.5; - this.setQuality = function ( quality ) { + this.info = { - switch ( quality ) { + render: { - case 'high': _quality = 1; break; - case 'low': _quality = 0; break; + vertices: 0, + faces: 0 - } + } - }; + }; - this.setClearColor = function ( color ) { + this.setQuality = function ( quality ) { - _clearColor.set( color ); + switch ( quality ) { - }; + case 'high': _quality = 1; break; + case 'low': _quality = 0; break; - this.setPixelRatio = function () {}; + } + + }; - this.setSize = function ( width, height ) { + this.setClearColor = function ( color ) { - _svgWidth = width; _svgHeight = height; - _svgWidthHalf = _svgWidth / 2; _svgHeightHalf = _svgHeight / 2; + _clearColor.set( color ); - _svg.setAttribute( 'viewBox', ( - _svgWidthHalf ) + ' ' + ( - _svgHeightHalf ) + ' ' + _svgWidth + ' ' + _svgHeight ); - _svg.setAttribute( 'width', _svgWidth ); - _svg.setAttribute( 'height', _svgHeight ); + }; - _clipBox.min.set( - _svgWidthHalf, - _svgHeightHalf ); - _clipBox.max.set( _svgWidthHalf, _svgHeightHalf ); + this.setPixelRatio = function () {}; - }; + this.setSize = function ( width, height ) { - this.getSize = function () { + _svgWidth = width; _svgHeight = height; + _svgWidthHalf = _svgWidth / 2; _svgHeightHalf = _svgHeight / 2; + + _svg.setAttribute( 'viewBox', ( - _svgWidthHalf ) + ' ' + ( - _svgHeightHalf ) + ' ' + _svgWidth + ' ' + _svgHeight ); + _svg.setAttribute( 'width', _svgWidth ); + _svg.setAttribute( 'height', _svgHeight ); + + _clipBox.min.set( - _svgWidthHalf, - _svgHeightHalf ); + _clipBox.max.set( _svgWidthHalf, _svgHeightHalf ); + + }; + + this.getSize = function () { + + return { + width: _svgWidth, + height: _svgHeight + }; - return { - width: _svgWidth, - height: _svgHeight }; - }; + this.setPrecision = function ( precision ) { - this.setPrecision = function ( precision ) { + _precision = precision; - _precision = precision; + }; - }; + function removeChildNodes() { - function removeChildNodes() { + _pathCount = 0; - _pathCount = 0; + while ( _svg.childNodes.length > 0 ) { - while ( _svg.childNodes.length > 0 ) { + _svg.removeChild( _svg.childNodes[ 0 ] ); - _svg.removeChild( _svg.childNodes[ 0 ] ); + } } - } + function convert( c ) { - function convert( c ) { + return _precision !== null ? c.toFixed( _precision ) : c; - return _precision !== null ? c.toFixed( _precision ) : c; + } - } + this.clear = function () { - this.clear = function () { + removeChildNodes(); + _svg.style.backgroundColor = _clearColor.getStyle(); - removeChildNodes(); - _svg.style.backgroundColor = _clearColor.getStyle(); + }; - }; + this.render = function ( scene, camera ) { - this.render = function ( scene, camera ) { + if ( camera instanceof Camera === false ) { - if ( camera instanceof Camera === false ) { + console.error( 'THREE.SVGRenderer.render: camera is not an instance of Camera.' ); + return; - console.error( 'THREE.SVGRenderer.render: camera is not an instance of Camera.' ); - return; + } - } + const background = scene.background; - var background = scene.background; + if ( background && background.isColor ) { - if ( background && background.isColor ) { + removeChildNodes(); + _svg.style.backgroundColor = background.getStyle(); - removeChildNodes(); - _svg.style.backgroundColor = background.getStyle(); + } else if ( this.autoClear === true ) { - } else if ( this.autoClear === true ) { + this.clear(); - this.clear(); + } - } + _this.info.render.vertices = 0; + _this.info.render.faces = 0; - _this.info.render.vertices = 0; - _this.info.render.faces = 0; + _viewMatrix.copy( camera.matrixWorldInverse ); + _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); - _viewMatrix.copy( camera.matrixWorldInverse ); - _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix ); + _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements ); + _elements = _renderData.elements; + _lights = _renderData.lights; - _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements ); - _elements = _renderData.elements; - _lights = _renderData.lights; + _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse ); - _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse ); + calculateLights( _lights ); - calculateLights( _lights ); + // reset accumulated path - // reset accumulated path + _currentPath = ''; + _currentStyle = ''; - _currentPath = ''; - _currentStyle = ''; + for ( let e = 0, el = _elements.length; e < el; e ++ ) { - for ( var e = 0, el = _elements.length; e < el; e ++ ) { + const element = _elements[ e ]; + const material = element.material; - var element = _elements[ e ]; - var material = element.material; + if ( material === undefined || material.opacity === 0 ) continue; - if ( material === undefined || material.opacity === 0 ) continue; + _elemBox.makeEmpty(); - _elemBox.makeEmpty(); + if ( element instanceof RenderableSprite ) { - if ( element instanceof RenderableSprite ) { + _v1 = element; + _v1.x *= _svgWidthHalf; _v1.y *= - _svgHeightHalf; - _v1 = element; - _v1.x *= _svgWidthHalf; _v1.y *= - _svgHeightHalf; + renderSprite( _v1, element, material ); - renderSprite( _v1, element, material ); + } else if ( element instanceof RenderableLine ) { - } else if ( element instanceof RenderableLine ) { + _v1 = element.v1; _v2 = element.v2; - _v1 = element.v1; _v2 = element.v2; + _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; + _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; + _elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen ] ); - _elemBox.setFromPoints( [ _v1.positionScreen, _v2.positionScreen ] ); + if ( _clipBox.intersectsBox( _elemBox ) === true ) { - if ( _clipBox.intersectsBox( _elemBox ) === true ) { + renderLine( _v1, _v2, element, material ); - renderLine( _v1, _v2, element, material ); + } - } + } else if ( element instanceof RenderableFace ) { - } else if ( element instanceof RenderableFace ) { + _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; - _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; + if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue; + if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue; + if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue; - if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue; - if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue; - if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue; + _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; + _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; + _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf; - _v1.positionScreen.x *= _svgWidthHalf; _v1.positionScreen.y *= - _svgHeightHalf; - _v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf; - _v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf; + if ( this.overdraw > 0 ) { - if ( this.overdraw > 0 ) { + expand( _v1.positionScreen, _v2.positionScreen, this.overdraw ); + expand( _v2.positionScreen, _v3.positionScreen, this.overdraw ); + expand( _v3.positionScreen, _v1.positionScreen, this.overdraw ); - expand( _v1.positionScreen, _v2.positionScreen, this.overdraw ); - expand( _v2.positionScreen, _v3.positionScreen, this.overdraw ); - expand( _v3.positionScreen, _v1.positionScreen, this.overdraw ); + } - } + _elemBox.setFromPoints( [ + _v1.positionScreen, + _v2.positionScreen, + _v3.positionScreen + ] ); - _elemBox.setFromPoints( [ - _v1.positionScreen, - _v2.positionScreen, - _v3.positionScreen - ] ); + if ( _clipBox.intersectsBox( _elemBox ) === true ) { - if ( _clipBox.intersectsBox( _elemBox ) === true ) { + renderFace3( _v1, _v2, _v3, element, material ); - renderFace3( _v1, _v2, _v3, element, material ); + } } } - } + flushPath(); // just to flush last svg:path - flushPath(); // just to flush last svg:path + scene.traverseVisible( function ( object ) { - scene.traverseVisible( function ( object ) { + if ( object.isSVGObject ) { - if ( object instanceof SVGObject ) { + _vector3.setFromMatrixPosition( object.matrixWorld ); + _vector3.applyMatrix4( _viewProjectionMatrix ); - _vector3.setFromMatrixPosition( object.matrixWorld ); - _vector3.applyMatrix4( _viewProjectionMatrix ); + if ( _vector3.z < - 1 || _vector3.z > 1 ) return; - if ( _vector3.z < - 1 || _vector3.z > 1 ) return; + const x = _vector3.x * _svgWidthHalf; + const y = - _vector3.y * _svgHeightHalf; - var x = _vector3.x * _svgWidthHalf; - var y = - _vector3.y * _svgHeightHalf; + const node = object.node; + node.setAttribute( 'transform', 'translate(' + x + ',' + y + ')' ); - var node = object.node; - node.setAttribute( 'transform', 'translate(' + x + ',' + y + ')' ); + _svg.appendChild( node ); - _svg.appendChild( node ); + } - } + } ); - } ); + }; - }; + function calculateLights( lights ) { - function calculateLights( lights ) { + _ambientLight.setRGB( 0, 0, 0 ); + _directionalLights.setRGB( 0, 0, 0 ); + _pointLights.setRGB( 0, 0, 0 ); - _ambientLight.setRGB( 0, 0, 0 ); - _directionalLights.setRGB( 0, 0, 0 ); - _pointLights.setRGB( 0, 0, 0 ); + for ( let l = 0, ll = lights.length; l < ll; l ++ ) { - for ( var l = 0, ll = lights.length; l < ll; l ++ ) { + const light = lights[ l ]; + const lightColor = light.color; - var light = lights[ l ]; - var lightColor = light.color; + if ( light.isAmbientLight ) { - if ( light.isAmbientLight ) { + _ambientLight.r += lightColor.r; + _ambientLight.g += lightColor.g; + _ambientLight.b += lightColor.b; - _ambientLight.r += lightColor.r; - _ambientLight.g += lightColor.g; - _ambientLight.b += lightColor.b; + } else if ( light.isDirectionalLight ) { - } else if ( light.isDirectionalLight ) { + _directionalLights.r += lightColor.r; + _directionalLights.g += lightColor.g; + _directionalLights.b += lightColor.b; - _directionalLights.r += lightColor.r; - _directionalLights.g += lightColor.g; - _directionalLights.b += lightColor.b; + } else if ( light.isPointLight ) { - } else if ( light.isPointLight ) { + _pointLights.r += lightColor.r; + _pointLights.g += lightColor.g; + _pointLights.b += lightColor.b; - _pointLights.r += lightColor.r; - _pointLights.g += lightColor.g; - _pointLights.b += lightColor.b; + } } } - } + function calculateLight( lights, position, normal, color ) { - function calculateLight( lights, position, normal, color ) { + for ( let l = 0, ll = lights.length; l < ll; l ++ ) { - for ( var l = 0, ll = lights.length; l < ll; l ++ ) { + const light = lights[ l ]; + const lightColor = light.color; - var light = lights[ l ]; - var lightColor = light.color; + if ( light.isDirectionalLight ) { - if ( light.isDirectionalLight ) { + const lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize(); - var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize(); + let amount = normal.dot( lightPosition ); - var amount = normal.dot( lightPosition ); + if ( amount <= 0 ) continue; - if ( amount <= 0 ) continue; + amount *= light.intensity; - amount *= light.intensity; + color.r += lightColor.r * amount; + color.g += lightColor.g * amount; + color.b += lightColor.b * amount; - color.r += lightColor.r * amount; - color.g += lightColor.g * amount; - color.b += lightColor.b * amount; + } else if ( light.isPointLight ) { - } else if ( light.isPointLight ) { + const lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ); - var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ); + let amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() ); - var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() ); + if ( amount <= 0 ) continue; - if ( amount <= 0 ) continue; + amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 ); - amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 ); + if ( amount == 0 ) continue; - if ( amount == 0 ) continue; + amount *= light.intensity; - amount *= light.intensity; + color.r += lightColor.r * amount; + color.g += lightColor.g * amount; + color.b += lightColor.b * amount; - color.r += lightColor.r * amount; - color.g += lightColor.g * amount; - color.b += lightColor.b * amount; + } } } - } + function renderSprite( v1, element, material ) { - function renderSprite( v1, element, material ) { + let scaleX = element.scale.x * _svgWidthHalf; + let scaleY = element.scale.y * _svgHeightHalf; - var scaleX = element.scale.x * _svgWidthHalf; - var scaleY = element.scale.y * _svgHeightHalf; + if ( material.isPointsMaterial ) { - if ( material.isPointsMaterial ) { + scaleX *= material.size; + scaleY *= material.size; - scaleX *= material.size; - scaleY *= material.size; + } - } + const path = 'M' + convert( v1.x - scaleX * 0.5 ) + ',' + convert( v1.y - scaleY * 0.5 ) + 'h' + convert( scaleX ) + 'v' + convert( scaleY ) + 'h' + convert( - scaleX ) + 'z'; + let style = ''; - var path = 'M' + convert( v1.x - scaleX * 0.5 ) + ',' + convert( v1.y - scaleY * 0.5 ) + 'h' + convert( scaleX ) + 'v' + convert( scaleY ) + 'h' + convert( - scaleX ) + 'z'; - var style = ''; + if ( material.isSpriteMaterial || material.isPointsMaterial ) { - if ( material.isSpriteMaterial || material.isPointsMaterial ) { + style = 'fill:' + material.color.getStyle() + ';fill-opacity:' + material.opacity; - style = 'fill:' + material.color.getStyle() + ';fill-opacity:' + material.opacity; + } + + addPath( style, path ); } - addPath( style, path ); + function renderLine( v1, v2, element, material ) { - } + const path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y ); - function renderLine( v1, v2, element, material ) { + if ( material.isLineBasicMaterial ) { - var path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y ); + let style = 'fill:none;stroke:' + material.color.getStyle() + ';stroke-opacity:' + material.opacity + ';stroke-width:' + material.linewidth + ';stroke-linecap:' + material.linecap; - if ( material.isLineBasicMaterial ) { + if ( material.isLineDashedMaterial ) { - var style = 'fill:none;stroke:' + material.color.getStyle() + ';stroke-opacity:' + material.opacity + ';stroke-width:' + material.linewidth + ';stroke-linecap:' + material.linecap; + style = style + ';stroke-dasharray:' + material.dashSize + ',' + material.gapSize; - if ( material.isLineDashedMaterial ) { + } - style = style + ';stroke-dasharray:' + material.dashSize + ',' + material.gapSize; + addPath( style, path ); } - addPath( style, path ); - } - } + function renderFace3( v1, v2, v3, element, material ) { - function renderFace3( v1, v2, v3, element, material ) { + _this.info.render.vertices += 3; + _this.info.render.faces ++; - _this.info.render.vertices += 3; - _this.info.render.faces ++; + const path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y ) + 'L' + convert( v3.positionScreen.x ) + ',' + convert( v3.positionScreen.y ) + 'z'; + let style = ''; - var path = 'M' + convert( v1.positionScreen.x ) + ',' + convert( v1.positionScreen.y ) + 'L' + convert( v2.positionScreen.x ) + ',' + convert( v2.positionScreen.y ) + 'L' + convert( v3.positionScreen.x ) + ',' + convert( v3.positionScreen.y ) + 'z'; - var style = ''; + if ( material.isMeshBasicMaterial ) { - if ( material.isMeshBasicMaterial ) { + _color.copy( material.color ); - _color.copy( material.color ); + if ( material.vertexColors ) { - if ( material.vertexColors ) { + _color.multiply( element.color ); - _color.multiply( element.color ); + } - } + } else if ( material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial ) { - } else if ( material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial ) { + _diffuseColor.copy( material.color ); - _diffuseColor.copy( material.color ); + if ( material.vertexColors ) { - if ( material.vertexColors ) { + _diffuseColor.multiply( element.color ); - _diffuseColor.multiply( element.color ); + } - } + _color.copy( _ambientLight ); - _color.copy( _ambientLight ); + _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 ); - _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 ); + calculateLight( _lights, _centroid, element.normalModel, _color ); - calculateLight( _lights, _centroid, element.normalModel, _color ); + _color.multiply( _diffuseColor ).add( material.emissive ); - _color.multiply( _diffuseColor ).add( material.emissive ); + } else if ( material.isMeshNormalMaterial ) { - } else if ( material.isMeshNormalMaterial ) { + _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix ).normalize(); - _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix ).normalize(); + _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 ); - _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 ); + } - } + if ( material.wireframe ) { - if ( material.wireframe ) { + style = 'fill:none;stroke:' + _color.getStyle() + ';stroke-opacity:' + material.opacity + ';stroke-width:' + material.wireframeLinewidth + ';stroke-linecap:' + material.wireframeLinecap + ';stroke-linejoin:' + material.wireframeLinejoin; - style = 'fill:none;stroke:' + _color.getStyle() + ';stroke-opacity:' + material.opacity + ';stroke-width:' + material.wireframeLinewidth + ';stroke-linecap:' + material.wireframeLinecap + ';stroke-linejoin:' + material.wireframeLinejoin; + } else { - } else { + style = 'fill:' + _color.getStyle() + ';fill-opacity:' + material.opacity; - style = 'fill:' + _color.getStyle() + ';fill-opacity:' + material.opacity; + } - } + addPath( style, path ); - addPath( style, path ); + } - } + // Hide anti-alias gaps - // Hide anti-alias gaps + function expand( v1, v2, pixels ) { - function expand( v1, v2, pixels ) { + let x = v2.x - v1.x, y = v2.y - v1.y; + const det = x * x + y * y; - var x = v2.x - v1.x, y = v2.y - v1.y, - det = x * x + y * y, idet; + if ( det === 0 ) return; - if ( det === 0 ) return; + const idet = pixels / Math.sqrt( det ); - idet = pixels / Math.sqrt( det ); + x *= idet; y *= idet; - x *= idet; y *= idet; + v2.x += x; v2.y += y; + v1.x -= x; v1.y -= y; - v2.x += x; v2.y += y; - v1.x -= x; v1.y -= y; + } - } + function addPath( style, path ) { - function addPath( style, path ) { + if ( _currentStyle === style ) { - if ( _currentStyle === style ) { + _currentPath += path; - _currentPath += path; + } else { - } else { + flushPath(); - flushPath(); + _currentStyle = style; + _currentPath = path; - _currentStyle = style; - _currentPath = path; + } } - } + function flushPath() { + + if ( _currentPath ) { - function flushPath() { + _svgNode = getPathNode( _pathCount ++ ); + _svgNode.setAttribute( 'd', _currentPath ); + _svgNode.setAttribute( 'style', _currentStyle ); + _svg.appendChild( _svgNode ); - if ( _currentPath ) { + } - _svgNode = getPathNode( _pathCount ++ ); - _svgNode.setAttribute( 'd', _currentPath ); - _svgNode.setAttribute( 'style', _currentStyle ); - _svg.appendChild( _svgNode ); + _currentPath = ''; + _currentStyle = ''; } - _currentPath = ''; - _currentStyle = ''; + function getPathNode( id ) { - } + if ( _svgPathPool[ id ] == null ) { - function getPathNode( id ) { + _svgPathPool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); - if ( _svgPathPool[ id ] == null ) { + if ( _quality == 0 ) { - _svgPathPool[ id ] = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); + _svgPathPool[ id ].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed - if ( _quality == 0 ) { + } - _svgPathPool[ id ].setAttribute( 'shape-rendering', 'crispEdges' ); //optimizeSpeed + return _svgPathPool[ id ]; } @@ -533,10 +546,8 @@ var SVGRenderer = function () { } - return _svgPathPool[ id ]; - } -}; +} export { SVGObject, SVGRenderer }; diff --git a/examples/jsm/renderers/nodes/accessors/CameraNode.js b/examples/jsm/renderers/nodes/accessors/CameraNode.js index 3ef2a61629a5ce..ff579d1114c014 100644 --- a/examples/jsm/renderers/nodes/accessors/CameraNode.js +++ b/examples/jsm/renderers/nodes/accessors/CameraNode.js @@ -1,37 +1,27 @@ -import Node from '../core/Node.js'; -import Vector3Node from '../inputs/Vector3Node.js'; +import Object3DNode from './Object3DNode.js'; import Matrix4Node from '../inputs/Matrix4Node.js'; -import { NodeUpdateType } from '../core/constants.js'; -class CameraNode extends Node { +class CameraNode extends Object3DNode { - static POSITION = 'position'; - static PROJECTION = 'projection'; - static VIEW = 'view'; + static PROJECTION_MATRIX = 'projectionMatrix'; constructor( scope = CameraNode.POSITION ) { - super(); - - this.updateType = NodeUpdateType.Frame; - - this.scope = scope; - - this._inputNode = null; + super( scope ); } - getType() { + getType( builder ) { const scope = this.scope; - if ( scope === CameraNode.PROJECTION || scope === CameraNode.VIEW ) { + if ( scope === CameraNode.PROJECTION_MATRIX ) { return 'mat4'; } - return 'vec3'; + return super.getType( builder ); } @@ -41,17 +31,17 @@ class CameraNode extends Node { const inputNode = this._inputNode; const scope = this.scope; - if ( scope === CameraNode.PROJECTION ) { + if ( scope === CameraNode.PROJECTION_MATRIX ) { inputNode.value = camera.projectionMatrix; - } else if ( scope === CameraNode.VIEW ) { + } else if ( scope === CameraNode.VIEW_MATRIX ) { inputNode.value = camera.matrixWorldInverse; - } else if ( scope === CameraNode.POSITION ) { + } else { - camera.getWorldPosition( inputNode.value ); + super.update( frame ); } @@ -67,7 +57,7 @@ class CameraNode extends Node { const scope = this.scope; - if ( scope === CameraNode.PROJECTION || scope === CameraNode.VIEW ) { + if ( scope === CameraNode.PROJECTION_MATRIX ) { if ( inputNode === null || inputNode.isMatrix4Node !== true ) { @@ -75,13 +65,9 @@ class CameraNode extends Node { } - } else if ( scope === CameraNode.POSITION ) { + } else { - if ( inputNode === null || inputNode.isVector3Node !== true ) { - - inputNode = new Vector3Node(); - - } + return super.generate( builder, output ); } diff --git a/examples/jsm/renderers/nodes/accessors/MaterialNode.js b/examples/jsm/renderers/nodes/accessors/MaterialNode.js new file mode 100644 index 00000000000000..4a9e4b89a62c2f --- /dev/null +++ b/examples/jsm/renderers/nodes/accessors/MaterialNode.js @@ -0,0 +1,106 @@ +import Node from '../core/Node.js'; +import OperatorNode from '../math/OperatorNode.js'; +import MaterialReferenceNode from './MaterialReferenceNode.js'; + +class MaterialNode extends Node { + + static COLOR = 'color'; + static OPACITY = 'opacity'; + static SPECULAR = 'specular'; + static SHININESS = 'shininess'; + + constructor( scope = MaterialNode.COLOR ) { + + super(); + + this.scope = scope; + + } + + getType( builder ) { + + const scope = this.scope; + const material = builder.getContextParameter( 'material' ); + + if ( scope === MaterialNode.COLOR ) { + + return material.map !== null ? 'vec4' : 'vec3'; + + } else if ( scope === MaterialNode.OPACITY ) { + + return 'float'; + + } else if ( scope === MaterialNode.SPECULAR ) { + + return 'vec3'; + + } else if ( scope === MaterialNode.SHININESS ) { + + return 'float'; + + } + + } + + generate( builder, output ) { + + const material = builder.getContextParameter( 'material' ); + const scope = this.scope; + + let node = null; + + if ( scope === MaterialNode.COLOR ) { + + const colorNode = new MaterialReferenceNode( 'color', 'color' ); + + if ( material.map !== null && material.map !== undefined && material.map.isTexture === true ) { + + node = new OperatorNode( '*', colorNode, new MaterialReferenceNode( 'map', 'texture' ) ); + + } else { + + node = colorNode; + + } + + } else if ( scope === MaterialNode.OPACITY ) { + + const opacityNode = new MaterialReferenceNode( 'opacity', 'float' ); + + if ( material.alphaMap !== null && material.alphaMap !== undefined && material.alphaMap.isTexture === true ) { + + node = new OperatorNode( '*', opacityNode, new MaterialReferenceNode( 'alphaMap', 'texture' ) ); + + } else { + + node = opacityNode; + + } + + } else if ( scope === MaterialNode.SPECULAR ) { + + const specularColorNode = new MaterialReferenceNode( 'specular', 'color' ); + + if ( material.specularMap !== null && material.specularMap !== undefined && material.specularMap.isTexture === true ) { + + node = new OperatorNode( '*', specularColorNode, new MaterialReferenceNode( 'specularMap', 'texture' ) ); + + } else { + + node = specularColorNode; + + } + + } else if ( scope === MaterialNode.SHININESS ) { + + node = new MaterialReferenceNode( 'shininess', 'float' ); + + } + + return node.build( builder, output ); + + } + +} + +export default MaterialNode; diff --git a/examples/jsm/renderers/nodes/accessors/MaterialReferenceNode.js b/examples/jsm/renderers/nodes/accessors/MaterialReferenceNode.js new file mode 100644 index 00000000000000..e23261c19c05be --- /dev/null +++ b/examples/jsm/renderers/nodes/accessors/MaterialReferenceNode.js @@ -0,0 +1,23 @@ +import ReferenceNode from './ReferenceNode.js'; + +class MaterialReferenceNode extends ReferenceNode { + + constructor( property, inputType, material = null ) { + + super( property, inputType, material ); + + this.material = material; + + } + + update( frame ) { + + this.object = this.material !== null ? this.material : frame.material; + + super.update( frame ); + + } + +} + +export default MaterialReferenceNode; diff --git a/examples/jsm/renderers/nodes/accessors/ModelNode.js b/examples/jsm/renderers/nodes/accessors/ModelNode.js index ed62e3d779f73d..7c1a46b931fbeb 100644 --- a/examples/jsm/renderers/nodes/accessors/ModelNode.js +++ b/examples/jsm/renderers/nodes/accessors/ModelNode.js @@ -1,94 +1,10 @@ -import Node from '../core/Node.js'; -import Matrix4Node from '../inputs/Matrix4Node.js'; -import Matrix3Node from '../inputs/Matrix3Node.js'; -import { NodeUpdateType } from '../core/constants.js'; +import Object3DNode from './Object3DNode.js'; -class ModelNode extends Node { +class ModelNode extends Object3DNode { - static VIEW = 'view'; - static NORMAL = 'normal'; + constructor( scope = ModelNode.VIEW_MATRIX ) { - constructor( scope = ModelNode.VIEW ) { - - super(); - - this.scope = scope; - - this.updateType = NodeUpdateType.Object; - - this._inputNode = null; - - } - - getType() { - - const scope = this.scope; - - if ( scope === ModelNode.VIEW ) { - - return 'mat4'; - - } else if ( scope === ModelNode.NORMAL ) { - - return 'mat3'; - - } - - } - - update( frame ) { - - const object = frame.object; - const inputNode = this._inputNode; - const scope = this.scope; - - if ( scope === ModelNode.VIEW ) { - - inputNode.value = object.modelViewMatrix; - - } else if ( scope === ModelNode.NORMAL ) { - - inputNode.value = object.normalMatrix; - - } - - } - - generate( builder, output ) { - - const nodeData = builder.getDataFromNode( this ); - - let inputNode = this._inputNode; - - if ( nodeData.inputNode === undefined ) { - - const scope = this.scope; - - if ( scope === ModelNode.VIEW ) { - - if ( inputNode === null || inputNode.isMatrix4Node !== true ) { - - inputNode = new Matrix4Node( null ); - - } - - } else if ( scope === ModelNode.NORMAL ) { - - if ( inputNode === null || inputNode.isMatrix3Node !== true ) { - - inputNode = new Matrix3Node( null ); - - } - - } - - this._inputNode = inputNode; - - nodeData.inputNode = inputNode; - - } - - return inputNode.build( builder, output ); + super( scope ); } diff --git a/examples/jsm/renderers/nodes/accessors/ModelViewProjectionNode.js b/examples/jsm/renderers/nodes/accessors/ModelViewProjectionNode.js index 2c92f063a67543..93463aa065b9a7 100644 --- a/examples/jsm/renderers/nodes/accessors/ModelViewProjectionNode.js +++ b/examples/jsm/renderers/nodes/accessors/ModelViewProjectionNode.js @@ -12,7 +12,7 @@ class ModelViewProjectionNode extends Node { this.position = position; - this._mvpMatrix = new OperatorNode( '*', new CameraNode( CameraNode.PROJECTION ), new ModelNode( ModelNode.VIEW ) ); + this._mvpMatrix = new OperatorNode( '*', new CameraNode( CameraNode.PROJECTION_MATRIX ), new ModelNode( ModelNode.VIEW_MATRIX ) ); } diff --git a/examples/jsm/renderers/nodes/accessors/NormalNode.js b/examples/jsm/renderers/nodes/accessors/NormalNode.js index 94bee1528303e0..fc28fd863d76d1 100644 --- a/examples/jsm/renderers/nodes/accessors/NormalNode.js +++ b/examples/jsm/renderers/nodes/accessors/NormalNode.js @@ -5,6 +5,7 @@ import ModelNode from '../accessors/ModelNode.js'; import CameraNode from '../accessors/CameraNode.js'; import OperatorNode from '../math/OperatorNode.js'; import MathNode from '../math/MathNode.js'; +import { inverseTransformDirection } from '../functions/MathFunctions.js'; class NormalNode extends Node { @@ -44,8 +45,7 @@ class NormalNode extends Node { if ( viewNormalNode === undefined ) { - const unnormalizedWNNode = new OperatorNode( '*', new ModelNode( ModelNode.NORMAL ), localNormalNode ); - const vertexNormalNode = new MathNode( MathNode.NORMALIZE, unnormalizedWNNode ); + const vertexNormalNode = new OperatorNode( '*', new ModelNode( ModelNode.NORMAL_MATRIX ), localNormalNode ); viewNormalNode = new MathNode( MathNode.NORMALIZE, new VaryNode( vertexNormalNode ) ); @@ -61,9 +61,9 @@ class NormalNode extends Node { if ( worldNormalNode === undefined ) { - const vertexNormalNode = new MathNode( MathNode.INVERSE_TRANSFORM_DIRETION, new NormalNode( NormalNode.VIEW ), new CameraNode( CameraNode.VIEW ) ); + const vertexNormalNode = inverseTransformDirection.call( { dir: new NormalNode( NormalNode.VIEW ), matrix: new CameraNode( CameraNode.VIEW_MATRIX ) } ); - worldNormalNode = new VaryNode( vertexNormalNode ); + worldNormalNode = new MathNode( MathNode.NORMALIZE, new VaryNode( vertexNormalNode ) ); nodeData.worldNormalNode = worldNormalNode; diff --git a/examples/jsm/renderers/nodes/accessors/Object3DNode.js b/examples/jsm/renderers/nodes/accessors/Object3DNode.js new file mode 100644 index 00000000000000..d471a0500033ce --- /dev/null +++ b/examples/jsm/renderers/nodes/accessors/Object3DNode.js @@ -0,0 +1,129 @@ +import Node from '../core/Node.js'; +import Matrix4Node from '../inputs/Matrix4Node.js'; +import Matrix3Node from '../inputs/Matrix3Node.js'; +import Vector3Node from '../inputs/Vector3Node.js'; +import { NodeUpdateType } from '../core/constants.js'; + +class Object3DNode extends Node { + + static VIEW_MATRIX = 'viewMatrix'; + static NORMAL_MATRIX = 'normalMatrix'; + static WORLD_MATRIX = 'worldMatrix'; + static POSITION = 'position'; + static VIEW_POSITION = 'viewPosition'; + + constructor( scope = Object3DNode.VIEW_MATRIX, object3d = null ) { + + super(); + + this.scope = scope; + this.object3d = object3d; + + this.updateType = NodeUpdateType.Object; + + this._inputNode = null; + + } + + getType() { + + const scope = this.scope; + + if ( scope === Object3DNode.WORLD_MATRIX || scope === Object3DNode.VIEW_MATRIX ) { + + return 'mat4'; + + } else if ( scope === Object3DNode.NORMAL_MATRIX ) { + + return 'mat3'; + + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION ) { + + return 'vec3'; + + } + + } + + update( frame ) { + + const object = this.object3d !== null ? this.object3d : frame.object; + const inputNode = this._inputNode; + const camera = frame.camera; + const scope = this.scope; + + if ( scope === Object3DNode.VIEW_MATRIX ) { + + inputNode.value = object.modelViewMatrix; + + } else if ( scope === Object3DNode.NORMAL_MATRIX ) { + + inputNode.value = object.normalMatrix; + + } else if ( scope === Object3DNode.WORLD_MATRIX ) { + + inputNode.value = object.matrixWorld; + + } else if ( scope === Object3DNode.POSITION ) { + + inputNode.value.setFromMatrixPosition( object.matrixWorld ); + + } else if ( scope === Object3DNode.VIEW_POSITION ) { + + inputNode.value.setFromMatrixPosition( object.matrixWorld ); + + inputNode.value.applyMatrix4( camera.matrixWorldInverse ); + + } + + } + + generate( builder, output ) { + + const nodeData = builder.getDataFromNode( this ); + + let inputNode = this._inputNode; + + if ( nodeData.inputNode === undefined ) { + + const scope = this.scope; + + if ( scope === Object3DNode.WORLD_MATRIX || scope === Object3DNode.VIEW_MATRIX ) { + + if ( inputNode === null || inputNode.isMatrix4Node !== true ) { + + inputNode = new Matrix4Node( null ); + + } + + } else if ( scope === Object3DNode.NORMAL_MATRIX ) { + + if ( inputNode === null || inputNode.isMatrix3Node !== true ) { + + inputNode = new Matrix3Node( null ); + + } + + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION ) { + + if ( inputNode === null || inputNode.isVector3Node !== true ) { + + inputNode = new Vector3Node(); + + } + + } + + this._inputNode = inputNode; + + nodeData.inputNode = inputNode; + + } + + return inputNode.build( builder, output ); + + } + +} + +export default Object3DNode; diff --git a/examples/jsm/renderers/nodes/accessors/PositionNode.js b/examples/jsm/renderers/nodes/accessors/PositionNode.js index 2bbd9e2baac7c8..118ede9888f54f 100644 --- a/examples/jsm/renderers/nodes/accessors/PositionNode.js +++ b/examples/jsm/renderers/nodes/accessors/PositionNode.js @@ -1,9 +1,17 @@ import Node from '../core/Node.js'; import AttributeNode from '../core/AttributeNode.js'; +import VaryNode from '../core/VaryNode.js'; +import ModelNode from '../accessors/ModelNode.js'; +import MathNode from '../math/MathNode.js'; +import OperatorNode from '../math/OperatorNode.js'; +import { transformDirection } from '../functions/MathFunctions.js'; class PositionNode extends Node { static LOCAL = 'local'; + static WORLD = 'world'; + static VIEW = 'view'; + static VIEW_DIRECTION = 'viewDirection'; constructor( scope = PositionNode.POSITION ) { @@ -17,18 +25,71 @@ class PositionNode extends Node { const type = this.getType( builder ); const nodeData = builder.getDataFromNode( this, builder.shaderStage ); + const scope = this.scope; - let positionNode = nodeData.positionNode; + let localPositionNode = nodeData.localPositionNode; - if ( positionNode === undefined ) { + if ( localPositionNode === undefined ) { - positionNode = new AttributeNode( 'position', 'vec3' ); + localPositionNode = new AttributeNode( 'position', 'vec3' ); - nodeData.positionNode = positionNode; + nodeData.localPositionNode = localPositionNode; } - const positionSnipped = positionNode.build( builder, type ); + let outputNode = localPositionNode; + + if ( scope === PositionNode.WORLD ) { + + let worldPositionNode = nodeData.worldPositionNode; + + if ( worldPositionNode === undefined ) { + + const vertexPositionNode = transformDirection.call( { dir: localPositionNode, matrix: new ModelNode( ModelNode.WORLD_MATRIX ) } ); + + worldPositionNode = new VaryNode( vertexPositionNode ); + + nodeData.worldPositionNode = worldPositionNode; + + } + + outputNode = worldPositionNode; + + } else if ( scope === PositionNode.VIEW ) { + + let viewPositionNode = nodeData.viewPositionNode; + + if ( viewPositionNode === undefined ) { + + const vertexPositionNode = new OperatorNode( '*', new ModelNode( ModelNode.VIEW_MATRIX ), localPositionNode ); + + viewPositionNode = new VaryNode( vertexPositionNode ); + + nodeData.viewPositionNode = viewPositionNode; + + } + + outputNode = viewPositionNode; + + } else if ( scope === PositionNode.VIEW_DIRECTION ) { + + let viewDirPositionNode = nodeData.viewDirPositionNode; + + if ( viewDirPositionNode === undefined ) { + + const vertexPositionNode = new MathNode( MathNode.NEGATE, new PositionNode( PositionNode.VIEW ) ); + + viewDirPositionNode = new MathNode( MathNode.NORMALIZE, new VaryNode( vertexPositionNode ) ); + + nodeData.viewDirPositionNode = viewDirPositionNode; + + } + + outputNode = viewDirPositionNode; + + } + + const positionSnipped = outputNode.build( builder, type ); return builder.format( positionSnipped, type, output ); diff --git a/examples/jsm/renderers/nodes/accessors/ReferenceNode.js b/examples/jsm/renderers/nodes/accessors/ReferenceNode.js new file mode 100644 index 00000000000000..bb70b8766e4112 --- /dev/null +++ b/examples/jsm/renderers/nodes/accessors/ReferenceNode.js @@ -0,0 +1,91 @@ +import Node from '../core/Node.js'; +import FloatNode from '../inputs/FloatNode.js'; +import Vector2Node from '../inputs/Vector2Node.js'; +import Vector3Node from '../inputs/Vector3Node.js'; +import Vector4Node from '../inputs/Vector4Node.js'; +import ColorNode from '../inputs/ColorNode.js'; +import TextureNode from '../inputs/TextureNode.js'; +import { NodeUpdateType } from '../core/constants.js'; + +class ReferenceNode extends Node { + + constructor( property, inputType, object = null ) { + + super(); + + this.property = property; + this.inputType = inputType; + + this.object = object; + + this.node = null; + + this.updateType = NodeUpdateType.Object; + + this.setNodeType( inputType ); + + } + + setNodeType( inputType ) { + + let node = null; + let type = inputType; + + if ( type === 'float' ) { + + node = new FloatNode(); + + } else if ( type === 'vec2' ) { + + node = new Vector2Node( null ); + + } else if ( type === 'vec3' ) { + + node = new Vector3Node( null ); + + } else if ( type === 'vec4' ) { + + node = new Vector4Node( null ); + + } else if ( type === 'color' ) { + + node = new ColorNode( null ); + type = 'vec3'; + + } else if ( type === 'texture' ) { + + node = new TextureNode(); + type = 'vec4'; + + } + + this.node = node; + this.type = type; + this.inputType = inputType; + + } + + getNodeType() { + + return this.inputType; + + } + + update( frame ) { + + const object = this.object !== null ? this.object : frame.object; + const value = object[ this.property ]; + + this.node.value = value; + + } + + generate( builder, output ) { + + return this.node.build( builder, output ); + + } + +} + +export default ReferenceNode; diff --git a/examples/jsm/renderers/nodes/accessors/UVNode.js b/examples/jsm/renderers/nodes/accessors/UVNode.js index 5bd7135ba6b3e0..ede76dbb01f3ed 100644 --- a/examples/jsm/renderers/nodes/accessors/UVNode.js +++ b/examples/jsm/renderers/nodes/accessors/UVNode.js @@ -8,6 +8,8 @@ class UVNode extends AttributeNode { this.index = index; + Object.defineProperty( this, 'isUVNode', { value: true } ); + } getAttributeName( /*builder*/ ) { diff --git a/examples/jsm/renderers/nodes/consts/MathConsts.js b/examples/jsm/renderers/nodes/consts/MathConsts.js new file mode 100644 index 00000000000000..b202eb083b39a9 --- /dev/null +++ b/examples/jsm/renderers/nodes/consts/MathConsts.js @@ -0,0 +1,4 @@ +import ConstNode from '../core/ConstNode.js'; + +export const PI = new ConstNode( '3.141592653589793', 'float', 'PI' ); +export const RECIPROCAL_PI = new ConstNode( '0.3183098861837907', 'float', 'RECIPROCAL_PI' ); diff --git a/examples/jsm/renderers/nodes/core/AttributeNode.js b/examples/jsm/renderers/nodes/core/AttributeNode.js index db711dc8f75906..bbf0a2ce0e4474 100644 --- a/examples/jsm/renderers/nodes/core/AttributeNode.js +++ b/examples/jsm/renderers/nodes/core/AttributeNode.js @@ -2,17 +2,17 @@ import Node from './Node.js'; class AttributeNode extends Node { - constructor( name, type ) { + constructor( attributeName, type ) { super( type ); - this.name = name; + this._attributeName = attributeName; } - setAttributeName( name ) { + setAttributeName( attributeName ) { - this.name = name; + this._attributeName = attributeName; return this; @@ -20,7 +20,7 @@ class AttributeNode extends Node { getAttributeName( /*builder*/ ) { - return this.name; + return this._attributeName; } diff --git a/examples/jsm/renderers/nodes/core/CodeNode.js b/examples/jsm/renderers/nodes/core/CodeNode.js new file mode 100644 index 00000000000000..3782ec03620ee6 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/CodeNode.js @@ -0,0 +1,80 @@ +import Node from './Node.js'; + +class CodeNode extends Node { + + constructor( code = '', type = 'code' ) { + + super( type ); + + this.code = code; + + this.useKeywords = false; + + this._includes = []; + + Object.defineProperty( this, 'isCodeNode', { value: true } ); + + } + + setIncludes( includes ) { + + this._includes = includes; + + return this; + + } + + getIncludes( /*builder*/ ) { + + return this._includes; + + } + + generate( builder, output ) { + + if ( this.useKeywords === true ) { + + const contextKeywords = builder.getContextParameter( 'keywords' ); + + if ( contextKeywords !== undefined ) { + + const nodeData = builder.getDataFromNode( this, builder.shaderStage ); + + if ( nodeData.keywords === undefined ) { + + nodeData.keywords = []; + + } + + if ( nodeData.keywords.indexOf( contextKeywords ) === - 1 ) { + + contextKeywords.include( builder, this.code ); + + nodeData.keywords.push( contextKeywords ); + + } + + } + + } + + const includes = this.getIncludes( builder ); + + for ( const include of includes ) { + + include.build( builder ); + + } + + const type = this.getType( builder ); + const nodeCode = builder.getCodeFromNode( this, type ); + + nodeCode.code = this.code; + + return nodeCode.code; + + } + +} + +export default CodeNode; diff --git a/examples/jsm/renderers/nodes/core/ConstNode.js b/examples/jsm/renderers/nodes/core/ConstNode.js new file mode 100644 index 00000000000000..566b094dc7f3eb --- /dev/null +++ b/examples/jsm/renderers/nodes/core/ConstNode.js @@ -0,0 +1,40 @@ +import CodeNode from './CodeNode.js'; + +class ConstNode extends CodeNode { + + constructor( code = '', type = '', name = '' ) { + + super( code, type ); + + this.includes = []; + + this.name = name; + + } + + generate( builder, output ) { + + const code = super.generate( builder ); + + const type = this.getType( builder ); + const nodeCode = builder.getCodeFromNode( this, type ); + + if ( this.name !== '' ) { + + // use a custom property name + + nodeCode.name = this.name; + + } + + const propertyName = builder.getPropertyName( nodeCode ); + + nodeCode.code = `#define ${propertyName} ${code}`; + + return builder.format( propertyName, type, output ); + + } + +} + +export default ConstNode; diff --git a/examples/jsm/renderers/nodes/core/ContextNode.js b/examples/jsm/renderers/nodes/core/ContextNode.js new file mode 100644 index 00000000000000..5d15180567f291 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/ContextNode.js @@ -0,0 +1,53 @@ +import Node from './Node.js'; + +class ContextNode extends Node { + + constructor( node, parameters = {} ) { + + super(); + + this.node = node; + + this.parameters = parameters; + + Object.defineProperty( this, 'isContextNode', { value: true } ); + + } + + setParameter( name, value ) { + + this.parameters[ name ] = value; + + return this; + + } + + getParameter( name ) { + + return this.parameters[ name ]; + + } + + getType( builder ) { + + return this.node.getType( builder ); + + } + + generate( builder, output ) { + + const previousContext = builder.getContext(); + + builder.setContext( Object.assign( {}, builder.context, this.parameters ) ); + + const snippet = this.node.build( builder, output ); + + builder.setContext( previousContext ); + + return snippet; + + } + +} + +export default ContextNode; diff --git a/examples/jsm/renderers/nodes/core/FunctionCallNode.js b/examples/jsm/renderers/nodes/core/FunctionCallNode.js new file mode 100644 index 00000000000000..b35ead023ee435 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/FunctionCallNode.js @@ -0,0 +1,70 @@ +import Node from './Node.js'; + +class FunctionCallNode extends Node { + + constructor( functionNode = null, parameters = {} ) { + + super(); + + this.functionNode = functionNode; + this.parameters = parameters; + + } + + setParameters( parameters ) { + + this.parameters = parameters; + + return this; + + } + + getParameters() { + + return this.parameters; + + } + + getType( builder ) { + + return this.functionNode.getType( builder ); + + } + + generate( builder, output ) { + + const params = []; + + const functionNode = this.functionNode; + + const inputs = functionNode.getInputs( builder ); + const parameters = this.parameters; + + for ( const inputNode of inputs ) { + + const node = parameters[ inputNode.name ]; + + if ( node !== undefined ) { + + params.push( node.build( builder, inputNode.type ) ); + + } else { + + throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` ); + + } + + } + + const type = this.getType( builder ); + const functionName = functionNode.build( builder, 'property' ); + + const callSnippet = `${functionName}( ${params.join( ', ' )} )`; + + return builder.format( callSnippet, type, output ); + + } + +} + +export default FunctionCallNode; diff --git a/examples/jsm/renderers/nodes/core/FunctionNode.js b/examples/jsm/renderers/nodes/core/FunctionNode.js new file mode 100644 index 00000000000000..98f2aa9b698130 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/FunctionNode.js @@ -0,0 +1,194 @@ +import CodeNode from './CodeNode.js'; +import NodeFunctionInput from './NodeFunctionInput.js'; +import FunctionCallNode from './FunctionCallNode.js'; + +const declarationRegexp = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\((.*?)\)/i; +const propertiesRegexp = /[a-z_0-9]+/ig; + +const pragmaMain = '#pragma main'; + +class FunctionNode extends CodeNode { + + constructor( code = '' ) { + + super( code ); + + this.inputs = []; + + this.name = ''; + this.needsUpdate = true; + + this.useKeywords = true; + + this.presicion = ''; + + this._includeCode = ''; + this._internalCode = ''; + + } + + getType( /*builder*/ ) { + + if ( this.needsUpdate === true ) { + + this.parse(); + + } + + return this.type; + + } + + getInputs( /*builder*/ ) { + + if ( this.needsUpdate === true ) { + + this.parse(); + + } + + return this.inputs; + + } + + parse() { + + const code = this.code; + + const pragmaMainIndex = code.indexOf( pragmaMain ); + + const mainCode = pragmaMainIndex !== - 1 ? code.substr( pragmaMainIndex + pragmaMain.length ) : code; + + const declaration = mainCode.match( declarationRegexp ); + + if ( declaration !== null && declaration.length === 5 ) { + + // tokenizer + + const paramsCode = declaration[ 4 ]; + const propsMatches = []; + + let nameMatch = null; + + while ( ( nameMatch = propertiesRegexp.exec( paramsCode ) ) !== null ) { + + propsMatches.push( nameMatch ); + + } + + // parser + + const inputs = []; + + let i = 0; + + while ( i < propsMatches.length ) { + + const isConst = propsMatches[ i ][ 0 ] === 'const'; + + if ( isConst === true ) { + + i ++; + + } + + let qualifier = propsMatches[ i ][ 0 ]; + + if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) { + + i ++; + + } else { + + qualifier = ''; + + } + + const type = propsMatches[ i ++ ][ 0 ]; + const name = propsMatches[ i ++ ][ 0 ]; + + inputs.push( new NodeFunctionInput( type, name, qualifier, isConst ) ); + + } + + const blockCode = mainCode.substring( declaration[ 0 ].length ); + + this.name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : ''; + this.type = declaration[ 2 ]; + + this.presicion = declaration[ 1 ] !== undefined ? declaration[ 1 ] : ''; + + this.inputs = inputs; + + this._includeCode = pragmaMainIndex !== - 1 ? code.substr( 0, pragmaMainIndex ) : ''; + this._internalCode = `( ${paramsCode} ) ${blockCode}`; + + } else { + + throw new Error( 'FunctionNode: Function is not a GLSL code.' ); + + } + + this.code = code; + + this.needsUpdate = false; + + } + + call( parameters = null ) { + + return new FunctionCallNode( this, parameters ); + + } + + generate( builder, output ) { + + super.generate( builder ); + + const type = this.getType( builder ); + const nodeCode = builder.getCodeFromNode( this, type ); + + if ( this.name !== '' ) { + + // use a custom property name + + nodeCode.name = this.name; + + } + + const propertyName = builder.getPropertyName( nodeCode ); + + const presicion = this.presicion; + const includeCode = this._includeCode; + + let code = `${type} ${propertyName} ${this._internalCode}`; + + if ( presicion !== '' ) { + + code = `${presicion} ${code}`; + + } + + if ( includeCode !== '' ) { + + code = `${includeCode} ${code}`; + + } + + nodeCode.code = code; + + if ( output === 'property' ) { + + return propertyName; + + } else { + + return builder.format( `${propertyName}()`, type, output ); + + } + + } + +} + +export default FunctionNode; diff --git a/examples/jsm/renderers/nodes/core/NodeBuilder.js b/examples/jsm/renderers/nodes/core/NodeBuilder.js index 2b63e936b00f56..c67afb0b0fad48 100644 --- a/examples/jsm/renderers/nodes/core/NodeBuilder.js +++ b/examples/jsm/renderers/nodes/core/NodeBuilder.js @@ -1,6 +1,9 @@ import NodeUniform from './NodeUniform.js'; import NodeAttribute from './NodeAttribute.js'; import NodeVary from './NodeVary.js'; +import NodeVar from './NodeVar.js'; +import NodeCode from './NodeCode.js'; +import NodeKeywords from './NodeKeywords.js'; import { NodeUpdateType } from './constants.js'; class NodeBuilder { @@ -19,8 +22,16 @@ class NodeBuilder { this.slots = { vertex: [], fragment: [] }; this.defines = { vertex: {}, fragment: {} }; this.uniforms = { vertex: [], fragment: [] }; + this.nodeCodes = { vertex: [], fragment: [] }; + this.vars = { vertex: [], fragment: [] }; this.attributes = []; this.varys = []; + this.flow = { code: '' }; + + this.context = { + keywords: new NodeKeywords(), + material: material + }; this.nodesData = new WeakMap(); @@ -58,6 +69,24 @@ class NodeBuilder { } + setContext( context ) { + + this.context = context; + + } + + getContext() { + + return this.context; + + } + + getContextParameter( name ) { + + return this.context[ name ]; + + } + getTexture( /* textureProperty, uvSnippet */ ) { console.warn( 'Abstract function.' ); @@ -72,7 +101,7 @@ class NodeBuilder { if ( type === 'vec4' ) return `vec4( ${value.x}, ${value.y}, ${value.z}, ${value.w} )`; if ( type === 'color' ) return `vec3( ${value.r}, ${value.g}, ${value.b} )`; - throw new Error( `Type '${type}' not found in generate constant attempt.` ); + throw new Error( `NodeBuilder: Type '${type}' not found in generate constant attempt.` ); } @@ -129,7 +158,7 @@ class NodeBuilder { getVectorType( type ) { if ( type === 'color' ) return 'vec3'; - else if ( type === 'texture' ) return 'vec4'; + if ( type === 'texture' ) return 'vec4'; return type; @@ -186,7 +215,7 @@ class NodeBuilder { const uniforms = this.uniforms[ shaderStage ]; const index = uniforms.length; - nodeUniform = new NodeUniform( 'nodeU' + index, type, node ); + nodeUniform = new NodeUniform( 'nodeUniform' + index, type, node ); uniforms.push( nodeUniform ); @@ -198,6 +227,29 @@ class NodeBuilder { } + getVarFromNode( node, type, shaderStage = this.shaderStage ) { + + const nodeData = this.getDataFromNode( node, shaderStage ); + + let nodeVar = nodeData.variable; + + if ( nodeVar === undefined ) { + + const vars = this.vars[ shaderStage ]; + const index = vars.length; + + nodeVar = new NodeVar( 'nodeVar' + index, type ); + + vars.push( nodeVar ); + + nodeData.variable = nodeVar; + + } + + return nodeVar; + + } + getVaryFromNode( node, type ) { const nodeData = this.getDataFromNode( node ); @@ -209,7 +261,7 @@ class NodeBuilder { const varys = this.varys; const index = varys.length; - nodeVary = new NodeVary( 'nodeV' + index, type ); + nodeVary = new NodeVary( 'nodeVary' + index, type ); varys.push( nodeVary ); @@ -221,6 +273,29 @@ class NodeBuilder { } + getCodeFromNode( node, type, shaderStage = this.shaderStage ) { + + const nodeData = this.getDataFromNode( node ); + + let nodeCode = nodeData.code; + + if ( nodeCode === undefined ) { + + const nodeCodes = this.nodeCodes[ shaderStage ]; + const index = nodeCodes.length; + + nodeCode = new NodeCode( 'nodeCode' + index, type ); + + nodeCodes.push( nodeCode ); + + nodeData.code = nodeCode; + + } + + return nodeCode; + + } + /* analyzeNode( node ) { @@ -228,12 +303,33 @@ class NodeBuilder { } */ + addFlowCode( code ) { + + if ( ! /;\s*$/.test( code ) ) { + + code += '; '; + + } + + this.flow.code += code; + + } + flowNode( node, output ) { - const flowData = {}; - flowData.result = node.build( this, output ); + const previousFlow = this.flow; - return flowData; + const flow = { + code: previousFlow.code, + }; + + this.flow = flow; + + flow.result = node.build( this, output ); + + this.flow = previousFlow; + + return flow; } @@ -277,12 +373,40 @@ class NodeBuilder { } + getVarsHeaderSnippet( /*shaderStage*/ ) { + + console.warn( 'Abstract function.' ); + + } + + getVarsBodySnippet( /*shaderStage*/ ) { + + console.warn( 'Abstract function.' ); + + } + getUniformsHeaderSnippet( /*shaderStage*/ ) { console.warn( 'Abstract function.' ); } + getUniformsHeaderCodes( shaderStage ) { + + const nodeCodes = this.nodeCodes[ shaderStage ]; + + let code = ''; + + for ( const nodeCode of nodeCodes ) { + + code += nodeCode.code + '\n'; + + } + + return code; + + } + getHash() { return this.vertexShader + this.fragmentShader; @@ -304,6 +428,7 @@ class NodeBuilder { const flowData = this.flowNode( slot.node, slot.output ); + this.define( shaderStage, `NODE_CODE_${slot.name}`, flowData.code ); this.define( shaderStage, `NODE_${slot.name}`, flowData.result ); } @@ -319,8 +444,14 @@ class NodeBuilder { this.define( shaderStage, 'NODE_HEADER_VARYS', this.getVarysHeaderSnippet( shaderStage ) ); this.define( shaderStage, 'NODE_BODY_VARYS', this.getVarysBodySnippet( shaderStage ) ); + this.define( shaderStage, 'NODE_BODY_VARS', this.getVarsBodySnippet( shaderStage ) ); + + let headerCode = ''; + + headerCode += this.getVarsHeaderSnippet( shaderStage ) + '\n'; + headerCode += this.getUniformsHeaderCodes( shaderStage ); - shaderData[ shaderStage ] = this._buildDefines( shaderStage ); + shaderData[ shaderStage ] = this._buildDefines( shaderStage ) + '\n' + headerCode; } diff --git a/examples/jsm/renderers/nodes/core/NodeCode.js b/examples/jsm/renderers/nodes/core/NodeCode.js new file mode 100644 index 00000000000000..ac47d0a46fb96f --- /dev/null +++ b/examples/jsm/renderers/nodes/core/NodeCode.js @@ -0,0 +1,15 @@ +class NodeCode { + + constructor( name, type, code = '' ) { + + this.name = name; + this.type = type; + this.code = code; + + Object.defineProperty( this, 'isNodeCode', { value: true } ); + + } + +} + +export default NodeCode; diff --git a/examples/jsm/renderers/nodes/core/NodeFunctionInput.js b/examples/jsm/renderers/nodes/core/NodeFunctionInput.js new file mode 100644 index 00000000000000..60671a65100426 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/NodeFunctionInput.js @@ -0,0 +1,16 @@ +class NodeFunctionInput { + + constructor( type, name, qualifier = '', isConst = false ) { + + this.type = type; + this.name = name; + this.qualifier = qualifier; + this.isConst = isConst; + + Object.defineProperty( this, 'isNodeFunction', { value: true } ); + + } + +} + +export default NodeFunctionInput; diff --git a/examples/jsm/renderers/nodes/core/NodeKeywords.js b/examples/jsm/renderers/nodes/core/NodeKeywords.js new file mode 100644 index 00000000000000..d83d2e123aee45 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/NodeKeywords.js @@ -0,0 +1,229 @@ +import VarNode from './VarNode.js'; +import PropertyNode from './PropertyNode.js'; +import PositionNode from '../accessors/PositionNode.js'; +import NormalNode from '../accessors/NormalNode.js'; + +import { PI, RECIPROCAL_PI } from '../consts/MathConsts.js'; +import { saturateMacro, whiteComplementMacro } from '../functions/MathFunctions.js'; + +class NodeKeywords { + + static PI = 'PI'; + static RECIPROCAL_PI = 'RECIPROCAL_PI'; + + static Saturate = 'saturate'; + static WhiteComplement = 'whiteComplement'; + + static PositionLocal = 'PositionLocal'; + static PositionWorld = 'PositionWorld'; + static PositionView = 'PositionView'; + static PositionViewDirection = 'PositionViewDirection'; + + static NormalLocal = 'NormalLocal'; + static NormalWorld = 'NormalWorld'; + static NormalView = 'NormalView'; + + static Irradiance = 'Irradiance'; + static ReflectedLightIndirectDiffuse = 'ReflectedLightIndirectDiffuse'; + static ReflectedLightIndirectSpecular = 'ReflectedLightIndirectSpecular'; + static ReflectedLightDirectDiffuse = 'ReflectedLightDirectDiffuse'; + static ReflectedLightDirectSpecular = 'ReflectedLightDirectSpecular'; + + static MaterialDiffuseColor = 'MaterialDiffuseColor'; + + static MaterialSpecularShininess = 'MaterialSpecularShininess'; + static MaterialSpecularColor = 'MaterialSpecularColor'; + + constructor() { + + this.keywords = [ + // consts + NodeKeywords.PI, + NodeKeywords.RECIPROCAL_PI, + // variadic macros + NodeKeywords.Saturate, + NodeKeywords.WhiteComplement, + // nodes + NodeKeywords.PositionLocal, + NodeKeywords.PositionWorld, + NodeKeywords.PositionView, + NodeKeywords.PositionViewDirection, + NodeKeywords.NormalLocal, + NodeKeywords.NormalWorld, + NodeKeywords.NormalView, + // vars -> float + NodeKeywords.MaterialSpecularShininess, + // vars -> vec3 + NodeKeywords.Irradiance, + NodeKeywords.ReflectedLightIndirectDiffuse, + NodeKeywords.ReflectedLightIndirectSpecular, + NodeKeywords.ReflectedLightDirectDiffuse, + NodeKeywords.ReflectedLightDirectSpecular, + NodeKeywords.MaterialSpecularColor, + // vars -> vec4 + NodeKeywords.MaterialDiffuseColor + ]; + + this.nodes = []; + + } + + getNode( name ) { + + let node = this.nodes[ name ]; + + if ( node === undefined ) { + + switch ( name ) { + + case NodeKeywords.PI: + + node = PI; + + break; + + case NodeKeywords.RECIPROCAL_PI: + + node = RECIPROCAL_PI; + + break; + + case NodeKeywords.Saturate: + + node = saturateMacro; + + break; + + case NodeKeywords.WhiteComplement: + + node = whiteComplementMacro; + + break; + + case NodeKeywords.PositionLocal: + + node = new VarNode( new PositionNode( PositionNode.LOCAL ), name ); + + break; + + case NodeKeywords.PositionWorld: + + node = new VarNode( new PositionNode( PositionNode.WORLD ), name ); + + break; + + case NodeKeywords.PositionView: + + node = new VarNode( new PositionNode( PositionNode.VIEW ), name ); + + break; + + case NodeKeywords.PositionViewDirection: + + node = new VarNode( new PositionNode( PositionNode.VIEW_DIRECTION ), name ); + + break; + + case NodeKeywords.NormalLocal: + + node = new VarNode( new NormalNode( NormalNode.LOCAL ), name ); + + break; + + case NodeKeywords.NormalWorld: + + node = new VarNode( new NormalNode( NormalNode.WORLD ), name ); + + break; + + case NodeKeywords.NormalView: + + node = new VarNode( new NormalNode( NormalNode.VIEW ), name ); + + break; + + // floats properties + case NodeKeywords.MaterialSpecularShininess: + + node = new PropertyNode( name, 'float' ); + + break; + + // vec3 properties + case NodeKeywords.Irradiance: + case NodeKeywords.ReflectedLightIndirectDiffuse: + case NodeKeywords.ReflectedLightIndirectSpecular: + case NodeKeywords.ReflectedLightDirectDiffuse: + case NodeKeywords.ReflectedLightDirectSpecular: + case NodeKeywords.MaterialSpecularColor: + + node = new PropertyNode( name, 'vec3' ); + + break; + + // vec4 properties + case NodeKeywords.MaterialDiffuseColor: + + node = new PropertyNode( name, 'vec4' ); + + break; + + } + + if ( node !== undefined ) { + + this.nodes[ name ] = node; + + } + + } + + return node; + + } + + parse( code ) { + + const keywordNames = this.keywords; + + const regExp = new RegExp( `\\b${keywordNames.join( '\\b|\\b' )}\\b`, 'g' ); + + const codeKeywords = code.match( regExp ); + + const keywords = []; + + if ( codeKeywords !== null ) { + + for ( const keyword of codeKeywords ) { + + const node = this.getNode( keyword ); + + if ( keywords.indexOf( node ) === - 1 ) { + + keywords.push( node ); + + } + + } + + } + + return keywords; + + } + + include( builder, code ) { + + const keywords = this.parse( code ); + + for ( const keywordNode of keywords ) { + + keywordNode.build( builder ); + + } + + } + +} + +export default NodeKeywords; diff --git a/examples/jsm/renderers/nodes/core/NodeVar.js b/examples/jsm/renderers/nodes/core/NodeVar.js new file mode 100644 index 00000000000000..ed791a79e920f5 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/NodeVar.js @@ -0,0 +1,15 @@ +class NodeVar { + + constructor( name, type, snippet = '' ) { + + this.name = name; + this.type = type; + this.snippet = snippet; + + Object.defineProperty( this, 'isNodeVar', { value: true } ); + + } + +} + +export default NodeVar; diff --git a/examples/jsm/renderers/nodes/core/PropertyNode.js b/examples/jsm/renderers/nodes/core/PropertyNode.js new file mode 100644 index 00000000000000..f74cd076a83574 --- /dev/null +++ b/examples/jsm/renderers/nodes/core/PropertyNode.js @@ -0,0 +1,29 @@ +import Node from './Node.js'; + +class PropertyNode extends Node { + + constructor( name, type ) { + + super(); + + this.name = name; + this.type = type; + + } + + generate( builder, output ) { + + const type = this.getType( builder ); + + const nodeVary = builder.getVarFromNode( this, type ); + nodeVary.name = this.name; + + const propertyName = builder.getPropertyName( nodeVary ); + + return builder.format( propertyName, type, output ); + + } + +} + +export default PropertyNode; diff --git a/examples/jsm/renderers/nodes/core/VarNode.js b/examples/jsm/renderers/nodes/core/VarNode.js new file mode 100644 index 00000000000000..6ad515d6cc1e5d --- /dev/null +++ b/examples/jsm/renderers/nodes/core/VarNode.js @@ -0,0 +1,43 @@ +import Node from './Node.js'; + +class VarNode extends Node { + + constructor( value, name = '' ) { + + super(); + + this.value = value; + this.name = name; + + } + + getType( builder ) { + + return this.value.getType( builder ); + + } + + generate( builder, output ) { + + const snippet = this.value.build( builder ); + + const type = this.getType( builder ); + + const nodeVary = builder.getVarFromNode( this, type ); + nodeVary.snippet = snippet; + + if ( this.name !== '' ) { + + nodeVary.name = this.name; + + } + + const propertyName = builder.getPropertyName( nodeVary ); + + return builder.format( propertyName, type, output ); + + } + +} + +export default VarNode; diff --git a/examples/jsm/renderers/nodes/functions/BSDFs.js b/examples/jsm/renderers/nodes/functions/BSDFs.js new file mode 100644 index 00000000000000..23329ad89fd2fa --- /dev/null +++ b/examples/jsm/renderers/nodes/functions/BSDFs.js @@ -0,0 +1,118 @@ +import FunctionNode from '../core/FunctionNode.js'; + +export const F_Schlick = new FunctionNode( ` +vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) { + + // Original approximation by Christophe Schlick '94 + // float fresnel = pow( 1.0 - dotLH, 5.0 ); + + // Optimized variant (presented by Epic at SIGGRAPH '13) + // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH ); + + return ( 1.0 - specularColor ) * fresnel + specularColor; + +}` ); // validated + +export const G_BlinnPhong_Implicit = new FunctionNode( ` +float G_BlinnPhong_Implicit() { + + // ( const in float dotNL, const in float dotNV ) + // geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v) + + return 0.25; + +}` ); // validated + +export const D_BlinnPhong = new FunctionNode( ` +float D_BlinnPhong( const in float shininess, const in float dotNH ) { + + return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess ); + +}` ); // validated + +export const BRDF_Diffuse_Lambert = new FunctionNode( ` +vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) { + + return RECIPROCAL_PI * diffuseColor; + +}` ); // validated + +export const BRDF_Specular_BlinnPhong = new FunctionNode( ` +vec3 BRDF_Specular_BlinnPhong( vec3 lightDirection, vec3 specularColor, float shininess ) { + + vec3 halfDir = normalize( lightDirection + PositionViewDirection ); + + //float dotNL = saturate( dot( NormalView, lightDirection ) ); + //float dotNV = saturate( dot( NormalView, PositionViewDirection ) ); + float dotNH = saturate( dot( NormalView, halfDir ) ); + float dotLH = saturate( dot( lightDirection, halfDir ) ); + + vec3 F = F_Schlick( specularColor, dotLH ); + + float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ ); + + float D = D_BlinnPhong( shininess, dotNH ); + + return F * ( G * D ); + +}` ).setIncludes( [ F_Schlick, G_BlinnPhong_Implicit, D_BlinnPhong ] ); // validated + +export const punctualLightIntensityToIrradianceFactor = new FunctionNode( ` +float punctualLightIntensityToIrradianceFactor( float lightDistance, float cutoffDistance, float decayExponent ) { + +#if defined ( PHYSICALLY_CORRECT_LIGHTS ) + + // based upon Frostbite 3 Moving to Physically-based Rendering + // page 32, equation 26: E[window1] + // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf + // this is intended to be used on spot and point lights who are represented as luminous intensity + // but who must be converted to luminous irradiance for surface lighting calculation + float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 ); + + if( cutoffDistance > 0.0 ) { + + distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) ); + + } + + return distanceFalloff; + +#else + + if( cutoffDistance > 0.0 && decayExponent > 0.0 ) { + + return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent ); + + } + + return 1.0; + +#endif + +}` ); + +export const RE_Direct_BlinnPhong = new FunctionNode( ` +void RE_Direct_BlinnPhong( vec3 lightDirection, vec3 lightColor ) { + + float dotNL = saturate( dot( NormalView, lightDirection ) ); + vec3 irradiance = dotNL * lightColor; + +#ifndef PHYSICALLY_CORRECT_LIGHTS + + irradiance *= PI; // punctual light + +#endif + + ReflectedLightDirectDiffuse += irradiance * BRDF_Diffuse_Lambert( MaterialDiffuseColor.rgb ); + + ReflectedLightDirectSpecular += irradiance * BRDF_Specular_BlinnPhong( lightDirection, MaterialSpecularColor, MaterialSpecularShininess ); + +}` ).setIncludes( [ BRDF_Diffuse_Lambert, BRDF_Specular_BlinnPhong ] ); + +export const RE_IndirectDiffuse_BlinnPhong = new FunctionNode( ` +void RE_IndirectDiffuse_BlinnPhong( ) { + + ReflectedLightIndirectDiffuse += Irradiance * BRDF_Diffuse_Lambert( MaterialDiffuseColor.rgb ); + +}` ).setIncludes( [ BRDF_Diffuse_Lambert ] ); diff --git a/examples/jsm/renderers/nodes/functions/MathFunctions.js b/examples/jsm/renderers/nodes/functions/MathFunctions.js new file mode 100644 index 00000000000000..c9faaa03765061 --- /dev/null +++ b/examples/jsm/renderers/nodes/functions/MathFunctions.js @@ -0,0 +1,47 @@ +import { PI } from '../consts/MathConsts.js'; +import CodeNode from '../core/CodeNode.js'; +import FunctionNode from '../core/FunctionNode.js'; + +// variadic macros +export const saturateMacro = new CodeNode( '#define saturate(a) clamp( a, 0.0, 1.0 )' ); +export const whiteComplementMacro = new CodeNode( '#define whiteComplement(a) ( 1.0 - saturate( a ) )' ); + +export const transformDirection = new FunctionNode( ` +vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + +}` ); + +export const inverseTransformDirection = new FunctionNode( ` +vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) { + + // dir can be either a direction vector or a normal vector + // upper-left 3x3 of matrix is assumed to be orthogonal + + return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz ); + +}` ); + +export const pow2 = new FunctionNode( 'float pow2( const in float x ) { return x*x; }' ); +export const pow3 = new FunctionNode( 'float pow3( const in float x ) { return x*x*x; }' ); +export const pow4 = new FunctionNode( 'float pow4( const in float x ) { float x2 = x*x; return x2*x2; }' ); + +export const average = new FunctionNode( 'float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }' ); + +export const max3 = new FunctionNode( 'float max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }' ); + +// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range. +// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ +export const rand = new FunctionNode( ` +highp float rand( const in vec2 uv ) { + + const highp float a = 12.9898, b = 78.233, c = 43758.5453; + + highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, 3.141592653589793 ); + + return fract(sin(sn) * c); + +}` ).setIncludes( [ PI ] ); + +export const precisionSafeLength = new FunctionNode( 'float precisionSafeLength( vec3 v ) { return length( v ); }' ); diff --git a/examples/jsm/renderers/nodes/inputs/ColorNode.js b/examples/jsm/renderers/nodes/inputs/ColorNode.js index cabe1a68387fc0..9c40609345ed8e 100644 --- a/examples/jsm/renderers/nodes/inputs/ColorNode.js +++ b/examples/jsm/renderers/nodes/inputs/ColorNode.js @@ -1,5 +1,5 @@ import InputNode from '../core/InputNode.js'; -import { Color } from '../../../../../build/three.module.js'; +import { Color } from 'three'; class ColorNode extends InputNode { diff --git a/examples/jsm/renderers/nodes/inputs/Matrix3Node.js b/examples/jsm/renderers/nodes/inputs/Matrix3Node.js index fc6bf09bd2df35..bcceb4f9215955 100644 --- a/examples/jsm/renderers/nodes/inputs/Matrix3Node.js +++ b/examples/jsm/renderers/nodes/inputs/Matrix3Node.js @@ -1,5 +1,5 @@ import InputNode from '../core/InputNode.js'; -import { Matrix3 } from '../../../../../build/three.module.js'; +import { Matrix3 } from 'three'; class Matrix3Node extends InputNode { diff --git a/examples/jsm/renderers/nodes/inputs/Matrix4Node.js b/examples/jsm/renderers/nodes/inputs/Matrix4Node.js index 07796a390f83b7..be47449a2fce46 100644 --- a/examples/jsm/renderers/nodes/inputs/Matrix4Node.js +++ b/examples/jsm/renderers/nodes/inputs/Matrix4Node.js @@ -1,5 +1,5 @@ import InputNode from '../core/InputNode.js'; -import { Matrix4 } from '../../../../../build/three.module.js'; +import { Matrix4 } from 'three'; class Matrix4Node extends InputNode { diff --git a/examples/jsm/renderers/nodes/inputs/TextureNode.js b/examples/jsm/renderers/nodes/inputs/TextureNode.js index dc38c972d53a43..3c4dc6e7c70dfc 100644 --- a/examples/jsm/renderers/nodes/inputs/TextureNode.js +++ b/examples/jsm/renderers/nodes/inputs/TextureNode.js @@ -3,7 +3,7 @@ import UVNode from '../accessors/UVNode.js'; class TextureNode extends InputNode { - constructor( value, uv = new UVNode() ) { + constructor( value = null, uv = new UVNode() ) { super( 'texture' ); diff --git a/examples/jsm/renderers/nodes/inputs/Vector2Node.js b/examples/jsm/renderers/nodes/inputs/Vector2Node.js index defe29fc9f0a2a..da8a46492e2e82 100644 --- a/examples/jsm/renderers/nodes/inputs/Vector2Node.js +++ b/examples/jsm/renderers/nodes/inputs/Vector2Node.js @@ -1,5 +1,5 @@ import InputNode from '../core/InputNode.js'; -import { Vector2 } from '../../../../../build/three.module.js'; +import { Vector2 } from 'three'; class Vector2Node extends InputNode { diff --git a/examples/jsm/renderers/nodes/inputs/Vector3Node.js b/examples/jsm/renderers/nodes/inputs/Vector3Node.js index da4632a503455d..a87741e12756c7 100644 --- a/examples/jsm/renderers/nodes/inputs/Vector3Node.js +++ b/examples/jsm/renderers/nodes/inputs/Vector3Node.js @@ -1,5 +1,5 @@ import InputNode from '../core/InputNode.js'; -import { Vector3 } from '../../../../../build/three.module.js'; +import { Vector3 } from 'three'; class Vector3Node extends InputNode { diff --git a/examples/jsm/renderers/nodes/inputs/Vector4Node.js b/examples/jsm/renderers/nodes/inputs/Vector4Node.js index af56e257430fd8..c933bdaa57fbc6 100644 --- a/examples/jsm/renderers/nodes/inputs/Vector4Node.js +++ b/examples/jsm/renderers/nodes/inputs/Vector4Node.js @@ -1,5 +1,5 @@ import InputNode from '../core/InputNode.js'; -import { Vector4 } from '../../../../../build/three.module.js'; +import { Vector4 } from 'three'; class Vector4Node extends InputNode { diff --git a/examples/jsm/renderers/nodes/lights/LightContextNode.js b/examples/jsm/renderers/nodes/lights/LightContextNode.js new file mode 100644 index 00000000000000..275c816f3b6ea9 --- /dev/null +++ b/examples/jsm/renderers/nodes/lights/LightContextNode.js @@ -0,0 +1,60 @@ +import ContextNode from '../core/ContextNode.js'; +import { RE_Direct_BlinnPhong, RE_IndirectDiffuse_BlinnPhong } from '../functions/BSDFs.js'; + +class LightContextNode extends ContextNode { + + constructor( node ) { + + super( node ); + + } + + getType( /*builder*/ ) { + + return 'vec3'; + + } + + generate( builder, output ) { + + const type = this.getType( builder ); + + const material = builder.material; + + let RE_Direct = null; + let RE_IndirectDiffuse = null; + + if ( material.isMeshPhongMaterial === true ) { + + RE_Direct = RE_Direct_BlinnPhong; + RE_IndirectDiffuse = RE_IndirectDiffuse_BlinnPhong; + + } + + if ( RE_Direct !== null ) { + + this.setParameter( 'RE_Direct', RE_Direct ); + this.setParameter( 'RE_IndirectDiffuse', RE_IndirectDiffuse ); + + } + + const resetTotalLight = 'Irradiance = vec3( 0.0 ); ReflectedLightDirectDiffuse = vec3( 0.0 ); ReflectedLightDirectSpecular = vec3( 0.0 );'; + const resultTotalLight = 'ReflectedLightDirectDiffuse + ReflectedLightDirectSpecular'; + + // include keywords + + builder.getContextParameter( 'keywords' ).include( builder, resetTotalLight ); + + // add code + + builder.addFlowCode( resetTotalLight ); + + super.generate( builder, output ); + + return builder.format( resultTotalLight, type, output ); + + } + +} + +export default LightContextNode; diff --git a/examples/jsm/renderers/nodes/lights/LightNode.js b/examples/jsm/renderers/nodes/lights/LightNode.js new file mode 100644 index 00000000000000..ea447f7dfe24c6 --- /dev/null +++ b/examples/jsm/renderers/nodes/lights/LightNode.js @@ -0,0 +1,82 @@ +import Node from '../core/Node.js'; +import Object3DNode from '../accessors/Object3DNode.js'; +import PositionNode from '../accessors/PositionNode.js'; +import ColorNode from '../inputs/ColorNode.js'; +import FloatNode from '../inputs/FloatNode.js'; +import OperatorNode from '../math/OperatorNode.js'; +import MathNode from '../math/MathNode.js'; +import { NodeUpdateType } from '../core/constants.js'; +import { punctualLightIntensityToIrradianceFactor } from '../functions/BSDFs.js'; + +import { Color } from 'three'; + +class LightNode extends Node { + + constructor( light = null ) { + + super( 'vec3' ); + + this.updateType = NodeUpdateType.Object; + + this.light = light; + + this.color = new ColorNode( new Color() ); + + this.lightCutoffDistance = new FloatNode( 0 ); + this.lightDecayExponent = new FloatNode( 0 ); + + this.lightPositionView = new Object3DNode( Object3DNode.VIEW_POSITION ); + this.positionView = new PositionNode( PositionNode.VIEW ); + + this.lVector = new OperatorNode( '-', this.lightPositionView, this.positionView ); + + this.lightDirection = new MathNode( MathNode.NORMALIZE, this.lVector ); + + this.lightDistance = new MathNode( MathNode.LENGTH, this.lVector ); + + this.lightIntensity = punctualLightIntensityToIrradianceFactor.call( { + lightDistance: this.lightDistance, + cutoffDistance: this.lightCutoffDistance, + decayExponent: this.lightDecayExponent + } ); + + this.lightColor = new OperatorNode( '*', this.color, this.lightIntensity ); + + } + + update( /* frame */ ) { + + this.color.value.copy( this.light.color ).multiplyScalar( this.light.intensity ); + this.lightCutoffDistance.value = this.light.distance; + this.lightDecayExponent.value = this.light.decay; + + } + + generate( builder, output ) { + + this.lightPositionView.object3d = this.light; + + const directFunctionNode = builder.getContextParameter( 'RE_Direct' ); + const indirectDiffuseFunctionNode = builder.getContextParameter( 'RE_IndirectDiffuse' ); + + const directFunctionCallNode = directFunctionNode.call( { + lightDirection: this.lightDirection, + lightColor: this.lightColor + } ); + + const indirectDiffuseFunctionCallNode = indirectDiffuseFunctionNode.call( { + lightDirection: this.lightDirection, + lightColor: this.lightColor + } ); + + builder.addFlowCode( directFunctionCallNode.build( builder ) ); + + builder.addFlowCode( indirectDiffuseFunctionCallNode.build( builder ) ); + + return this.color.build( builder, output ); + + } + +} + +export default LightNode; diff --git a/examples/jsm/renderers/nodes/lights/LightsNode.js b/examples/jsm/renderers/nodes/lights/LightsNode.js new file mode 100644 index 00000000000000..acb377158eb655 --- /dev/null +++ b/examples/jsm/renderers/nodes/lights/LightsNode.js @@ -0,0 +1,44 @@ +import Node from '../core/Node.js'; +import LightNode from './LightNode.js'; + +class LightsNode extends Node { + + constructor( lightNodes = [] ) { + + super( 'vec3' ); + + this.lightNodes = lightNodes; + + } + + generate( builder, output ) { + + const lightNodes = this.lightNodes; + + for ( const lightNode of lightNodes ) { + + lightNode.build( builder ); + + } + + return builder.format( 'vec3( 0.0 )', this.getType( builder ), output ); + + } + + static fromLights( lights ) { + + const lightNodes = []; + + for ( const light of lights ) { + + lightNodes.push( new LightNode( light ) ); + + } + + return new LightsNode( lightNodes ); + + } + +} + +export default LightsNode; diff --git a/examples/jsm/renderers/nodes/math/MathNode.js b/examples/jsm/renderers/nodes/math/MathNode.js index 7b9b2bbdfb356f..4b021b8ee8d00d 100644 --- a/examples/jsm/renderers/nodes/math/MathNode.js +++ b/examples/jsm/renderers/nodes/math/MathNode.js @@ -3,7 +3,8 @@ import Node from '../core/Node.js'; class MathNode extends Node { static NORMALIZE = 'normalize'; - static INVERSE_TRANSFORM_DIRETION = 'inverseTransformDirection'; + static NEGATE = 'negate'; + static LENGTH = 'length'; constructor( method, a, b = null ) { @@ -16,60 +17,62 @@ class MathNode extends Node { } - getType( builder ) { - - const method = this.method; - - if ( method === MathNode.INVERSE_TRANSFORM_DIRETION ) { - - return 'vec3'; - - } else { + getInputType( builder ) { - const typeA = this.a.getType( builder ); + const typeA = this.a.getType( builder ); - if ( this.b !== null ) { + if ( this.b !== null ) { - if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) { + const typeB = this.b.getType( builder ); - // anytype x anytype: use the greater length vector + if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) { - return typeB; + // anytype x anytype: use the greater length vector - } + return typeB; } - return typeA; - } + return typeA; + } - generate( builder, output ) { + getType( builder ) { const method = this.method; - const type = this.getType( builder ); - let a = null, b = null; + if ( method === MathNode.LENGTH ) { - if ( method === MathNode.INVERSE_TRANSFORM_DIRETION ) { + return 'float'; - a = this.a.build( builder, 'vec3' ); - b = this.b.build( builder, 'mat4' ); + } else if ( + method === MathNode.TRANSFORM_DIRETION || + method === MathNode.INVERSE_TRANSFORM_DIRETION + ) { - // add in FunctionNode later - return `normalize( ( vec4( ${a}, 0.0 ) * ${b} ).xyz )`; + return 'vec3'; } else { - a = this.a.build( builder, type ); + return this.getInputType( builder ); - if ( this.b !== null ) { + } - b = this.b.build( builder, type ); + } - } + generate( builder, output ) { + + const method = this.method; + const type = this.getInputType( builder ); + + const a = this.a.build( builder, type ); + let b = null; + + if ( this.b !== null ) { + + b = this.b.build( builder, type ); } @@ -79,7 +82,15 @@ class MathNode extends Node { } else { - return builder.format( `${method}( ${a} )`, type, output ); + if ( method === MathNode.NEGATE ) { + + return builder.format( `( -${a} )`, type, output ); + + } else { + + return builder.format( `${method}( ${a} )`, type, output ); + + } } diff --git a/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js b/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js new file mode 100644 index 00000000000000..4d6c9a5ac5e4ef --- /dev/null +++ b/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js @@ -0,0 +1,123 @@ +import NodeBuilder from '../../nodes/core/NodeBuilder.js'; +import NodeSlot from '../../nodes/core/NodeSlot.js'; + +class WebGLNodeBuilder extends NodeBuilder { + + constructor( material, renderer, properties ) { + + super( material, renderer ); + + this.properties = properties; + + this._parseMaterial(); + + } + + _parseMaterial() { + + const material = this.material; + + // parse inputs + + if ( material.colorNode !== undefined ) { + + this.addSlot( 'fragment', new NodeSlot( material.colorNode, 'COLOR', 'vec4' ) ); + + } + + } + + getVaryFromNode( node, type ) { + + const vary = super.getVaryFromNode( node, type ); + + if ( node.isUVNode ) { + + vary.name = 'vUv'; + + } + + return vary; + + } + + getTexture( textureProperty, uvSnippet ) { + + return `sRGBToLinear( texture2D( ${textureProperty}, ${uvSnippet} ) )`; + + } + + getUniformsHeaderSnippet( shaderStage ) { + + const uniforms = this.uniforms[ shaderStage ]; + + let snippet = ''; + + for ( const uniform of uniforms ) { + + if ( uniform.type === 'texture' ) { + + snippet += `uniform sampler2D ${uniform.name};`; + + } else { + + const vectorType = this.getVectorType( uniform.type ); + + snippet += `uniform ${vectorType} ${uniform.name};`; + + } + + } + + return snippet; + + } + + getAttributesHeaderSnippet( /*shaderStage*/ ) { + + } + + getVarsHeaderSnippet( /*shaderStage*/ ) { + + } + + getVarsBodySnippet( /*shaderStage*/ ) { + + } + + getVarysHeaderSnippet( /*shaderStage*/ ) { + + } + + getVarysBodySnippet( /*shaderStage*/ ) { + + } + + composeUniforms() { + + const uniforms = this.uniforms[ 'fragment' ]; + + for ( const uniform of uniforms ) { + + this.properties.uniforms[ uniform.name ] = uniform; + + } + + } + + build() { + + super.build(); + + this.properties.defines[ 'NODE_HEADER_UNIFORMS' ] = this.defines[ 'fragment' ][ 'NODE_HEADER_UNIFORMS' ]; + this.properties.defines[ 'NODE_COLOR' ] = this.defines[ 'fragment' ][ 'NODE_COLOR' ]; + + this.composeUniforms(); + + return this; + + } + +} + +export { WebGLNodeBuilder }; diff --git a/examples/jsm/renderers/webgl/nodes/WebGLNodes.js b/examples/jsm/renderers/webgl/nodes/WebGLNodes.js new file mode 100644 index 00000000000000..c922866807746b --- /dev/null +++ b/examples/jsm/renderers/webgl/nodes/WebGLNodes.js @@ -0,0 +1,44 @@ +import { WebGLNodeBuilder } from './WebGLNodeBuilder.js'; + +import { Material } from '../../../../../build/three.module.js'; + +function addCodeAfterSnippet( source, snippet, code ) { + + const index = source.indexOf( snippet ); + + if ( index !== - 1 ) { + + const start = source.substring( 0, index + snippet.length ); + const end = source.substring( index + snippet.length ); + + return `${start}\n${code}\n${end}`; + + } + + return source; + +} + +Material.prototype.onBuild = function ( parameters, renderer ) { + + new WebGLNodeBuilder( this, renderer, parameters ).build(); + + let fragmentShader = parameters.fragmentShader; + + fragmentShader = addCodeAfterSnippet( fragmentShader, '#include ', + `#ifdef NODE_HEADER_UNIFORMS + + NODE_HEADER_UNIFORMS + + #endif` ); + + fragmentShader = addCodeAfterSnippet( fragmentShader, '#include ', + `#ifdef NODE_COLOR + + diffuseColor = NODE_COLOR; + + #endif` ); + + parameters.fragmentShader = fragmentShader; + +}; diff --git a/examples/jsm/renderers/webgpu/WebGPUBindings.js b/examples/jsm/renderers/webgpu/WebGPUBindings.js index 1b53a0e8b39d68..95f174515f727c 100644 --- a/examples/jsm/renderers/webgpu/WebGPUBindings.js +++ b/examples/jsm/renderers/webgpu/WebGPUBindings.js @@ -123,7 +123,7 @@ class WebGPUBindings { } else if ( binding.isSampler ) { - const texture = binding.texture; + const texture = binding.getTexture(); textures.updateSampler( texture ); @@ -138,7 +138,7 @@ class WebGPUBindings { } else if ( binding.isSampledTexture ) { - const texture = binding.texture; + const texture = binding.getTexture(); const forceUpdate = textures.updateTexture( texture ); const textureGPU = textures.getTextureGPU( texture ); diff --git a/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js b/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js index a3a36fabc0accf..d1d15e7978ea38 100644 --- a/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js +++ b/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js @@ -41,13 +41,13 @@ class WebGPUComputePipelines { // - const computeStage = { + const compute = { module: moduleCompute, entryPoint: 'main' }; pipeline = device.createComputePipeline( { - computeStage: computeStage + compute: compute } ); this.pipelines.set( param, pipeline ); diff --git a/examples/jsm/renderers/webgpu/WebGPURenderer.js b/examples/jsm/renderers/webgpu/WebGPURenderer.js index 05119fecbbffca..ef1e7d8cf58d09 100644 --- a/examples/jsm/renderers/webgpu/WebGPURenderer.js +++ b/examples/jsm/renderers/webgpu/WebGPURenderer.js @@ -189,10 +189,10 @@ class WebGPURenderer { this._renderPassDescriptor = { colorAttachments: [ { - attachment: null + view: null } ], depthStencilAttachment: { - attachment: null, + view: null, depthStoreOp: GPUStoreOp.Store, stencilStoreOp: GPUStoreOp.Store } @@ -246,24 +246,24 @@ class WebGPURenderer { const renderTargetProperties = this._properties.get( renderTarget ); - colorAttachment.attachment = renderTargetProperties.colorTextureGPU.createView(); - depthStencilAttachment.attachment = renderTargetProperties.depthTextureGPU.createView(); + colorAttachment.view = renderTargetProperties.colorTextureGPU.createView(); + depthStencilAttachment.view = renderTargetProperties.depthTextureGPU.createView(); } else { if ( this._parameters.antialias === true ) { - colorAttachment.attachment = this._colorBuffer.createView(); + colorAttachment.view = this._colorBuffer.createView(); colorAttachment.resolveTarget = this._swapChain.getCurrentTexture().createView(); } else { - colorAttachment.attachment = this._swapChain.getCurrentTexture().createView(); + colorAttachment.view = this._swapChain.getCurrentTexture().createView(); colorAttachment.resolveTarget = undefined; } - depthStencilAttachment.attachment = this._depthBuffer.createView(); + depthStencilAttachment.view = this._depthBuffer.createView(); } diff --git a/examples/jsm/renderers/webgpu/WebGPUSampledTexture.js b/examples/jsm/renderers/webgpu/WebGPUSampledTexture.js index 2b20127957727a..51353e8e7cb56a 100644 --- a/examples/jsm/renderers/webgpu/WebGPUSampledTexture.js +++ b/examples/jsm/renderers/webgpu/WebGPUSampledTexture.js @@ -18,6 +18,12 @@ class WebGPUSampledTexture extends WebGPUBinding { } + getTexture() { + + return this.texture; + + } + } WebGPUSampledTexture.prototype.isSampledTexture = true; diff --git a/examples/jsm/renderers/webgpu/WebGPUSampler.js b/examples/jsm/renderers/webgpu/WebGPUSampler.js index 19670bb04c8239..99a69daf6678dd 100644 --- a/examples/jsm/renderers/webgpu/WebGPUSampler.js +++ b/examples/jsm/renderers/webgpu/WebGPUSampler.js @@ -16,6 +16,12 @@ class WebGPUSampler extends WebGPUBinding { } + getTexture() { + + return this.texture; + + } + } WebGPUSampler.prototype.isSampler = true; diff --git a/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js b/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js index c8ee7f5ad06c1b..3e62b856d1af86 100644 --- a/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js +++ b/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js @@ -111,7 +111,7 @@ class WebGPUTextureUtils { const passEncoder = commandEncoder.beginRenderPass( { colorAttachments: [ { - attachment: dstView, + view: dstView, loadValue: [ 0, 0, 0, 0 ], } ], } ); diff --git a/examples/jsm/renderers/webgpu/nodes/ShaderLib.js b/examples/jsm/renderers/webgpu/nodes/ShaderLib.js index 7d2d39eb8e4038..821ace53c69623 100644 --- a/examples/jsm/renderers/webgpu/nodes/ShaderLib.js +++ b/examples/jsm/renderers/webgpu/nodes/ShaderLib.js @@ -1,41 +1,135 @@ const ShaderLib = { + common: { - vertexShader: `#version 450 -NODE_HEADER_ATTRIBUTES -NODE_HEADER_UNIFORMS -NODE_HEADER_VARYS + vertexShader: + `#version 450 + + NODE_HEADER_ATTRIBUTES + NODE_HEADER_UNIFORMS + NODE_HEADER_VARYS + + void main(){ + + NODE_BODY_VARYS + NODE_BODY_VARS + + gl_Position = NODE_MVP; + + }`, + + fragmentShader: + `#version 450 + + NODE_HEADER_ATTRIBUTES + NODE_HEADER_UNIFORMS + NODE_HEADER_VARYS + + layout(location = 0) out vec4 outColor; + + void main() { + + NODE_BODY_VARS + + MaterialDiffuseColor = vec4( 1.0 ); + + #ifdef NODE_COLOR + + NODE_CODE_COLOR + + MaterialDiffuseColor = NODE_COLOR; + + #endif + + #ifdef NODE_OPACITY + + NODE_CODE_OPACITY + + MaterialDiffuseColor.a *= NODE_OPACITY; + + #endif + + #ifdef NODE_LIGHT -void main(){ - NODE_BODY_VARYS - gl_Position = NODE_MVP; -}`, - fragmentShader: `#version 450 + NODE_CODE_LIGHT -NODE_HEADER_ATTRIBUTES -NODE_HEADER_UNIFORMS -NODE_HEADER_VARYS + outColor.rgb = NODE_LIGHT; + outColor.a = MaterialDiffuseColor.a; -layout(location = 0) out vec4 outColor; + #else -void main() { + outColor = MaterialDiffuseColor; - outColor = vec4( 1.0, 1.0, 1.0, 1.0 ); + #endif - #ifdef NODE_COLOR + }` - outColor = NODE_COLOR; + }, - #endif + phong: { - #ifdef NODE_OPACITY + vertexShader: + `#version 450 - outColor.a *= NODE_OPACITY; + NODE_HEADER_ATTRIBUTES + NODE_HEADER_UNIFORMS + NODE_HEADER_VARYS - #endif + void main(){ + + NODE_BODY_VARYS + NODE_BODY_VARS + + gl_Position = NODE_MVP; + + }`, + + fragmentShader: + `#version 450 + + NODE_HEADER_ATTRIBUTES + NODE_HEADER_UNIFORMS + NODE_HEADER_VARYS + + layout(location = 0) out vec4 outColor; + + void main() { + + NODE_BODY_VARS + + MaterialDiffuseColor = vec4( 1.0 ); + MaterialSpecularColor = vec3( 1.0 ); + MaterialSpecularShininess = 30.0; + + NODE_CODE_COLOR + MaterialDiffuseColor = NODE_COLOR; + + NODE_CODE_OPACITY + MaterialDiffuseColor.a *= NODE_OPACITY; + + NODE_CODE_SPECULAR + MaterialSpecularColor = NODE_SPECULAR; + + NODE_CODE_SHININESS + MaterialSpecularShininess = NODE_SHININESS; + + #ifdef NODE_LIGHT + + NODE_CODE_LIGHT + + outColor.rgb = NODE_LIGHT; + outColor.a = MaterialDiffuseColor.a; + + #else + + outColor = MaterialDiffuseColor; + + #endif + + }` -}` } + }; export default ShaderLib; diff --git a/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js b/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js index 9f00359630f36c..5bb577156c4db0 100644 --- a/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +++ b/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js @@ -3,13 +3,14 @@ import { FloatNodeUniform, Vector2NodeUniform, Vector3NodeUniform, Vector4NodeUniform, ColorNodeUniform, Matrix3NodeUniform, Matrix4NodeUniform } from './WebGPUNodeUniform.js'; -import WebGPUSampler from '../WebGPUSampler.js'; -import { WebGPUSampledTexture } from '../WebGPUSampledTexture.js'; +import WebGPUNodeSampler from './WebGPUNodeSampler.js'; +import { WebGPUNodeSampledTexture } from './WebGPUNodeSampledTexture.js'; import NodeSlot from '../../nodes/core/NodeSlot.js'; import NodeBuilder from '../../nodes/core/NodeBuilder.js'; +import MaterialNode from '../../nodes/accessors/MaterialNode.js'; import ModelViewProjectionNode from '../../nodes/accessors/ModelViewProjectionNode.js'; - +import LightContextNode from '../../nodes/lights/LightContextNode.js'; import ShaderLib from './ShaderLib.js'; class WebGPUNodeBuilder extends NodeBuilder { @@ -35,13 +36,26 @@ class WebGPUNodeBuilder extends NodeBuilder { // get shader - this.nativeShader = ShaderLib.common; + let shader = null; + + if ( material.isMeshPhongMaterial ) { + + shader = ShaderLib.phong; + + } else { + + shader = ShaderLib.common; + + } + + this.nativeShader = shader; // parse inputs - if ( material.isMeshBasicMaterial || material.isPointsMaterial || material.isLineBasicMaterial ) { + if ( material.isMeshPhongMaterial || material.isMeshBasicMaterial || material.isPointsMaterial || material.isLineBasicMaterial ) { const mvpNode = new ModelViewProjectionNode(); + const lightNode = material.lightNode; if ( material.positionNode !== undefined ) { @@ -55,12 +69,52 @@ class WebGPUNodeBuilder extends NodeBuilder { this.addSlot( 'fragment', new NodeSlot( material.colorNode, 'COLOR', 'vec4' ) ); + } else { + + this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.COLOR ), 'COLOR', 'vec4' ) ); + } if ( material.opacityNode !== undefined ) { this.addSlot( 'fragment', new NodeSlot( material.opacityNode, 'OPACITY', 'float' ) ); + } else { + + this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.OPACITY ), 'OPACITY', 'float' ) ); + + } + + if ( material.isMeshPhongMaterial ) { + + if ( material.specularNode !== undefined ) { + + this.addSlot( 'fragment', new NodeSlot( material.specularNode, 'SPECULAR', 'vec3' ) ); + + } else { + + this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.SPECULAR ), 'SPECULAR', 'vec3' ) ); + + } + + if ( material.shininessNode !== undefined ) { + + this.addSlot( 'fragment', new NodeSlot( material.shininessNode, 'SHININESS', 'float' ) ); + + } else { + + this.addSlot( 'fragment', new NodeSlot( new MaterialNode( MaterialNode.SHININESS ), 'SHININESS', 'float' ) ); + + } + + } + + if ( lightNode !== undefined ) { + + const lightContextNode = new LightContextNode( lightNode ); + + this.addSlot( 'fragment', new NodeSlot( lightContextNode, 'LIGHT', 'vec3' ) ); + } } @@ -75,7 +129,7 @@ class WebGPUNodeBuilder extends NodeBuilder { getPropertyName( node ) { - if ( node.isNodeUniform ) { + if ( node.isNodeUniform === true ) { const name = node.name; const type = node.type; @@ -117,8 +171,8 @@ class WebGPUNodeBuilder extends NodeBuilder { if ( type === 'texture' ) { - const sampler = new WebGPUSampler( `${uniformNode.name}_sampler`, uniformNode.value ); - const texture = new WebGPUSampledTexture( uniformNode.name, uniformNode.value ); + const sampler = new WebGPUNodeSampler( `${uniformNode.name}_sampler`, uniformNode.node ); + const texture = new WebGPUNodeSampledTexture( uniformNode.name, uniformNode.node ); // add first textures in sequence and group for last const lastBinding = bindings[ bindings.length - 1 ]; @@ -206,7 +260,7 @@ class WebGPUNodeBuilder extends NodeBuilder { const attribute = attributes[ index ]; - snippet += `layout(location = ${index}) in ${attribute.type} ${attribute.name};`; + snippet += `layout(location = ${index}) in ${attribute.type} ${attribute.name}; `; } @@ -228,7 +282,7 @@ class WebGPUNodeBuilder extends NodeBuilder { const vary = varys[ index ]; - snippet += `layout(location = ${index}) ${ioStage} ${vary.type} ${vary.name};`; + snippet += `layout(location = ${index}) ${ioStage} ${vary.type} ${vary.name}; `; } @@ -244,7 +298,45 @@ class WebGPUNodeBuilder extends NodeBuilder { for ( const vary of this.varys ) { - snippet += `${vary.name} = ${vary.snippet};`; + snippet += `${vary.name} = ${vary.snippet}; `; + + } + + } + + return snippet; + + } + + getVarsHeaderSnippet( shaderStage ) { + + let snippet = ''; + + const vars = this.vars[ shaderStage ]; + + for ( let index = 0; index < vars.length; index ++ ) { + + const variable = vars[ index ]; + + snippet += `${variable.type} ${variable.name}; `; + + } + + return snippet; + + } + + getVarsBodySnippet( shaderStage ) { + + let snippet = ''; + + const vars = this.vars[ shaderStage ]; + + for ( const variable of vars ) { + + if ( variable.snippet !== '' ) { + + snippet += `${variable.name} = ${variable.snippet}; `; } @@ -267,14 +359,14 @@ class WebGPUNodeBuilder extends NodeBuilder { if ( uniform.type === 'texture' ) { - snippet += `layout(set = 0, binding = ${index ++}) uniform sampler ${uniform.name}_sampler;`; - snippet += `layout(set = 0, binding = ${index ++}) uniform texture2D ${uniform.name};`; + snippet += `layout(set = 0, binding = ${index ++}) uniform sampler ${uniform.name}_sampler; `; + snippet += `layout(set = 0, binding = ${index ++}) uniform texture2D ${uniform.name}; `; } else { const vectorType = this.getVectorType( uniform.type ); - groupSnippet += `uniform ${vectorType} ${uniform.name};`; + groupSnippet += `uniform ${vectorType} ${uniform.name}; `; } @@ -282,7 +374,7 @@ class WebGPUNodeBuilder extends NodeBuilder { if ( groupSnippet ) { - snippet += `layout(set = 0, binding = ${index ++}) uniform NodeUniforms { ${groupSnippet} } nodeUniforms;`; + snippet += `layout(set = 0, binding = ${index ++}) uniform NodeUniforms { ${groupSnippet} } nodeUniforms; `; } @@ -307,6 +399,16 @@ class WebGPUNodeBuilder extends NodeBuilder { build() { + const keywords = this.getContextParameter( 'keywords' ); + + for ( const shaderStage of [ 'vertex', 'fragment' ] ) { + + this.shaderStage = shaderStage; + + keywords.include( this, this.nativeShader.fragmentShader ); + + } + super.build(); this.vertexShader = this.composeShaderCode( this.nativeShader.vertexShader, this.vertexShader ); diff --git a/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampledTexture.js b/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampledTexture.js new file mode 100644 index 00000000000000..b93784ab33557b --- /dev/null +++ b/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampledTexture.js @@ -0,0 +1,21 @@ +import { WebGPUSampledTexture } from '../WebGPUSampledTexture.js'; + +class WebGPUNodeSampledTexture extends WebGPUSampledTexture { + + constructor( name, textureNode ) { + + super( name, textureNode.value ); + + this.textureNode = textureNode; + + } + + getTexture() { + + return this.textureNode.value; + + } + +} + +export { WebGPUNodeSampledTexture }; diff --git a/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampler.js b/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampler.js new file mode 100644 index 00000000000000..c0a645b6ae4963 --- /dev/null +++ b/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampler.js @@ -0,0 +1,21 @@ +import WebGPUSampler from '../WebGPUSampler.js'; + +class WebGPUNodeSampler extends WebGPUSampler { + + constructor( name, textureNode ) { + + super( name, textureNode.value ); + + this.textureNode = textureNode; + + } + + getTexture() { + + return this.textureNode.value; + + } + +} + +export default WebGPUNodeSampler; diff --git a/examples/jsm/shaders/ACESFilmicToneMappingShader.js b/examples/jsm/shaders/ACESFilmicToneMappingShader.js index cba722dc41d861..1c8756c8c90175 100644 --- a/examples/jsm/shaders/ACESFilmicToneMappingShader.js +++ b/examples/jsm/shaders/ACESFilmicToneMappingShader.js @@ -6,7 +6,7 @@ * the scale factor of 1/0.6 is subjective. see discussion in #19621. */ -var ACESFilmicToneMappingShader = { +const ACESFilmicToneMappingShader = { uniforms: { @@ -15,76 +15,72 @@ var ACESFilmicToneMappingShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + #define saturate(a) clamp( a, 0.0, 1.0 ) - '#define saturate(a) clamp( a, 0.0, 1.0 )', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + uniform float exposure; - 'uniform float exposure;', + varying vec2 vUv; - 'varying vec2 vUv;', + vec3 RRTAndODTFit( vec3 v ) { - 'vec3 RRTAndODTFit( vec3 v ) {', + vec3 a = v * ( v + 0.0245786 ) - 0.000090537; + vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081; + return a / b; - ' vec3 a = v * ( v + 0.0245786 ) - 0.000090537;', - ' vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;', - ' return a / b;', + } - '}', - - 'vec3 ACESFilmicToneMapping( vec3 color ) {', + vec3 ACESFilmicToneMapping( vec3 color ) { // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT - ' const mat3 ACESInputMat = mat3(', - ' vec3( 0.59719, 0.07600, 0.02840 ),', // transposed from source - ' vec3( 0.35458, 0.90834, 0.13383 ),', - ' vec3( 0.04823, 0.01566, 0.83777 )', - ' );', + const mat3 ACESInputMat = mat3( + vec3( 0.59719, 0.07600, 0.02840 ), // transposed from source + vec3( 0.35458, 0.90834, 0.13383 ), + vec3( 0.04823, 0.01566, 0.83777 ) + ); // ODT_SAT => XYZ => D60_2_D65 => sRGB - ' const mat3 ACESOutputMat = mat3(', - ' vec3( 1.60475, -0.10208, -0.00327 ),', // transposed from source - ' vec3( -0.53108, 1.10813, -0.07276 ),', - ' vec3( -0.07367, -0.00605, 1.07602 )', - ' );', + const mat3 ACESOutputMat = mat3( + vec3( 1.60475, -0.10208, -0.00327 ), // transposed from source + vec3( -0.53108, 1.10813, -0.07276 ), + vec3( -0.07367, -0.00605, 1.07602 ) + ); - ' color = ACESInputMat * color;', + color = ACESInputMat * color; // Apply RRT and ODT - ' color = RRTAndODTFit( color );', + color = RRTAndODTFit( color ); - ' color = ACESOutputMat * color;', + color = ACESOutputMat * color; // Clamp to [0, 1] - ' return saturate( color );', - - '}', + return saturate( color ); - 'void main() {', + } - ' vec4 tex = texture2D( tDiffuse, vUv );', + void main() { - ' tex.rgb *= exposure / 0.6;', // pre-exposed, outside of the tone mapping function + vec4 tex = texture2D( tDiffuse, vUv ); - ' gl_FragColor = vec4( ACESFilmicToneMapping( tex.rgb ), tex.a );', + tex.rgb *= exposure / 0.6; // pre-exposed, outside of the tone mapping function - '}' + gl_FragColor = vec4( ACESFilmicToneMapping( tex.rgb ), tex.a ); - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/AfterimageShader.js b/examples/jsm/shaders/AfterimageShader.js index 3be2b9aac84759..a8a78d390d1325 100644 --- a/examples/jsm/shaders/AfterimageShader.js +++ b/examples/jsm/shaders/AfterimageShader.js @@ -4,7 +4,7 @@ * https://codepen.io/brunoimbrizi/pen/MoRJaN?page=1& */ -var AfterimageShader = { +const AfterimageShader = { uniforms: { @@ -14,46 +14,42 @@ var AfterimageShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float damp; - 'uniform float damp;', + uniform sampler2D tOld; + uniform sampler2D tNew; - 'uniform sampler2D tOld;', - 'uniform sampler2D tNew;', + varying vec2 vUv; - 'varying vec2 vUv;', + vec4 when_gt( vec4 x, float y ) { - 'vec4 when_gt( vec4 x, float y ) {', + return max( sign( x - y ), 0.0 ); - ' return max( sign( x - y ), 0.0 );', + } - '}', + void main() { - 'void main() {', + vec4 texelOld = texture2D( tOld, vUv ); + vec4 texelNew = texture2D( tNew, vUv ); - ' vec4 texelOld = texture2D( tOld, vUv );', - ' vec4 texelNew = texture2D( tNew, vUv );', + texelOld *= damp * when_gt( texelOld, 0.1 ); - ' texelOld *= damp * when_gt( texelOld, 0.1 );', + gl_FragColor = max(texelNew, texelOld); - ' gl_FragColor = max(texelNew, texelOld);', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/BasicShader.js b/examples/jsm/shaders/BasicShader.js index d895a5b85423a0..b88bfad1a198a9 100644 --- a/examples/jsm/shaders/BasicShader.js +++ b/examples/jsm/shaders/BasicShader.js @@ -2,29 +2,25 @@ * Simple test shader */ -var BasicShader = { +const BasicShader = { uniforms: {}, - vertexShader: [ + vertexShader: /* glsl */` - 'void main() {', + void main() { - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + void main() { - 'void main() {', + gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 ); - ' gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.5 );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/BleachBypassShader.js b/examples/jsm/shaders/BleachBypassShader.js index f2517697f6782a..cc5284ceeec103 100644 --- a/examples/jsm/shaders/BleachBypassShader.js +++ b/examples/jsm/shaders/BleachBypassShader.js @@ -4,7 +4,7 @@ * http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass */ -var BleachBypassShader = { +const BleachBypassShader = { uniforms: { @@ -13,51 +13,47 @@ var BleachBypassShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float opacity; - 'uniform float opacity;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 base = texture2D( tDiffuse, vUv ); - ' vec4 base = texture2D( tDiffuse, vUv );', + vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 ); + float lum = dot( lumCoeff, base.rgb ); + vec3 blend = vec3( lum ); - ' vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );', - ' float lum = dot( lumCoeff, base.rgb );', - ' vec3 blend = vec3( lum );', + float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) ); - ' float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );', + vec3 result1 = 2.0 * base.rgb * blend; + vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb ); - ' vec3 result1 = 2.0 * base.rgb * blend;', - ' vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );', + vec3 newColor = mix( result1, result2, L ); - ' vec3 newColor = mix( result1, result2, L );', + float A2 = opacity * base.a; + vec3 mixRGB = A2 * newColor.rgb; + mixRGB += ( ( 1.0 - A2 ) * base.rgb ); - ' float A2 = opacity * base.a;', - ' vec3 mixRGB = A2 * newColor.rgb;', - ' mixRGB += ( ( 1.0 - A2 ) * base.rgb );', + gl_FragColor = vec4( mixRGB, base.a ); - ' gl_FragColor = vec4( mixRGB, base.a );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/BlendShader.js b/examples/jsm/shaders/BlendShader.js index 0a2251889d6381..3445f14c3bdb4a 100644 --- a/examples/jsm/shaders/BlendShader.js +++ b/examples/jsm/shaders/BlendShader.js @@ -2,7 +2,7 @@ * Blend two textures */ -var BlendShader = { +const BlendShader = { uniforms: { @@ -13,38 +13,34 @@ var BlendShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float opacity; + uniform float mixRatio; - 'uniform float opacity;', - 'uniform float mixRatio;', + uniform sampler2D tDiffuse1; + uniform sampler2D tDiffuse2; - 'uniform sampler2D tDiffuse1;', - 'uniform sampler2D tDiffuse2;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 texel1 = texture2D( tDiffuse1, vUv ); + vec4 texel2 = texture2D( tDiffuse2, vUv ); + gl_FragColor = opacity * mix( texel1, texel2, mixRatio ); - ' vec4 texel1 = texture2D( tDiffuse1, vUv );', - ' vec4 texel2 = texture2D( tDiffuse2, vUv );', - ' gl_FragColor = opacity * mix( texel1, texel2, mixRatio );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/BokehShader.js b/examples/jsm/shaders/BokehShader.js index 6e853d3d092f5b..32a20875275e1e 100644 --- a/examples/jsm/shaders/BokehShader.js +++ b/examples/jsm/shaders/BokehShader.js @@ -4,7 +4,7 @@ * http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html */ -var BokehShader = { +const BokehShader = { defines: { 'DEPTH_PACKING': 1, @@ -24,122 +24,119 @@ var BokehShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ - '#include ', + #include - 'varying vec2 vUv;', + varying vec2 vUv; - 'uniform sampler2D tColor;', - 'uniform sampler2D tDepth;', + uniform sampler2D tColor; + uniform sampler2D tDepth; - 'uniform float maxblur;', // max blur amount - 'uniform float aperture;', // aperture - bigger values for shallower depth of field + uniform float maxblur; // max blur amount + uniform float aperture; // aperture - bigger values for shallower depth of field - 'uniform float nearClip;', - 'uniform float farClip;', + uniform float nearClip; + uniform float farClip; - 'uniform float focus;', - 'uniform float aspect;', + uniform float focus; + uniform float aspect; - '#include ', + #include - 'float getDepth( const in vec2 screenPosition ) {', - ' #if DEPTH_PACKING == 1', - ' return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );', - ' #else', - ' return texture2D( tDepth, screenPosition ).x;', - ' #endif', - '}', + float getDepth( const in vec2 screenPosition ) { + #if DEPTH_PACKING == 1 + return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) ); + #else + return texture2D( tDepth, screenPosition ).x; + #endif + } - 'float getViewZ( const in float depth ) {', - ' #if PERSPECTIVE_CAMERA == 1', - ' return perspectiveDepthToViewZ( depth, nearClip, farClip );', - ' #else', - ' return orthographicDepthToViewZ( depth, nearClip, farClip );', - ' #endif', - '}', + float getViewZ( const in float depth ) { + #if PERSPECTIVE_CAMERA == 1 + return perspectiveDepthToViewZ( depth, nearClip, farClip ); + #else + return orthographicDepthToViewZ( depth, nearClip, farClip ); + #endif + } - 'void main() {', + void main() { - ' vec2 aspectcorrect = vec2( 1.0, aspect );', + vec2 aspectcorrect = vec2( 1.0, aspect ); - ' float viewZ = getViewZ( getDepth( vUv ) );', + float viewZ = getViewZ( getDepth( vUv ) ); - ' float factor = ( focus + viewZ );', // viewZ is <= 0, so this is a difference equation + float factor = ( focus + viewZ ); // viewZ is <= 0, so this is a difference equation - ' vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );', + vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) ); - ' vec2 dofblur9 = dofblur * 0.9;', - ' vec2 dofblur7 = dofblur * 0.7;', - ' vec2 dofblur4 = dofblur * 0.4;', + vec2 dofblur9 = dofblur * 0.9; + vec2 dofblur7 = dofblur * 0.7; + vec2 dofblur4 = dofblur * 0.4; - ' vec4 col = vec4( 0.0 );', + vec4 col = vec4( 0.0 ); - ' col += texture2D( tColor, vUv.xy );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur );', + col += texture2D( tColor, vUv.xy ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur ); - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 );', + col += texture2D( tColor, vUv.xy + ( vec2( 0.15, 0.37 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.37, 0.15 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.37, -0.15 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.15, 0.37 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.37, 0.15 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.15, -0.37 ) * aspectcorrect ) * dofblur9 ); - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 );', + col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.40, 0.0 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur7 ); - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );', - ' col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 );', - - ' gl_FragColor = col / 41.0;', - ' gl_FragColor.a = 1.0;', - - '}' - - ].join( '\n' ) + col += texture2D( tColor, vUv.xy + ( vec2( 0.29, 0.29 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.4, 0.0 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.29, -0.29 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.0, -0.4 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.29, 0.29 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.4, 0.0 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 ); + col += texture2D( tColor, vUv.xy + ( vec2( 0.0, 0.4 ) * aspectcorrect ) * dofblur4 ); + + gl_FragColor = col / 41.0; + gl_FragColor.a = 1.0; + + }` }; diff --git a/examples/jsm/shaders/BokehShader2.js b/examples/jsm/shaders/BokehShader2.js index 9871d5377b93fc..7e8ff83159fa38 100644 --- a/examples/jsm/shaders/BokehShader2.js +++ b/examples/jsm/shaders/BokehShader2.js @@ -9,10 +9,7 @@ import { * * Requires #define RINGS and SAMPLES integers */ - - - -var BokehShader = { +const BokehShader = { uniforms: { @@ -51,313 +48,308 @@ var BokehShader = { }, - vertexShader: [ - - 'varying vec2 vUv;', + vertexShader: /* glsl */` - 'void main() {', + varying vec2 vUv; - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + void main() { - '}' + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - ].join( '\n' ), + }`, - fragmentShader: [ + fragmentShader: /* glsl */` - '#include ', + #include - 'varying vec2 vUv;', + varying vec2 vUv; - 'uniform sampler2D tColor;', - 'uniform sampler2D tDepth;', - 'uniform float textureWidth;', - 'uniform float textureHeight;', + uniform sampler2D tColor; + uniform sampler2D tDepth; + uniform float textureWidth; + uniform float textureHeight; - 'uniform float focalDepth; //focal distance value in meters, but you may use autofocus option below', - 'uniform float focalLength; //focal length in mm', - 'uniform float fstop; //f-stop value', - 'uniform bool showFocus; //show debug focus point and focal range (red = focal point, green = focal range)', + uniform float focalDepth; //focal distance value in meters, but you may use autofocus option below + uniform float focalLength; //focal length in mm + uniform float fstop; //f-stop value + uniform bool showFocus; //show debug focus point and focal range (red = focal point, green = focal range) - '/*', - 'make sure that these two values are the same for your camera, otherwise distances will be wrong.', - '*/', + /* + make sure that these two values are the same for your camera, otherwise distances will be wrong. + */ - 'uniform float znear; // camera clipping start', - 'uniform float zfar; // camera clipping end', + uniform float znear; // camera clipping start + uniform float zfar; // camera clipping end - '//------------------------------------------', - '//user variables', + //------------------------------------------ + //user variables - 'const int samples = SAMPLES; //samples on the first ring', - 'const int rings = RINGS; //ring count', + const int samples = SAMPLES; //samples on the first ring + const int rings = RINGS; //ring count - 'const int maxringsamples = rings * samples;', + const int maxringsamples = rings * samples; - 'uniform bool manualdof; // manual dof calculation', - 'float ndofstart = 1.0; // near dof blur start', - 'float ndofdist = 2.0; // near dof blur falloff distance', - 'float fdofstart = 1.0; // far dof blur start', - 'float fdofdist = 3.0; // far dof blur falloff distance', + uniform bool manualdof; // manual dof calculation + float ndofstart = 1.0; // near dof blur start + float ndofdist = 2.0; // near dof blur falloff distance + float fdofstart = 1.0; // far dof blur start + float fdofdist = 3.0; // far dof blur falloff distance - 'float CoC = 0.03; //circle of confusion size in mm (35mm film = 0.03mm)', + float CoC = 0.03; //circle of confusion size in mm (35mm film = 0.03mm) - 'uniform bool vignetting; // use optical lens vignetting', + uniform bool vignetting; // use optical lens vignetting - 'float vignout = 1.3; // vignetting outer border', - 'float vignin = 0.0; // vignetting inner border', - 'float vignfade = 22.0; // f-stops till vignete fades', + float vignout = 1.3; // vignetting outer border + float vignin = 0.0; // vignetting inner border + float vignfade = 22.0; // f-stops till vignete fades - 'uniform bool shaderFocus;', - '// disable if you use external focalDepth value', + uniform bool shaderFocus; + // disable if you use external focalDepth value - 'uniform vec2 focusCoords;', - '// autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right)', - '// if center of screen use vec2(0.5, 0.5);', + uniform vec2 focusCoords; + // autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right) + // if center of screen use vec2(0.5, 0.5); - 'uniform float maxblur;', - '//clamp value of max blur (0.0 = no blur, 1.0 default)', + uniform float maxblur; + //clamp value of max blur (0.0 = no blur, 1.0 default) - 'uniform float threshold; // highlight threshold;', - 'uniform float gain; // highlight gain;', + uniform float threshold; // highlight threshold; + uniform float gain; // highlight gain; - 'uniform float bias; // bokeh edge bias', - 'uniform float fringe; // bokeh chromatic aberration / fringing', + uniform float bias; // bokeh edge bias + uniform float fringe; // bokeh chromatic aberration / fringing - 'uniform bool noise; //use noise instead of pattern for sample dithering', + uniform bool noise; //use noise instead of pattern for sample dithering - 'uniform float dithering;', + uniform float dithering; - 'uniform bool depthblur; // blur the depth buffer', - 'float dbsize = 1.25; // depth blur size', + uniform bool depthblur; // blur the depth buffer + float dbsize = 1.25; // depth blur size - '/*', - 'next part is experimental', - 'not looking good with small sample and ring count', - 'looks okay starting from samples = 4, rings = 4', - '*/', + /* + next part is experimental + not looking good with small sample and ring count + looks okay starting from samples = 4, rings = 4 + */ - 'uniform bool pentagon; //use pentagon as bokeh shape?', - 'float feather = 0.4; //pentagon shape feather', + uniform bool pentagon; //use pentagon as bokeh shape? + float feather = 0.4; //pentagon shape feather - '//------------------------------------------', + //------------------------------------------ - 'float penta(vec2 coords) {', - ' //pentagonal shape', - ' float scale = float(rings) - 1.3;', - ' vec4 HS0 = vec4( 1.0, 0.0, 0.0, 1.0);', - ' vec4 HS1 = vec4( 0.309016994, 0.951056516, 0.0, 1.0);', - ' vec4 HS2 = vec4(-0.809016994, 0.587785252, 0.0, 1.0);', - ' vec4 HS3 = vec4(-0.809016994,-0.587785252, 0.0, 1.0);', - ' vec4 HS4 = vec4( 0.309016994,-0.951056516, 0.0, 1.0);', - ' vec4 HS5 = vec4( 0.0 ,0.0 , 1.0, 1.0);', + float penta(vec2 coords) { + //pentagonal shape + float scale = float(rings) - 1.3; + vec4 HS0 = vec4( 1.0, 0.0, 0.0, 1.0); + vec4 HS1 = vec4( 0.309016994, 0.951056516, 0.0, 1.0); + vec4 HS2 = vec4(-0.809016994, 0.587785252, 0.0, 1.0); + vec4 HS3 = vec4(-0.809016994,-0.587785252, 0.0, 1.0); + vec4 HS4 = vec4( 0.309016994,-0.951056516, 0.0, 1.0); + vec4 HS5 = vec4( 0.0 ,0.0 , 1.0, 1.0); - ' vec4 one = vec4( 1.0 );', + vec4 one = vec4( 1.0 ); - ' vec4 P = vec4((coords),vec2(scale, scale));', + vec4 P = vec4((coords),vec2(scale, scale)); - ' vec4 dist = vec4(0.0);', - ' float inorout = -4.0;', + vec4 dist = vec4(0.0); + float inorout = -4.0; - ' dist.x = dot( P, HS0 );', - ' dist.y = dot( P, HS1 );', - ' dist.z = dot( P, HS2 );', - ' dist.w = dot( P, HS3 );', + dist.x = dot( P, HS0 ); + dist.y = dot( P, HS1 ); + dist.z = dot( P, HS2 ); + dist.w = dot( P, HS3 ); - ' dist = smoothstep( -feather, feather, dist );', + dist = smoothstep( -feather, feather, dist ); - ' inorout += dot( dist, one );', + inorout += dot( dist, one ); - ' dist.x = dot( P, HS4 );', - ' dist.y = HS5.w - abs( P.z );', + dist.x = dot( P, HS4 ); + dist.y = HS5.w - abs( P.z ); - ' dist = smoothstep( -feather, feather, dist );', - ' inorout += dist.x;', + dist = smoothstep( -feather, feather, dist ); + inorout += dist.x; - ' return clamp( inorout, 0.0, 1.0 );', - '}', + return clamp( inorout, 0.0, 1.0 ); + } - 'float bdepth(vec2 coords) {', - ' // Depth buffer blur', - ' float d = 0.0;', - ' float kernel[9];', - ' vec2 offset[9];', + float bdepth(vec2 coords) { + // Depth buffer blur + float d = 0.0; + float kernel[9]; + vec2 offset[9]; - ' vec2 wh = vec2(1.0/textureWidth,1.0/textureHeight) * dbsize;', + vec2 wh = vec2(1.0/textureWidth,1.0/textureHeight) * dbsize; - ' offset[0] = vec2(-wh.x,-wh.y);', - ' offset[1] = vec2( 0.0, -wh.y);', - ' offset[2] = vec2( wh.x -wh.y);', + offset[0] = vec2(-wh.x,-wh.y); + offset[1] = vec2( 0.0, -wh.y); + offset[2] = vec2( wh.x -wh.y); - ' offset[3] = vec2(-wh.x, 0.0);', - ' offset[4] = vec2( 0.0, 0.0);', - ' offset[5] = vec2( wh.x, 0.0);', + offset[3] = vec2(-wh.x, 0.0); + offset[4] = vec2( 0.0, 0.0); + offset[5] = vec2( wh.x, 0.0); - ' offset[6] = vec2(-wh.x, wh.y);', - ' offset[7] = vec2( 0.0, wh.y);', - ' offset[8] = vec2( wh.x, wh.y);', + offset[6] = vec2(-wh.x, wh.y); + offset[7] = vec2( 0.0, wh.y); + offset[8] = vec2( wh.x, wh.y); - ' kernel[0] = 1.0/16.0; kernel[1] = 2.0/16.0; kernel[2] = 1.0/16.0;', - ' kernel[3] = 2.0/16.0; kernel[4] = 4.0/16.0; kernel[5] = 2.0/16.0;', - ' kernel[6] = 1.0/16.0; kernel[7] = 2.0/16.0; kernel[8] = 1.0/16.0;', + kernel[0] = 1.0/16.0; kernel[1] = 2.0/16.0; kernel[2] = 1.0/16.0; + kernel[3] = 2.0/16.0; kernel[4] = 4.0/16.0; kernel[5] = 2.0/16.0; + kernel[6] = 1.0/16.0; kernel[7] = 2.0/16.0; kernel[8] = 1.0/16.0; - ' for( int i=0; i<9; i++ ) {', - ' float tmp = texture2D(tDepth, coords + offset[i]).r;', - ' d += tmp * kernel[i];', - ' }', + for( int i=0; i<9; i++ ) { + float tmp = texture2D(tDepth, coords + offset[i]).r; + d += tmp * kernel[i]; + } - ' return d;', - '}', + return d; + } - 'vec3 color(vec2 coords,float blur) {', - ' //processing the sample', + vec3 color(vec2 coords,float blur) { + //processing the sample - ' vec3 col = vec3(0.0);', - ' vec2 texel = vec2(1.0/textureWidth,1.0/textureHeight);', + vec3 col = vec3(0.0); + vec2 texel = vec2(1.0/textureWidth,1.0/textureHeight); - ' col.r = texture2D(tColor,coords + vec2(0.0,1.0)*texel*fringe*blur).r;', - ' col.g = texture2D(tColor,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;', - ' col.b = texture2D(tColor,coords + vec2(0.866,-0.5)*texel*fringe*blur).b;', + col.r = texture2D(tColor,coords + vec2(0.0,1.0)*texel*fringe*blur).r; + col.g = texture2D(tColor,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g; + col.b = texture2D(tColor,coords + vec2(0.866,-0.5)*texel*fringe*blur).b; - ' vec3 lumcoeff = vec3(0.299,0.587,0.114);', - ' float lum = dot(col.rgb, lumcoeff);', - ' float thresh = max((lum-threshold)*gain, 0.0);', - ' return col+mix(vec3(0.0),col,thresh*blur);', - '}', + vec3 lumcoeff = vec3(0.299,0.587,0.114); + float lum = dot(col.rgb, lumcoeff); + float thresh = max((lum-threshold)*gain, 0.0); + return col+mix(vec3(0.0),col,thresh*blur); + } - 'vec3 debugFocus(vec3 col, float blur, float depth) {', - ' float edge = 0.002*depth; //distance based edge smoothing', - ' float m = clamp(smoothstep(0.0,edge,blur),0.0,1.0);', - ' float e = clamp(smoothstep(1.0-edge,1.0,blur),0.0,1.0);', + vec3 debugFocus(vec3 col, float blur, float depth) { + float edge = 0.002*depth; //distance based edge smoothing + float m = clamp(smoothstep(0.0,edge,blur),0.0,1.0); + float e = clamp(smoothstep(1.0-edge,1.0,blur),0.0,1.0); - ' col = mix(col,vec3(1.0,0.5,0.0),(1.0-m)*0.6);', - ' col = mix(col,vec3(0.0,0.5,1.0),((1.0-e)-(1.0-m))*0.2);', + col = mix(col,vec3(1.0,0.5,0.0),(1.0-m)*0.6); + col = mix(col,vec3(0.0,0.5,1.0),((1.0-e)-(1.0-m))*0.2); - ' return col;', - '}', + return col; + } - 'float linearize(float depth) {', - ' return -zfar * znear / (depth * (zfar - znear) - zfar);', - '}', + float linearize(float depth) { + return -zfar * znear / (depth * (zfar - znear) - zfar); + } + float vignette() { + float dist = distance(vUv.xy, vec2(0.5,0.5)); + dist = smoothstep(vignout+(fstop/vignfade), vignin+(fstop/vignfade), dist); + return clamp(dist,0.0,1.0); + } - 'float vignette() {', - ' float dist = distance(vUv.xy, vec2(0.5,0.5));', - ' dist = smoothstep(vignout+(fstop/vignfade), vignin+(fstop/vignfade), dist);', - ' return clamp(dist,0.0,1.0);', - '}', + float gather(float i, float j, int ringsamples, inout vec3 col, float w, float h, float blur) { + float rings2 = float(rings); + float step = PI*2.0 / float(ringsamples); + float pw = cos(j*step)*i; + float ph = sin(j*step)*i; + float p = 1.0; + if (pentagon) { + p = penta(vec2(pw,ph)); + } + col += color(vUv.xy + vec2(pw*w,ph*h), blur) * mix(1.0, i/rings2, bias) * p; + return 1.0 * mix(1.0, i /rings2, bias) * p; + } - 'float gather(float i, float j, int ringsamples, inout vec3 col, float w, float h, float blur) {', - ' float rings2 = float(rings);', - ' float step = PI*2.0 / float(ringsamples);', - ' float pw = cos(j*step)*i;', - ' float ph = sin(j*step)*i;', - ' float p = 1.0;', - ' if (pentagon) {', - ' p = penta(vec2(pw,ph));', - ' }', - ' col += color(vUv.xy + vec2(pw*w,ph*h), blur) * mix(1.0, i/rings2, bias) * p;', - ' return 1.0 * mix(1.0, i /rings2, bias) * p;', - '}', + void main() { + //scene depth calculation - 'void main() {', - ' //scene depth calculation', + float depth = linearize(texture2D(tDepth,vUv.xy).x); - ' float depth = linearize(texture2D(tDepth,vUv.xy).x);', + // Blur depth? + if ( depthblur ) { + depth = linearize(bdepth(vUv.xy)); + } - ' // Blur depth?', - ' if ( depthblur ) {', - ' depth = linearize(bdepth(vUv.xy));', - ' }', + //focal plane calculation - ' //focal plane calculation', + float fDepth = focalDepth; - ' float fDepth = focalDepth;', + if (shaderFocus) { - ' if (shaderFocus) {', + fDepth = linearize(texture2D(tDepth,focusCoords).x); - ' fDepth = linearize(texture2D(tDepth,focusCoords).x);', + } - ' }', + // dof blur factor calculation - ' // dof blur factor calculation', + float blur = 0.0; - ' float blur = 0.0;', + if (manualdof) { + float a = depth-fDepth; // Focal plane + float b = (a-fdofstart)/fdofdist; // Far DoF + float c = (-a-ndofstart)/ndofdist; // Near Dof + blur = (a>0.0) ? b : c; + } else { + float f = focalLength; // focal length in mm + float d = fDepth*1000.0; // focal plane in mm + float o = depth*1000.0; // depth in mm - ' if (manualdof) {', - ' float a = depth-fDepth; // Focal plane', - ' float b = (a-fdofstart)/fdofdist; // Far DoF', - ' float c = (-a-ndofstart)/ndofdist; // Near Dof', - ' blur = (a>0.0) ? b : c;', - ' } else {', - ' float f = focalLength; // focal length in mm', - ' float d = fDepth*1000.0; // focal plane in mm', - ' float o = depth*1000.0; // depth in mm', + float a = (o*f)/(o-f); + float b = (d*f)/(d-f); + float c = (d-f)/(d*fstop*CoC); - ' float a = (o*f)/(o-f);', - ' float b = (d*f)/(d-f);', - ' float c = (d-f)/(d*fstop*CoC);', + blur = abs(a-b)*c; + } - ' blur = abs(a-b)*c;', - ' }', + blur = clamp(blur,0.0,1.0); - ' blur = clamp(blur,0.0,1.0);', + // calculation of pattern for dithering - ' // calculation of pattern for dithering', + vec2 noise = vec2(rand(vUv.xy), rand( vUv.xy + vec2( 0.4, 0.6 ) ) )*dithering*blur; - ' vec2 noise = vec2(rand(vUv.xy), rand( vUv.xy + vec2( 0.4, 0.6 ) ) )*dithering*blur;', + // getting blur x and y step factor - ' // getting blur x and y step factor', + float w = (1.0/textureWidth)*blur*maxblur+noise.x; + float h = (1.0/textureHeight)*blur*maxblur+noise.y; - ' float w = (1.0/textureWidth)*blur*maxblur+noise.x;', - ' float h = (1.0/textureHeight)*blur*maxblur+noise.y;', + // calculation of final color - ' // calculation of final color', + vec3 col = vec3(0.0); - ' vec3 col = vec3(0.0);', + if(blur < 0.05) { + //some optimization thingy + col = texture2D(tColor, vUv.xy).rgb; + } else { + col = texture2D(tColor, vUv.xy).rgb; + float s = 1.0; + int ringsamples; - ' if(blur < 0.05) {', - ' //some optimization thingy', - ' col = texture2D(tColor, vUv.xy).rgb;', - ' } else {', - ' col = texture2D(tColor, vUv.xy).rgb;', - ' float s = 1.0;', - ' int ringsamples;', + for (int i = 1; i <= rings; i++) { + /*unboxstart*/ + ringsamples = i * samples; - ' for (int i = 1; i <= rings; i++) {', - ' /*unboxstart*/', - ' ringsamples = i * samples;', + for (int j = 0 ; j < maxringsamples ; j++) { + if (j >= ringsamples) break; + s += gather(float(i), float(j), ringsamples, col, w, h, blur); + } + /*unboxend*/ + } - ' for (int j = 0 ; j < maxringsamples ; j++) {', - ' if (j >= ringsamples) break;', - ' s += gather(float(i), float(j), ringsamples, col, w, h, blur);', - ' }', - ' /*unboxend*/', - ' }', + col /= s; //divide by sample count + } - ' col /= s; //divide by sample count', - ' }', + if (showFocus) { + col = debugFocus(col, blur, depth); + } - ' if (showFocus) {', - ' col = debugFocus(col, blur, depth);', - ' }', + if (vignetting) { + col *= vignette(); + } - ' if (vignetting) {', - ' col *= vignette();', - ' }', - - ' gl_FragColor.rgb = col;', - ' gl_FragColor.a = 1.0;', - '} ' - - ].join( '\n' ) + gl_FragColor.rgb = col; + gl_FragColor.a = 1.0; + }` }; -var BokehDepthShader = { +const BokehDepthShader = { uniforms: { @@ -366,36 +358,32 @@ var BokehDepthShader = { }, - vertexShader: [ - - 'varying float vViewZDepth;', - - 'void main() {', + vertexShader: /* glsl */` - ' #include ', - ' #include ', + varying float vViewZDepth; - ' vViewZDepth = - mvPosition.z;', + void main() { - '}' + #include + #include - ].join( '\n' ), + vViewZDepth = - mvPosition.z; - fragmentShader: [ + }`, - 'uniform float mNear;', - 'uniform float mFar;', + fragmentShader: /* glsl */` - 'varying float vViewZDepth;', + uniform float mNear; + uniform float mFar; - 'void main() {', + varying float vViewZDepth; - ' float color = 1.0 - smoothstep( mNear, mFar, vViewZDepth );', - ' gl_FragColor = vec4( vec3( color ), 1.0 );', + void main() { - '} ' + float color = 1.0 - smoothstep( mNear, mFar, vViewZDepth ); + gl_FragColor = vec4( vec3( color ), 1.0 ); - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/BrightnessContrastShader.js b/examples/jsm/shaders/BrightnessContrastShader.js index d4c66b9c557f92..41edbdd21cf52a 100644 --- a/examples/jsm/shaders/BrightnessContrastShader.js +++ b/examples/jsm/shaders/BrightnessContrastShader.js @@ -5,7 +5,7 @@ * contrast: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast) */ -var BrightnessContrastShader = { +const BrightnessContrastShader = { uniforms: { @@ -15,43 +15,39 @@ var BrightnessContrastShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float brightness; + uniform float contrast; - 'uniform sampler2D tDiffuse;', - 'uniform float brightness;', - 'uniform float contrast;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + gl_FragColor = texture2D( tDiffuse, vUv ); - ' gl_FragColor = texture2D( tDiffuse, vUv );', + gl_FragColor.rgb += brightness; - ' gl_FragColor.rgb += brightness;', + if (contrast > 0.0) { + gl_FragColor.rgb = (gl_FragColor.rgb - 0.5) / (1.0 - contrast) + 0.5; + } else { + gl_FragColor.rgb = (gl_FragColor.rgb - 0.5) * (1.0 + contrast) + 0.5; + } - ' if (contrast > 0.0) {', - ' gl_FragColor.rgb = (gl_FragColor.rgb - 0.5) / (1.0 - contrast) + 0.5;', - ' } else {', - ' gl_FragColor.rgb = (gl_FragColor.rgb - 0.5) * (1.0 + contrast) + 0.5;', - ' }', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/ColorCorrectionShader.js b/examples/jsm/shaders/ColorCorrectionShader.js index 8be2e7d92b14bd..b7cc5c242ccdd9 100644 --- a/examples/jsm/shaders/ColorCorrectionShader.js +++ b/examples/jsm/shaders/ColorCorrectionShader.js @@ -6,7 +6,7 @@ import { * Color correction */ -var ColorCorrectionShader = { +const ColorCorrectionShader = { uniforms: { @@ -17,37 +17,33 @@ var ColorCorrectionShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform vec3 powRGB; + uniform vec3 mulRGB; + uniform vec3 addRGB; - 'uniform sampler2D tDiffuse;', - 'uniform vec3 powRGB;', - 'uniform vec3 mulRGB;', - 'uniform vec3 addRGB;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + gl_FragColor = texture2D( tDiffuse, vUv ); + gl_FragColor.rgb = mulRGB * pow( ( gl_FragColor.rgb + addRGB ), powRGB ); - ' gl_FragColor = texture2D( tDiffuse, vUv );', - ' gl_FragColor.rgb = mulRGB * pow( ( gl_FragColor.rgb + addRGB ), powRGB );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/ColorifyShader.js b/examples/jsm/shaders/ColorifyShader.js index 794d3363473dbb..fa4cfd25f883b4 100644 --- a/examples/jsm/shaders/ColorifyShader.js +++ b/examples/jsm/shaders/ColorifyShader.js @@ -6,7 +6,7 @@ import { * Colorify shader */ -var ColorifyShader = { +const ColorifyShader = { uniforms: { @@ -15,38 +15,34 @@ var ColorifyShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform vec3 color; + uniform sampler2D tDiffuse; - 'uniform vec3 color;', - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 texel = texture2D( tDiffuse, vUv ); - ' vec4 texel = texture2D( tDiffuse, vUv );', + vec3 luma = vec3( 0.299, 0.587, 0.114 ); + float v = dot( texel.xyz, luma ); - ' vec3 luma = vec3( 0.299, 0.587, 0.114 );', - ' float v = dot( texel.xyz, luma );', + gl_FragColor = vec4( v * color, texel.w ); - ' gl_FragColor = vec4( v * color, texel.w );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/ConvolutionShader.js b/examples/jsm/shaders/ConvolutionShader.js index 67e0e00631f43e..42601b6a219011 100644 --- a/examples/jsm/shaders/ConvolutionShader.js +++ b/examples/jsm/shaders/ConvolutionShader.js @@ -8,7 +8,7 @@ import { * http://o3d.googlecode.com/svn/trunk/samples/convolution.html */ -var ConvolutionShader = { +const ConvolutionShader = { defines: { @@ -25,67 +25,58 @@ var ConvolutionShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'uniform vec2 uImageIncrement;', + uniform vec2 uImageIncrement; - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv - ( ( KERNEL_SIZE_FLOAT - 1.0 ) / 2.0 ) * uImageIncrement;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv - ( ( KERNEL_SIZE_FLOAT - 1.0 ) / 2.0 ) * uImageIncrement; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float cKernel[ KERNEL_SIZE_INT ]; - 'uniform float cKernel[ KERNEL_SIZE_INT ];', + uniform sampler2D tDiffuse; + uniform vec2 uImageIncrement; - 'uniform sampler2D tDiffuse;', - 'uniform vec2 uImageIncrement;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec2 imageCoord = vUv; + vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 ); - ' vec2 imageCoord = vUv;', - ' vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );', + for( int i = 0; i < KERNEL_SIZE_INT; i ++ ) { - ' for( int i = 0; i < KERNEL_SIZE_INT; i ++ ) {', + sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ]; + imageCoord += uImageIncrement; - ' sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];', - ' imageCoord += uImageIncrement;', + } - ' }', + gl_FragColor = sum; - ' gl_FragColor = sum;', - - '}' - - - ].join( '\n' ), + }`, buildKernel: function ( sigma ) { // We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway. - function gauss( x, sigma ) { - - return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); - - } - - var i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; + const kMaxKernelSize = 25; + let kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1; if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize; - halfWidth = ( kernelSize - 1 ) * 0.5; - values = new Array( kernelSize ); - sum = 0.0; - for ( i = 0; i < kernelSize; ++ i ) { + const halfWidth = ( kernelSize - 1 ) * 0.5; + + const values = new Array( kernelSize ); + let sum = 0.0; + for ( let i = 0; i < kernelSize; ++ i ) { values[ i ] = gauss( i - halfWidth, sigma ); sum += values[ i ]; @@ -94,7 +85,7 @@ var ConvolutionShader = { // normalize the kernel - for ( i = 0; i < kernelSize; ++ i ) values[ i ] /= sum; + for ( let i = 0; i < kernelSize; ++ i ) values[ i ] /= sum; return values; @@ -102,4 +93,10 @@ var ConvolutionShader = { }; +function gauss( x, sigma ) { + + return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) ); + +} + export { ConvolutionShader }; diff --git a/examples/jsm/shaders/CopyShader.js b/examples/jsm/shaders/CopyShader.js index d6e7eb1be2be06..f6e57bd75e7868 100644 --- a/examples/jsm/shaders/CopyShader.js +++ b/examples/jsm/shaders/CopyShader.js @@ -11,35 +11,31 @@ var CopyShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float opacity; - 'uniform float opacity;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 texel = texture2D( tDiffuse, vUv ); + gl_FragColor = opacity * texel; - ' vec4 texel = texture2D( tDiffuse, vUv );', - ' gl_FragColor = opacity * texel;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/DOFMipMapShader.js b/examples/jsm/shaders/DOFMipMapShader.js index b5cdad0901187e..e8add02132e240 100644 --- a/examples/jsm/shaders/DOFMipMapShader.js +++ b/examples/jsm/shaders/DOFMipMapShader.js @@ -4,7 +4,7 @@ * - requires power-of-2 sized render target with enabled mipmaps */ -var DOFMipMapShader = { +const DOFMipMapShader = { uniforms: { @@ -15,43 +15,39 @@ var DOFMipMapShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float focus; + uniform float maxblur; - 'uniform float focus;', - 'uniform float maxblur;', + uniform sampler2D tColor; + uniform sampler2D tDepth; - 'uniform sampler2D tColor;', - 'uniform sampler2D tDepth;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 depth = texture2D( tDepth, vUv ); - ' vec4 depth = texture2D( tDepth, vUv );', + float factor = depth.x - focus; - ' float factor = depth.x - focus;', + vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) ); - ' vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );', + gl_FragColor = col; + gl_FragColor.a = 1.0; - ' gl_FragColor = col;', - ' gl_FragColor.a = 1.0;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/DepthLimitedBlurShader.js b/examples/jsm/shaders/DepthLimitedBlurShader.js index 75cdeb9e654d56..56aefdd712c6bc 100644 --- a/examples/jsm/shaders/DepthLimitedBlurShader.js +++ b/examples/jsm/shaders/DepthLimitedBlurShader.js @@ -6,7 +6,7 @@ import { * TODO */ -var DepthLimitedBlurShader = { +const DepthLimitedBlurShader = { defines: { 'KERNEL_RADIUS': 4, 'DEPTH_PACKING': 1, @@ -22,112 +22,107 @@ var DepthLimitedBlurShader = { 'cameraFar': { value: 1000 }, 'depthCutoff': { value: 10 }, }, - vertexShader: [ - '#include ', + vertexShader: /* glsl */` - 'uniform vec2 size;', + #include - 'varying vec2 vUv;', - 'varying vec2 vInvSize;', + uniform vec2 size; - 'void main() {', - ' vUv = uv;', - ' vInvSize = 1.0 / size;', + varying vec2 vUv; + varying vec2 vInvSize; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - '}' + void main() { + vUv = uv; + vInvSize = 1.0 / size; - ].join( '\n' ), - fragmentShader: [ - '#include ', - '#include ', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, - 'uniform sampler2D tDiffuse;', - 'uniform sampler2D tDepth;', + fragmentShader: /* glsl */` - 'uniform float cameraNear;', - 'uniform float cameraFar;', - 'uniform float depthCutoff;', + #include + #include - 'uniform vec2 sampleUvOffsets[ KERNEL_RADIUS + 1 ];', - 'uniform float sampleWeights[ KERNEL_RADIUS + 1 ];', + uniform sampler2D tDiffuse; + uniform sampler2D tDepth; - 'varying vec2 vUv;', - 'varying vec2 vInvSize;', + uniform float cameraNear; + uniform float cameraFar; + uniform float depthCutoff; - 'float getDepth( const in vec2 screenPosition ) {', - ' #if DEPTH_PACKING == 1', - ' return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );', - ' #else', - ' return texture2D( tDepth, screenPosition ).x;', - ' #endif', - '}', + uniform vec2 sampleUvOffsets[ KERNEL_RADIUS + 1 ]; + uniform float sampleWeights[ KERNEL_RADIUS + 1 ]; - 'float getViewZ( const in float depth ) {', - ' #if PERSPECTIVE_CAMERA == 1', - ' return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );', - ' #else', - ' return orthographicDepthToViewZ( depth, cameraNear, cameraFar );', - ' #endif', - '}', + varying vec2 vUv; + varying vec2 vInvSize; - 'void main() {', - ' float depth = getDepth( vUv );', - ' if( depth >= ( 1.0 - EPSILON ) ) {', - ' discard;', - ' }', + float getDepth( const in vec2 screenPosition ) { + #if DEPTH_PACKING == 1 + return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) ); + #else + return texture2D( tDepth, screenPosition ).x; + #endif + } - ' float centerViewZ = -getViewZ( depth );', - ' bool rBreak = false, lBreak = false;', + float getViewZ( const in float depth ) { + #if PERSPECTIVE_CAMERA == 1 + return perspectiveDepthToViewZ( depth, cameraNear, cameraFar ); + #else + return orthographicDepthToViewZ( depth, cameraNear, cameraFar ); + #endif + } - ' float weightSum = sampleWeights[0];', - ' vec4 diffuseSum = texture2D( tDiffuse, vUv ) * weightSum;', + void main() { + float depth = getDepth( vUv ); + if( depth >= ( 1.0 - EPSILON ) ) { + discard; + } - ' for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {', + float centerViewZ = -getViewZ( depth ); + bool rBreak = false, lBreak = false; - ' float sampleWeight = sampleWeights[i];', - ' vec2 sampleUvOffset = sampleUvOffsets[i] * vInvSize;', + float weightSum = sampleWeights[0]; + vec4 diffuseSum = texture2D( tDiffuse, vUv ) * weightSum; - ' vec2 sampleUv = vUv + sampleUvOffset;', - ' float viewZ = -getViewZ( getDepth( sampleUv ) );', + for( int i = 1; i <= KERNEL_RADIUS; i ++ ) { - ' if( abs( viewZ - centerViewZ ) > depthCutoff ) rBreak = true;', + float sampleWeight = sampleWeights[i]; + vec2 sampleUvOffset = sampleUvOffsets[i] * vInvSize; - ' if( ! rBreak ) {', - ' diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight;', - ' weightSum += sampleWeight;', - ' }', + vec2 sampleUv = vUv + sampleUvOffset; + float viewZ = -getViewZ( getDepth( sampleUv ) ); - ' sampleUv = vUv - sampleUvOffset;', - ' viewZ = -getViewZ( getDepth( sampleUv ) );', + if( abs( viewZ - centerViewZ ) > depthCutoff ) rBreak = true; - ' if( abs( viewZ - centerViewZ ) > depthCutoff ) lBreak = true;', + if( ! rBreak ) { + diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight; + weightSum += sampleWeight; + } - ' if( ! lBreak ) {', - ' diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight;', - ' weightSum += sampleWeight;', - ' }', + sampleUv = vUv - sampleUvOffset; + viewZ = -getViewZ( getDepth( sampleUv ) ); - ' }', + if( abs( viewZ - centerViewZ ) > depthCutoff ) lBreak = true; - ' gl_FragColor = diffuseSum / weightSum;', - '}' - ].join( '\n' ) -}; + if( ! lBreak ) { + diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight; + weightSum += sampleWeight; + } -var BlurShaderUtils = { + } - createSampleWeights: function ( kernelRadius, stdDev ) { + gl_FragColor = diffuseSum / weightSum; + }` - var gaussian = function ( x, stdDev ) { +}; - return Math.exp( - ( x * x ) / ( 2.0 * ( stdDev * stdDev ) ) ) / ( Math.sqrt( 2.0 * Math.PI ) * stdDev ); +const BlurShaderUtils = { - }; + createSampleWeights: function ( kernelRadius, stdDev ) { - var weights = []; + const weights = []; - for ( var i = 0; i <= kernelRadius; i ++ ) { + for ( let i = 0; i <= kernelRadius; i ++ ) { weights.push( gaussian( i, stdDev ) ); @@ -139,9 +134,9 @@ var BlurShaderUtils = { createSampleOffsets: function ( kernelRadius, uvIncrement ) { - var offsets = []; + const offsets = []; - for ( var i = 0; i <= kernelRadius; i ++ ) { + for ( let i = 0; i <= kernelRadius; i ++ ) { offsets.push( uvIncrement.clone().multiplyScalar( i ) ); @@ -162,4 +157,10 @@ var BlurShaderUtils = { }; +function gaussian( x, stdDev ) { + + return Math.exp( - ( x * x ) / ( 2.0 * ( stdDev * stdDev ) ) ) / ( Math.sqrt( 2.0 * Math.PI ) * stdDev ); + +} + export { DepthLimitedBlurShader, BlurShaderUtils }; diff --git a/examples/jsm/shaders/DigitalGlitch.js b/examples/jsm/shaders/DigitalGlitch.js index b4af23b2139ee4..149624eeb48210 100644 --- a/examples/jsm/shaders/DigitalGlitch.js +++ b/examples/jsm/shaders/DigitalGlitch.js @@ -8,7 +8,7 @@ * angle: shift angle in radians */ -var DigitalGlitch = { +const DigitalGlitch = { uniforms: { @@ -25,78 +25,76 @@ var DigitalGlitch = { 'col_s': { value: 0.05 } }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', - 'void main() {', - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - '}' - ].join( '\n' ), + varying vec2 vUv; + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, - fragmentShader: [ - 'uniform int byp;', //should we apply the glitch ? + fragmentShader: /* glsl */` - 'uniform sampler2D tDiffuse;', - 'uniform sampler2D tDisp;', + uniform int byp; //should we apply the glitch ? - 'uniform float amount;', - 'uniform float angle;', - 'uniform float seed;', - 'uniform float seed_x;', - 'uniform float seed_y;', - 'uniform float distortion_x;', - 'uniform float distortion_y;', - 'uniform float col_s;', + uniform sampler2D tDiffuse; + uniform sampler2D tDisp; - 'varying vec2 vUv;', + uniform float amount; + uniform float angle; + uniform float seed; + uniform float seed_x; + uniform float seed_y; + uniform float distortion_x; + uniform float distortion_y; + uniform float col_s; + varying vec2 vUv; - 'float rand(vec2 co){', - ' return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);', - '}', - 'void main() {', - ' if(byp<1) {', - ' vec2 p = vUv;', - ' float xs = floor(gl_FragCoord.x / 0.5);', - ' float ys = floor(gl_FragCoord.y / 0.5);', - //based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch - ' vec4 normal = texture2D (tDisp, p*seed*seed);', - ' if(p.ydistortion_x-col_s*seed) {', - ' if(seed_x>0.){', - ' p.y = 1. - (p.y + distortion_y);', - ' }', - ' else {', - ' p.y = distortion_y;', - ' }', - ' }', - ' if(p.xdistortion_y-col_s*seed) {', - ' if(seed_y>0.){', - ' p.x=distortion_x;', - ' }', - ' else {', - ' p.x = 1. - (p.x + distortion_x);', - ' }', - ' }', - ' p.x+=normal.x*seed_x*(seed/5.);', - ' p.y+=normal.y*seed_y*(seed/5.);', - //base from RGB shift shader - ' vec2 offset = amount * vec2( cos(angle), sin(angle));', - ' vec4 cr = texture2D(tDiffuse, p + offset);', - ' vec4 cga = texture2D(tDiffuse, p);', - ' vec4 cb = texture2D(tDiffuse, p - offset);', - ' gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);', - //add noise - ' vec4 snow = 200.*amount*vec4(rand(vec2(xs * seed,ys * seed*50.))*0.2);', - ' gl_FragColor = gl_FragColor+ snow;', - ' }', - ' else {', - ' gl_FragColor=texture2D (tDiffuse, vUv);', - ' }', - '}' + float rand(vec2 co){ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); + } - ].join( '\n' ) + void main() { + if(byp<1) { + vec2 p = vUv; + float xs = floor(gl_FragCoord.x / 0.5); + float ys = floor(gl_FragCoord.y / 0.5); + //based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch + vec4 normal = texture2D (tDisp, p*seed*seed); + if(p.ydistortion_x-col_s*seed) { + if(seed_x>0.){ + p.y = 1. - (p.y + distortion_y); + } + else { + p.y = distortion_y; + } + } + if(p.xdistortion_y-col_s*seed) { + if(seed_y>0.){ + p.x=distortion_x; + } + else { + p.x = 1. - (p.x + distortion_x); + } + } + p.x+=normal.x*seed_x*(seed/5.); + p.y+=normal.y*seed_y*(seed/5.); + //base from RGB shift shader + vec2 offset = amount * vec2( cos(angle), sin(angle)); + vec4 cr = texture2D(tDiffuse, p + offset); + vec4 cga = texture2D(tDiffuse, p); + vec4 cb = texture2D(tDiffuse, p - offset); + gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a); + //add noise + vec4 snow = 200.*amount*vec4(rand(vec2(xs * seed,ys * seed*50.))*0.2); + gl_FragColor = gl_FragColor+ snow; + } + else { + gl_FragColor=texture2D (tDiffuse, vUv); + } + }` }; diff --git a/examples/jsm/shaders/DotScreenShader.js b/examples/jsm/shaders/DotScreenShader.js index a06c89d3ced420..ba69067c58b813 100644 --- a/examples/jsm/shaders/DotScreenShader.js +++ b/examples/jsm/shaders/DotScreenShader.js @@ -8,7 +8,7 @@ import { * https://github.com/evanw/glfx.js */ -var DotScreenShader = { +const DotScreenShader = { uniforms: { @@ -20,52 +20,48 @@ var DotScreenShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform vec2 center; + uniform float angle; + uniform float scale; + uniform vec2 tSize; - 'uniform vec2 center;', - 'uniform float angle;', - 'uniform float scale;', - 'uniform vec2 tSize;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + float pattern() { - 'float pattern() {', + float s = sin( angle ), c = cos( angle ); - ' float s = sin( angle ), c = cos( angle );', + vec2 tex = vUv * tSize - center; + vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale; - ' vec2 tex = vUv * tSize - center;', - ' vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;', + return ( sin( point.x ) * sin( point.y ) ) * 4.0; - ' return ( sin( point.x ) * sin( point.y ) ) * 4.0;', + } - '}', + void main() { - 'void main() {', + vec4 color = texture2D( tDiffuse, vUv ); - ' vec4 color = texture2D( tDiffuse, vUv );', + float average = ( color.r + color.g + color.b ) / 3.0; - ' float average = ( color.r + color.g + color.b ) / 3.0;', + gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a ); - ' gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/FXAAShader.js b/examples/jsm/shaders/FXAAShader.js index fb40d5533f962e..ffe2bb802f0f22 100644 --- a/examples/jsm/shaders/FXAAShader.js +++ b/examples/jsm/shaders/FXAAShader.js @@ -9,7 +9,7 @@ import { * http://www.glge.org/demos/fxaa/ */ -var FXAAShader = { +const FXAAShader = { uniforms: { @@ -18,1100 +18,1100 @@ var FXAAShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: - fragmentShader: [ - 'precision highp float;', - '', - 'uniform sampler2D tDiffuse;', - '', - 'uniform vec2 resolution;', - '', - 'varying vec2 vUv;', - '', - '// FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com)', - '', - '//----------------------------------------------------------------------------------', - '// File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag', - '// SDK Version: v3.00', - '// Email: gameworks@nvidia.com', - '// Site: http://developer.nvidia.com/', - '//', - '// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.', - '//', - '// Redistribution and use in source and binary forms, with or without', - '// modification, are permitted provided that the following conditions', - '// are met:', - '// * Redistributions of source code must retain the above copyright', - '// notice, this list of conditions and the following disclaimer.', - '// * Redistributions in binary form must reproduce the above copyright', - '// notice, this list of conditions and the following disclaimer in the', - '// documentation and/or other materials provided with the distribution.', - '// * Neither the name of NVIDIA CORPORATION nor the names of its', - '// contributors may be used to endorse or promote products derived', - '// from this software without specific prior written permission.', - '//', - '// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS\'\' AND ANY', - '// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE', - '// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR', - '// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR', - '// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,', - '// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,', - '// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR', - '// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY', - '// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT', - '// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE', - '// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.', - '//', - '//----------------------------------------------------------------------------------', - '', - '#define FXAA_PC 1', - '#define FXAA_GLSL_100 1', - '#define FXAA_QUALITY_PRESET 12', - '', - '#define FXAA_GREEN_AS_LUMA 1', - '', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_PC_CONSOLE', - ' //', - ' // The console algorithm for PC is included', - ' // for developers targeting really low spec machines.', - ' // Likely better to just run FXAA_PC, and use a really low preset.', - ' //', - ' #define FXAA_PC_CONSOLE 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_GLSL_120', - ' #define FXAA_GLSL_120 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_GLSL_130', - ' #define FXAA_GLSL_130 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_HLSL_3', - ' #define FXAA_HLSL_3 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_HLSL_4', - ' #define FXAA_HLSL_4 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_HLSL_5', - ' #define FXAA_HLSL_5 0', - '#endif', - '/*==========================================================================*/', - '#ifndef FXAA_GREEN_AS_LUMA', - ' //', - ' // For those using non-linear color,', - ' // and either not able to get luma in alpha, or not wanting to,', - ' // this enables FXAA to run using green as a proxy for luma.', - ' // So with this enabled, no need to pack luma in alpha.', - ' //', - ' // This will turn off AA on anything which lacks some amount of green.', - ' // Pure red and blue or combination of only R and B, will get no AA.', - ' //', - ' // Might want to lower the settings for both,', - ' // fxaaConsoleEdgeThresholdMin', - ' // fxaaQualityEdgeThresholdMin', - ' // In order to insure AA does not get turned off on colors', - ' // which contain a minor amount of green.', - ' //', - ' // 1 = On.', - ' // 0 = Off.', - ' //', - ' #define FXAA_GREEN_AS_LUMA 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_EARLY_EXIT', - ' //', - ' // Controls algorithm\'s early exit path.', - ' // On PS3 turning this ON adds 2 cycles to the shader.', - ' // On 360 turning this OFF adds 10ths of a millisecond to the shader.', - ' // Turning this off on console will result in a more blurry image.', - ' // So this defaults to on.', - ' //', - ' // 1 = On.', - ' // 0 = Off.', - ' //', - ' #define FXAA_EARLY_EXIT 1', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_DISCARD', - ' //', - ' // Only valid for PC OpenGL currently.', - ' // Probably will not work when FXAA_GREEN_AS_LUMA = 1.', - ' //', - ' // 1 = Use discard on pixels which don\'t need AA.', - ' // For APIs which enable concurrent TEX+ROP from same surface.', - ' // 0 = Return unchanged color on pixels which don\'t need AA.', - ' //', - ' #define FXAA_DISCARD 0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_FAST_PIXEL_OFFSET', - ' //', - ' // Used for GLSL 120 only.', - ' //', - ' // 1 = GL API supports fast pixel offsets', - ' // 0 = do not use fast pixel offsets', - ' //', - ' #ifdef GL_EXT_gpu_shader4', - ' #define FXAA_FAST_PIXEL_OFFSET 1', - ' #endif', - ' #ifdef GL_NV_gpu_shader5', - ' #define FXAA_FAST_PIXEL_OFFSET 1', - ' #endif', - ' #ifdef GL_ARB_gpu_shader5', - ' #define FXAA_FAST_PIXEL_OFFSET 1', - ' #endif', - ' #ifndef FXAA_FAST_PIXEL_OFFSET', - ' #define FXAA_FAST_PIXEL_OFFSET 0', - ' #endif', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#ifndef FXAA_GATHER4_ALPHA', - ' //', - ' // 1 = API supports gather4 on alpha channel.', - ' // 0 = API does not support gather4 on alpha channel.', - ' //', - ' #if (FXAA_HLSL_5 == 1)', - ' #define FXAA_GATHER4_ALPHA 1', - ' #endif', - ' #ifdef GL_ARB_gpu_shader5', - ' #define FXAA_GATHER4_ALPHA 1', - ' #endif', - ' #ifdef GL_NV_gpu_shader5', - ' #define FXAA_GATHER4_ALPHA 1', - ' #endif', - ' #ifndef FXAA_GATHER4_ALPHA', - ' #define FXAA_GATHER4_ALPHA 0', - ' #endif', - '#endif', - '', - '', - '/*============================================================================', - ' FXAA QUALITY - TUNING KNOBS', - '------------------------------------------------------------------------------', - 'NOTE the other tuning knobs are now in the shader function inputs!', - '============================================================================*/', - '#ifndef FXAA_QUALITY_PRESET', - ' //', - ' // Choose the quality preset.', - ' // This needs to be compiled into the shader as it effects code.', - ' // Best option to include multiple presets is to', - ' // in each shader define the preset, then include this file.', - ' //', - ' // OPTIONS', - ' // -----------------------------------------------------------------------', - ' // 10 to 15 - default medium dither (10=fastest, 15=highest quality)', - ' // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)', - ' // 39 - no dither, very expensive', - ' //', - ' // NOTES', - ' // -----------------------------------------------------------------------', - ' // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)', - ' // 13 = about same speed as FXAA 3.9 and better than 12', - ' // 23 = closest to FXAA 3.9 visually and performance wise', - ' // _ = the lowest digit is directly related to performance', - ' // _ = the highest digit is directly related to style', - ' //', - ' #define FXAA_QUALITY_PRESET 12', - '#endif', - '', - '', - '/*============================================================================', - '', - ' FXAA QUALITY - PRESETS', - '', - '============================================================================*/', - '', - '/*============================================================================', - ' FXAA QUALITY - MEDIUM DITHER PRESETS', - '============================================================================*/', - '#if (FXAA_QUALITY_PRESET == 10)', - ' #define FXAA_QUALITY_PS 3', - ' #define FXAA_QUALITY_P0 1.5', - ' #define FXAA_QUALITY_P1 3.0', - ' #define FXAA_QUALITY_P2 12.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 11)', - ' #define FXAA_QUALITY_PS 4', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 3.0', - ' #define FXAA_QUALITY_P3 12.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 12)', - ' #define FXAA_QUALITY_PS 5', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 4.0', - ' #define FXAA_QUALITY_P4 12.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 13)', - ' #define FXAA_QUALITY_PS 6', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 4.0', - ' #define FXAA_QUALITY_P5 12.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 14)', - ' #define FXAA_QUALITY_PS 7', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 4.0', - ' #define FXAA_QUALITY_P6 12.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 15)', - ' #define FXAA_QUALITY_PS 8', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 2.0', - ' #define FXAA_QUALITY_P6 4.0', - ' #define FXAA_QUALITY_P7 12.0', - '#endif', - '', - '/*============================================================================', - ' FXAA QUALITY - LOW DITHER PRESETS', - '============================================================================*/', - '#if (FXAA_QUALITY_PRESET == 20)', - ' #define FXAA_QUALITY_PS 3', - ' #define FXAA_QUALITY_P0 1.5', - ' #define FXAA_QUALITY_P1 2.0', - ' #define FXAA_QUALITY_P2 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 21)', - ' #define FXAA_QUALITY_PS 4', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 22)', - ' #define FXAA_QUALITY_PS 5', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 23)', - ' #define FXAA_QUALITY_PS 6', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 24)', - ' #define FXAA_QUALITY_PS 7', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 3.0', - ' #define FXAA_QUALITY_P6 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 25)', - ' #define FXAA_QUALITY_PS 8', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 2.0', - ' #define FXAA_QUALITY_P6 4.0', - ' #define FXAA_QUALITY_P7 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 26)', - ' #define FXAA_QUALITY_PS 9', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 2.0', - ' #define FXAA_QUALITY_P6 2.0', - ' #define FXAA_QUALITY_P7 4.0', - ' #define FXAA_QUALITY_P8 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 27)', - ' #define FXAA_QUALITY_PS 10', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 2.0', - ' #define FXAA_QUALITY_P6 2.0', - ' #define FXAA_QUALITY_P7 2.0', - ' #define FXAA_QUALITY_P8 4.0', - ' #define FXAA_QUALITY_P9 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 28)', - ' #define FXAA_QUALITY_PS 11', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 2.0', - ' #define FXAA_QUALITY_P6 2.0', - ' #define FXAA_QUALITY_P7 2.0', - ' #define FXAA_QUALITY_P8 2.0', - ' #define FXAA_QUALITY_P9 4.0', - ' #define FXAA_QUALITY_P10 8.0', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_QUALITY_PRESET == 29)', - ' #define FXAA_QUALITY_PS 12', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.5', - ' #define FXAA_QUALITY_P2 2.0', - ' #define FXAA_QUALITY_P3 2.0', - ' #define FXAA_QUALITY_P4 2.0', - ' #define FXAA_QUALITY_P5 2.0', - ' #define FXAA_QUALITY_P6 2.0', - ' #define FXAA_QUALITY_P7 2.0', - ' #define FXAA_QUALITY_P8 2.0', - ' #define FXAA_QUALITY_P9 2.0', - ' #define FXAA_QUALITY_P10 4.0', - ' #define FXAA_QUALITY_P11 8.0', - '#endif', - '', - '/*============================================================================', - ' FXAA QUALITY - EXTREME QUALITY', - '============================================================================*/', - '#if (FXAA_QUALITY_PRESET == 39)', - ' #define FXAA_QUALITY_PS 12', - ' #define FXAA_QUALITY_P0 1.0', - ' #define FXAA_QUALITY_P1 1.0', - ' #define FXAA_QUALITY_P2 1.0', - ' #define FXAA_QUALITY_P3 1.0', - ' #define FXAA_QUALITY_P4 1.0', - ' #define FXAA_QUALITY_P5 1.5', - ' #define FXAA_QUALITY_P6 2.0', - ' #define FXAA_QUALITY_P7 2.0', - ' #define FXAA_QUALITY_P8 2.0', - ' #define FXAA_QUALITY_P9 2.0', - ' #define FXAA_QUALITY_P10 4.0', - ' #define FXAA_QUALITY_P11 8.0', - '#endif', - '', - '', - '', - '/*============================================================================', - '', - ' API PORTING', - '', - '============================================================================*/', - '#if (FXAA_GLSL_100 == 1) || (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)', - ' #define FxaaBool bool', - ' #define FxaaDiscard discard', - ' #define FxaaFloat float', - ' #define FxaaFloat2 vec2', - ' #define FxaaFloat3 vec3', - ' #define FxaaFloat4 vec4', - ' #define FxaaHalf float', - ' #define FxaaHalf2 vec2', - ' #define FxaaHalf3 vec3', - ' #define FxaaHalf4 vec4', - ' #define FxaaInt2 ivec2', - ' #define FxaaSat(x) clamp(x, 0.0, 1.0)', - ' #define FxaaTex sampler2D', - '#else', - ' #define FxaaBool bool', - ' #define FxaaDiscard clip(-1)', - ' #define FxaaFloat float', - ' #define FxaaFloat2 float2', - ' #define FxaaFloat3 float3', - ' #define FxaaFloat4 float4', - ' #define FxaaHalf half', - ' #define FxaaHalf2 half2', - ' #define FxaaHalf3 half3', - ' #define FxaaHalf4 half4', - ' #define FxaaSat(x) saturate(x)', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_GLSL_100 == 1)', - ' #define FxaaTexTop(t, p) texture2D(t, p, 0.0)', - ' #define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), 0.0)', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_GLSL_120 == 1)', - ' // Requires,', - ' // #version 120', - ' // And at least,', - ' // #extension GL_EXT_gpu_shader4 : enable', - ' // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)', - ' #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)', - ' #if (FXAA_FAST_PIXEL_OFFSET == 1)', - ' #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)', - ' #else', - ' #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)', - ' #endif', - ' #if (FXAA_GATHER4_ALPHA == 1)', - ' // use #extension GL_ARB_gpu_shader5 : enable', - ' #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)', - ' #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)', - ' #define FxaaTexGreen4(t, p) textureGather(t, p, 1)', - ' #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)', - ' #endif', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_GLSL_130 == 1)', - ' // Requires "#version 130" or better', - ' #define FxaaTexTop(t, p) textureLod(t, p, 0.0)', - ' #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)', - ' #if (FXAA_GATHER4_ALPHA == 1)', - ' // use #extension GL_ARB_gpu_shader5 : enable', - ' #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)', - ' #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)', - ' #define FxaaTexGreen4(t, p) textureGather(t, p, 1)', - ' #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)', - ' #endif', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_HLSL_3 == 1)', - ' #define FxaaInt2 float2', - ' #define FxaaTex sampler2D', - ' #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))', - ' #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_HLSL_4 == 1)', - ' #define FxaaInt2 int2', - ' struct FxaaTex { SamplerState smpl; Texture2D tex; };', - ' #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)', - ' #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)', - '#endif', - '/*--------------------------------------------------------------------------*/', - '#if (FXAA_HLSL_5 == 1)', - ' #define FxaaInt2 int2', - ' struct FxaaTex { SamplerState smpl; Texture2D tex; };', - ' #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)', - ' #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)', - ' #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)', - ' #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)', - ' #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)', - ' #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)', - '#endif', - '', - '', - '/*============================================================================', - ' GREEN AS LUMA OPTION SUPPORT FUNCTION', - '============================================================================*/', - '#if (FXAA_GREEN_AS_LUMA == 0)', - ' FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }', - '#else', - ' FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }', - '#endif', - '', - '', - '', - '', - '/*============================================================================', - '', - ' FXAA3 QUALITY - PC', - '', - '============================================================================*/', - '#if (FXAA_PC == 1)', - '/*--------------------------------------------------------------------------*/', - 'FxaaFloat4 FxaaPixelShader(', - ' //', - ' // Use noperspective interpolation here (turn off perspective interpolation).', - ' // {xy} = center of pixel', - ' FxaaFloat2 pos,', - ' //', - ' // Used only for FXAA Console, and not used on the 360 version.', - ' // Use noperspective interpolation here (turn off perspective interpolation).', - ' // {xy_} = upper left of pixel', - ' // {_zw} = lower right of pixel', - ' FxaaFloat4 fxaaConsolePosPos,', - ' //', - ' // Input color texture.', - ' // {rgb_} = color in linear or perceptual color space', - ' // if (FXAA_GREEN_AS_LUMA == 0)', - ' // {__a} = luma in perceptual color space (not linear)', - ' FxaaTex tex,', - ' //', - ' // Only used on the optimized 360 version of FXAA Console.', - ' // For everything but 360, just use the same input here as for "tex".', - ' // For 360, same texture, just alias with a 2nd sampler.', - ' // This sampler needs to have an exponent bias of -1.', - ' FxaaTex fxaaConsole360TexExpBiasNegOne,', - ' //', - ' // Only used on the optimized 360 version of FXAA Console.', - ' // For everything but 360, just use the same input here as for "tex".', - ' // For 360, same texture, just alias with a 3nd sampler.', - ' // This sampler needs to have an exponent bias of -2.', - ' FxaaTex fxaaConsole360TexExpBiasNegTwo,', - ' //', - ' // Only used on FXAA Quality.', - ' // This must be from a constant/uniform.', - ' // {x_} = 1.0/screenWidthInPixels', - ' // {_y} = 1.0/screenHeightInPixels', - ' FxaaFloat2 fxaaQualityRcpFrame,', - ' //', - ' // Only used on FXAA Console.', - ' // This must be from a constant/uniform.', - ' // This effects sub-pixel AA quality and inversely sharpness.', - ' // Where N ranges between,', - ' // N = 0.50 (default)', - ' // N = 0.33 (sharper)', - ' // {x__} = -N/screenWidthInPixels', - ' // {_y_} = -N/screenHeightInPixels', - ' // {_z_} = N/screenWidthInPixels', - ' // {__w} = N/screenHeightInPixels', - ' FxaaFloat4 fxaaConsoleRcpFrameOpt,', - ' //', - ' // Only used on FXAA Console.', - ' // Not used on 360, but used on PS3 and PC.', - ' // This must be from a constant/uniform.', - ' // {x__} = -2.0/screenWidthInPixels', - ' // {_y_} = -2.0/screenHeightInPixels', - ' // {_z_} = 2.0/screenWidthInPixels', - ' // {__w} = 2.0/screenHeightInPixels', - ' FxaaFloat4 fxaaConsoleRcpFrameOpt2,', - ' //', - ' // Only used on FXAA Console.', - ' // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.', - ' // This must be from a constant/uniform.', - ' // {x__} = 8.0/screenWidthInPixels', - ' // {_y_} = 8.0/screenHeightInPixels', - ' // {_z_} = -4.0/screenWidthInPixels', - ' // {__w} = -4.0/screenHeightInPixels', - ' FxaaFloat4 fxaaConsole360RcpFrameOpt2,', - ' //', - ' // Only used on FXAA Quality.', - ' // This used to be the FXAA_QUALITY_SUBPIX define.', - ' // It is here now to allow easier tuning.', - ' // Choose the amount of sub-pixel aliasing removal.', - ' // This can effect sharpness.', - ' // 1.00 - upper limit (softer)', - ' // 0.75 - default amount of filtering', - ' // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)', - ' // 0.25 - almost off', - ' // 0.00 - completely off', - ' FxaaFloat fxaaQualitySubpix,', - ' //', - ' // Only used on FXAA Quality.', - ' // This used to be the FXAA_QUALITY_EDGE_THRESHOLD define.', - ' // It is here now to allow easier tuning.', - ' // The minimum amount of local contrast required to apply algorithm.', - ' // 0.333 - too little (faster)', - ' // 0.250 - low quality', - ' // 0.166 - default', - ' // 0.125 - high quality', - ' // 0.063 - overkill (slower)', - ' FxaaFloat fxaaQualityEdgeThreshold,', - ' //', - ' // Only used on FXAA Quality.', - ' // This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define.', - ' // It is here now to allow easier tuning.', - ' // Trims the algorithm from processing darks.', - ' // 0.0833 - upper limit (default, the start of visible unfiltered edges)', - ' // 0.0625 - high quality (faster)', - ' // 0.0312 - visible limit (slower)', - ' // Special notes when using FXAA_GREEN_AS_LUMA,', - ' // Likely want to set this to zero.', - ' // As colors that are mostly not-green', - ' // will appear very dark in the green channel!', - ' // Tune by looking at mostly non-green content,', - ' // then start at zero and increase until aliasing is a problem.', - ' FxaaFloat fxaaQualityEdgeThresholdMin,', - ' //', - ' // Only used on FXAA Console.', - ' // This used to be the FXAA_CONSOLE_EDGE_SHARPNESS define.', - ' // It is here now to allow easier tuning.', - ' // This does not effect PS3, as this needs to be compiled in.', - ' // Use FXAA_CONSOLE_PS3_EDGE_SHARPNESS for PS3.', - ' // Due to the PS3 being ALU bound,', - ' // there are only three safe values here: 2 and 4 and 8.', - ' // These options use the shaders ability to a free *|/ by 2|4|8.', - ' // For all other platforms can be a non-power of two.', - ' // 8.0 is sharper (default!!!)', - ' // 4.0 is softer', - ' // 2.0 is really soft (good only for vector graphics inputs)', - ' FxaaFloat fxaaConsoleEdgeSharpness,', - ' //', - ' // Only used on FXAA Console.', - ' // This used to be the FXAA_CONSOLE_EDGE_THRESHOLD define.', - ' // It is here now to allow easier tuning.', - ' // This does not effect PS3, as this needs to be compiled in.', - ' // Use FXAA_CONSOLE_PS3_EDGE_THRESHOLD for PS3.', - ' // Due to the PS3 being ALU bound,', - ' // there are only two safe values here: 1/4 and 1/8.', - ' // These options use the shaders ability to a free *|/ by 2|4|8.', - ' // The console setting has a different mapping than the quality setting.', - ' // Other platforms can use other values.', - ' // 0.125 leaves less aliasing, but is softer (default!!!)', - ' // 0.25 leaves more aliasing, and is sharper', - ' FxaaFloat fxaaConsoleEdgeThreshold,', - ' //', - ' // Only used on FXAA Console.', - ' // This used to be the FXAA_CONSOLE_EDGE_THRESHOLD_MIN define.', - ' // It is here now to allow easier tuning.', - ' // Trims the algorithm from processing darks.', - ' // The console setting has a different mapping than the quality setting.', - ' // This only applies when FXAA_EARLY_EXIT is 1.', - ' // This does not apply to PS3,', - ' // PS3 was simplified to avoid more shader instructions.', - ' // 0.06 - faster but more aliasing in darks', - ' // 0.05 - default', - ' // 0.04 - slower and less aliasing in darks', - ' // Special notes when using FXAA_GREEN_AS_LUMA,', - ' // Likely want to set this to zero.', - ' // As colors that are mostly not-green', - ' // will appear very dark in the green channel!', - ' // Tune by looking at mostly non-green content,', - ' // then start at zero and increase until aliasing is a problem.', - ' FxaaFloat fxaaConsoleEdgeThresholdMin,', - ' //', - ' // Extra constants for 360 FXAA Console only.', - ' // Use zeros or anything else for other platforms.', - ' // These must be in physical constant registers and NOT immediates.', - ' // Immediates will result in compiler un-optimizing.', - ' // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)', - ' FxaaFloat4 fxaaConsole360ConstDir', - ') {', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat2 posM;', - ' posM.x = pos.x;', - ' posM.y = pos.y;', - ' #if (FXAA_GATHER4_ALPHA == 1)', - ' #if (FXAA_DISCARD == 0)', - ' FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);', - ' #if (FXAA_GREEN_AS_LUMA == 0)', - ' #define lumaM rgbyM.w', - ' #else', - ' #define lumaM rgbyM.y', - ' #endif', - ' #endif', - ' #if (FXAA_GREEN_AS_LUMA == 0)', - ' FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);', - ' FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));', - ' #else', - ' FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);', - ' FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));', - ' #endif', - ' #if (FXAA_DISCARD == 1)', - ' #define lumaM luma4A.w', - ' #endif', - ' #define lumaE luma4A.z', - ' #define lumaS luma4A.x', - ' #define lumaSE luma4A.y', - ' #define lumaNW luma4B.w', - ' #define lumaN luma4B.z', - ' #define lumaW luma4B.x', - ' #else', - ' FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);', - ' #if (FXAA_GREEN_AS_LUMA == 0)', - ' #define lumaM rgbyM.w', - ' #else', - ' #define lumaM rgbyM.y', - ' #endif', - ' #if (FXAA_GLSL_100 == 1)', - ' FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 0.0, 1.0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0, 0.0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 0.0,-1.0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0, 0.0), fxaaQualityRcpFrame.xy));', - ' #else', - ' FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));', - ' #endif', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat maxSM = max(lumaS, lumaM);', - ' FxaaFloat minSM = min(lumaS, lumaM);', - ' FxaaFloat maxESM = max(lumaE, maxSM);', - ' FxaaFloat minESM = min(lumaE, minSM);', - ' FxaaFloat maxWN = max(lumaN, lumaW);', - ' FxaaFloat minWN = min(lumaN, lumaW);', - ' FxaaFloat rangeMax = max(maxWN, maxESM);', - ' FxaaFloat rangeMin = min(minWN, minESM);', - ' FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;', - ' FxaaFloat range = rangeMax - rangeMin;', - ' FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);', - ' FxaaBool earlyExit = range < rangeMaxClamped;', - '/*--------------------------------------------------------------------------*/', - ' if(earlyExit)', - ' #if (FXAA_DISCARD == 1)', - ' FxaaDiscard;', - ' #else', - ' return rgbyM;', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_GATHER4_ALPHA == 0)', - ' #if (FXAA_GLSL_100 == 1)', - ' FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0,-1.0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0, 1.0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0,-1.0), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0, 1.0), fxaaQualityRcpFrame.xy));', - ' #else', - ' FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));', - ' #endif', - ' #else', - ' FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));', - ' FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat lumaNS = lumaN + lumaS;', - ' FxaaFloat lumaWE = lumaW + lumaE;', - ' FxaaFloat subpixRcpRange = 1.0/range;', - ' FxaaFloat subpixNSWE = lumaNS + lumaWE;', - ' FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;', - ' FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat lumaNESE = lumaNE + lumaSE;', - ' FxaaFloat lumaNWNE = lumaNW + lumaNE;', - ' FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;', - ' FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat lumaNWSW = lumaNW + lumaSW;', - ' FxaaFloat lumaSWSE = lumaSW + lumaSE;', - ' FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);', - ' FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);', - ' FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;', - ' FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;', - ' FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;', - ' FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;', - ' FxaaFloat lengthSign = fxaaQualityRcpFrame.x;', - ' FxaaBool horzSpan = edgeHorz >= edgeVert;', - ' FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;', - '/*--------------------------------------------------------------------------*/', - ' if(!horzSpan) lumaN = lumaW;', - ' if(!horzSpan) lumaS = lumaE;', - ' if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;', - ' FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat gradientN = lumaN - lumaM;', - ' FxaaFloat gradientS = lumaS - lumaM;', - ' FxaaFloat lumaNN = lumaN + lumaM;', - ' FxaaFloat lumaSS = lumaS + lumaM;', - ' FxaaBool pairN = abs(gradientN) >= abs(gradientS);', - ' FxaaFloat gradient = max(abs(gradientN), abs(gradientS));', - ' if(pairN) lengthSign = -lengthSign;', - ' FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat2 posB;', - ' posB.x = posM.x;', - ' posB.y = posM.y;', - ' FxaaFloat2 offNP;', - ' offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;', - ' offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;', - ' if(!horzSpan) posB.x += lengthSign * 0.5;', - ' if( horzSpan) posB.y += lengthSign * 0.5;', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat2 posN;', - ' posN.x = posB.x - offNP.x * FXAA_QUALITY_P0;', - ' posN.y = posB.y - offNP.y * FXAA_QUALITY_P0;', - ' FxaaFloat2 posP;', - ' posP.x = posB.x + offNP.x * FXAA_QUALITY_P0;', - ' posP.y = posB.y + offNP.y * FXAA_QUALITY_P0;', - ' FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;', - ' FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));', - ' FxaaFloat subpixE = subpixC * subpixC;', - ' FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));', - '/*--------------------------------------------------------------------------*/', - ' if(!pairN) lumaNN = lumaSS;', - ' FxaaFloat gradientScaled = gradient * 1.0/4.0;', - ' FxaaFloat lumaMM = lumaM - lumaNN * 0.5;', - ' FxaaFloat subpixF = subpixD * subpixE;', - ' FxaaBool lumaMLTZero = lumaMM < 0.0;', - '/*--------------------------------------------------------------------------*/', - ' lumaEndN -= lumaNN * 0.5;', - ' lumaEndP -= lumaNN * 0.5;', - ' FxaaBool doneN = abs(lumaEndN) >= gradientScaled;', - ' FxaaBool doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1;', - ' FxaaBool doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1;', - '/*--------------------------------------------------------------------------*/', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 3)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 4)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 5)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 6)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 7)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 8)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 9)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 10)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 11)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11;', - '/*--------------------------------------------------------------------------*/', - ' #if (FXAA_QUALITY_PS > 12)', - ' if(doneNP) {', - ' if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));', - ' if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));', - ' if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;', - ' if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;', - ' doneN = abs(lumaEndN) >= gradientScaled;', - ' doneP = abs(lumaEndP) >= gradientScaled;', - ' if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12;', - ' if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12;', - ' doneNP = (!doneN) || (!doneP);', - ' if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12;', - ' if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12;', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - ' #endif', - '/*--------------------------------------------------------------------------*/', - ' }', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat dstN = posM.x - posN.x;', - ' FxaaFloat dstP = posP.x - posM.x;', - ' if(!horzSpan) dstN = posM.y - posN.y;', - ' if(!horzSpan) dstP = posP.y - posM.y;', - '/*--------------------------------------------------------------------------*/', - ' FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;', - ' FxaaFloat spanLength = (dstP + dstN);', - ' FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;', - ' FxaaFloat spanLengthRcp = 1.0/spanLength;', - '/*--------------------------------------------------------------------------*/', - ' FxaaBool directionN = dstN < dstP;', - ' FxaaFloat dst = min(dstN, dstP);', - ' FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;', - ' FxaaFloat subpixG = subpixF * subpixF;', - ' FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;', - ' FxaaFloat subpixH = subpixG * fxaaQualitySubpix;', - '/*--------------------------------------------------------------------------*/', - ' FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;', - ' FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);', - ' if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;', - ' if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;', - ' #if (FXAA_DISCARD == 1)', - ' return FxaaTexTop(tex, posM);', - ' #else', - ' return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);', - ' #endif', - '}', - '/*==========================================================================*/', - '#endif', - '', - 'void main() {', - ' gl_FragColor = FxaaPixelShader(', - ' vUv,', - ' vec4(0.0),', - ' tDiffuse,', - ' tDiffuse,', - ' tDiffuse,', - ' resolution,', - ' vec4(0.0),', - ' vec4(0.0),', - ' vec4(0.0),', - ' 0.75,', - ' 0.166,', - ' 0.0833,', - ' 0.0,', - ' 0.0,', - ' 0.0,', - ' vec4(0.0)', - ' );', - '', - ' // TODO avoid querying texture twice for same texel', - ' gl_FragColor.a = texture2D(tDiffuse, vUv).a;', - '}' - ].join( '\n' ) + // FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com) + + //---------------------------------------------------------------------------------- + // File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag + // SDK Version: v3.00 + // Email: gameworks@nvidia.com + // Site: http://developer.nvidia.com/ + // + // Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // * Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // * Redistributions in binary form must reproduce the above copyright + // notice, this list of conditions and the following disclaimer in the + // documentation and/or other materials provided with the distribution. + // * Neither the name of NVIDIA CORPORATION nor the names of its + // contributors may be used to endorse or promote products derived + // from this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS\'\' AND ANY + // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // + //---------------------------------------------------------------------------------- + + /* glsl */` + + precision highp float; + + uniform sampler2D tDiffuse; + + uniform vec2 resolution; + + varying vec2 vUv; + + #define FXAA_PC 1 + #define FXAA_GLSL_100 1 + #define FXAA_QUALITY_PRESET 12 + + #define FXAA_GREEN_AS_LUMA 1 + + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_PC_CONSOLE + // + // The console algorithm for PC is included + // for developers targeting really low spec machines. + // Likely better to just run FXAA_PC, and use a really low preset. + // + #define FXAA_PC_CONSOLE 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_GLSL_120 + #define FXAA_GLSL_120 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_GLSL_130 + #define FXAA_GLSL_130 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_HLSL_3 + #define FXAA_HLSL_3 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_HLSL_4 + #define FXAA_HLSL_4 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_HLSL_5 + #define FXAA_HLSL_5 0 + #endif + /*==========================================================================*/ + #ifndef FXAA_GREEN_AS_LUMA + // + // For those using non-linear color, + // and either not able to get luma in alpha, or not wanting to, + // this enables FXAA to run using green as a proxy for luma. + // So with this enabled, no need to pack luma in alpha. + // + // This will turn off AA on anything which lacks some amount of green. + // Pure red and blue or combination of only R and B, will get no AA. + // + // Might want to lower the settings for both, + // fxaaConsoleEdgeThresholdMin + // fxaaQualityEdgeThresholdMin + // In order to insure AA does not get turned off on colors + // which contain a minor amount of green. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_GREEN_AS_LUMA 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_EARLY_EXIT + // + // Controls algorithm\'s early exit path. + // On PS3 turning this ON adds 2 cycles to the shader. + // On 360 turning this OFF adds 10ths of a millisecond to the shader. + // Turning this off on console will result in a more blurry image. + // So this defaults to on. + // + // 1 = On. + // 0 = Off. + // + #define FXAA_EARLY_EXIT 1 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_DISCARD + // + // Only valid for PC OpenGL currently. + // Probably will not work when FXAA_GREEN_AS_LUMA = 1. + // + // 1 = Use discard on pixels which don\'t need AA. + // For APIs which enable concurrent TEX+ROP from same surface. + // 0 = Return unchanged color on pixels which don\'t need AA. + // + #define FXAA_DISCARD 0 + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_FAST_PIXEL_OFFSET + // + // Used for GLSL 120 only. + // + // 1 = GL API supports fast pixel offsets + // 0 = do not use fast pixel offsets + // + #ifdef GL_EXT_gpu_shader4 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_FAST_PIXEL_OFFSET 1 + #endif + #ifndef FXAA_FAST_PIXEL_OFFSET + #define FXAA_FAST_PIXEL_OFFSET 0 + #endif + #endif + /*--------------------------------------------------------------------------*/ + #ifndef FXAA_GATHER4_ALPHA + // + // 1 = API supports gather4 on alpha channel. + // 0 = API does not support gather4 on alpha channel. + // + #if (FXAA_HLSL_5 == 1) + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif + #endif + + + /*============================================================================ + FXAA QUALITY - TUNING KNOBS + ------------------------------------------------------------------------------ + NOTE the other tuning knobs are now in the shader function inputs! + ============================================================================*/ + #ifndef FXAA_QUALITY_PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY_PRESET 12 + #endif + + + /*============================================================================ + + FXAA QUALITY - PRESETS + + ============================================================================*/ + + /*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS + ============================================================================*/ + #if (FXAA_QUALITY_PRESET == 10) + #define FXAA_QUALITY_PS 3 + #define FXAA_QUALITY_P0 1.5 + #define FXAA_QUALITY_P1 3.0 + #define FXAA_QUALITY_P2 12.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 11) + #define FXAA_QUALITY_PS 4 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 3.0 + #define FXAA_QUALITY_P3 12.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 12) + #define FXAA_QUALITY_PS 5 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 4.0 + #define FXAA_QUALITY_P4 12.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 13) + #define FXAA_QUALITY_PS 6 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 4.0 + #define FXAA_QUALITY_P5 12.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 14) + #define FXAA_QUALITY_PS 7 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 4.0 + #define FXAA_QUALITY_P6 12.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 15) + #define FXAA_QUALITY_PS 8 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 4.0 + #define FXAA_QUALITY_P7 12.0 + #endif + + /*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS + ============================================================================*/ + #if (FXAA_QUALITY_PRESET == 20) + #define FXAA_QUALITY_PS 3 + #define FXAA_QUALITY_P0 1.5 + #define FXAA_QUALITY_P1 2.0 + #define FXAA_QUALITY_P2 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 21) + #define FXAA_QUALITY_PS 4 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 22) + #define FXAA_QUALITY_PS 5 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 23) + #define FXAA_QUALITY_PS 6 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 24) + #define FXAA_QUALITY_PS 7 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 3.0 + #define FXAA_QUALITY_P6 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 25) + #define FXAA_QUALITY_PS 8 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 4.0 + #define FXAA_QUALITY_P7 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 26) + #define FXAA_QUALITY_PS 9 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 4.0 + #define FXAA_QUALITY_P8 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 27) + #define FXAA_QUALITY_PS 10 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 4.0 + #define FXAA_QUALITY_P9 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 28) + #define FXAA_QUALITY_PS 11 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 2.0 + #define FXAA_QUALITY_P9 4.0 + #define FXAA_QUALITY_P10 8.0 + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PRESET == 29) + #define FXAA_QUALITY_PS 12 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.5 + #define FXAA_QUALITY_P2 2.0 + #define FXAA_QUALITY_P3 2.0 + #define FXAA_QUALITY_P4 2.0 + #define FXAA_QUALITY_P5 2.0 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 2.0 + #define FXAA_QUALITY_P9 2.0 + #define FXAA_QUALITY_P10 4.0 + #define FXAA_QUALITY_P11 8.0 + #endif + + /*============================================================================ + FXAA QUALITY - EXTREME QUALITY + ============================================================================*/ + #if (FXAA_QUALITY_PRESET == 39) + #define FXAA_QUALITY_PS 12 + #define FXAA_QUALITY_P0 1.0 + #define FXAA_QUALITY_P1 1.0 + #define FXAA_QUALITY_P2 1.0 + #define FXAA_QUALITY_P3 1.0 + #define FXAA_QUALITY_P4 1.0 + #define FXAA_QUALITY_P5 1.5 + #define FXAA_QUALITY_P6 2.0 + #define FXAA_QUALITY_P7 2.0 + #define FXAA_QUALITY_P8 2.0 + #define FXAA_QUALITY_P9 2.0 + #define FXAA_QUALITY_P10 4.0 + #define FXAA_QUALITY_P11 8.0 + #endif + + + + /*============================================================================ + + API PORTING + + ============================================================================*/ + #if (FXAA_GLSL_100 == 1) || (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) + #define FxaaBool bool + #define FxaaDiscard discard + #define FxaaFloat float + #define FxaaFloat2 vec2 + #define FxaaFloat3 vec3 + #define FxaaFloat4 vec4 + #define FxaaHalf float + #define FxaaHalf2 vec2 + #define FxaaHalf3 vec3 + #define FxaaHalf4 vec4 + #define FxaaInt2 ivec2 + #define FxaaSat(x) clamp(x, 0.0, 1.0) + #define FxaaTex sampler2D + #else + #define FxaaBool bool + #define FxaaDiscard clip(-1) + #define FxaaFloat float + #define FxaaFloat2 float2 + #define FxaaFloat3 float3 + #define FxaaFloat4 float4 + #define FxaaHalf half + #define FxaaHalf2 half2 + #define FxaaHalf3 half3 + #define FxaaHalf4 half4 + #define FxaaSat(x) saturate(x) + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_GLSL_100 == 1) + #define FxaaTexTop(t, p) texture2D(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), 0.0) + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_GLSL_120 == 1) + // Requires, + // #version 120 + // And at least, + // #extension GL_EXT_gpu_shader4 : enable + // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) + #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) + #if (FXAA_FAST_PIXEL_OFFSET == 1) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) + #else + #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) + #endif + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_GLSL_130 == 1) + // Requires "#version 130" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #if (FXAA_GATHER4_ALPHA == 1) + // use #extension GL_ARB_gpu_shader5 : enable + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) + #endif + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_HLSL_3 == 1) + #define FxaaInt2 float2 + #define FxaaTex sampler2D + #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) + #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_HLSL_4 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_HLSL_5 == 1) + #define FxaaInt2 int2 + struct FxaaTex { SamplerState smpl; Texture2D tex; }; + #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) + #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) + #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) + #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) + #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) + #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) + #endif + + + /*============================================================================ + GREEN AS LUMA OPTION SUPPORT FUNCTION + ============================================================================*/ + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } + #else + FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } + #endif + + + + + /*============================================================================ + + FXAA3 QUALITY - PC + + ============================================================================*/ + #if (FXAA_PC == 1) + /*--------------------------------------------------------------------------*/ + FxaaFloat4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + FxaaFloat2 pos, + // + // Used only for FXAA Console, and not used on the 360 version. + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy_} = upper left of pixel + // {_zw} = lower right of pixel + FxaaFloat4 fxaaConsolePosPos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + // if (FXAA_GREEN_AS_LUMA == 0) + // {__a} = luma in perceptual color space (not linear) + FxaaTex tex, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 2nd sampler. + // This sampler needs to have an exponent bias of -1. + FxaaTex fxaaConsole360TexExpBiasNegOne, + // + // Only used on the optimized 360 version of FXAA Console. + // For everything but 360, just use the same input here as for "tex". + // For 360, same texture, just alias with a 3nd sampler. + // This sampler needs to have an exponent bias of -2. + FxaaTex fxaaConsole360TexExpBiasNegTwo, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + FxaaFloat2 fxaaQualityRcpFrame, + // + // Only used on FXAA Console. + // This must be from a constant/uniform. + // This effects sub-pixel AA quality and inversely sharpness. + // Where N ranges between, + // N = 0.50 (default) + // N = 0.33 (sharper) + // {x__} = -N/screenWidthInPixels + // {_y_} = -N/screenHeightInPixels + // {_z_} = N/screenWidthInPixels + // {__w} = N/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt, + // + // Only used on FXAA Console. + // Not used on 360, but used on PS3 and PC. + // This must be from a constant/uniform. + // {x__} = -2.0/screenWidthInPixels + // {_y_} = -2.0/screenHeightInPixels + // {_z_} = 2.0/screenWidthInPixels + // {__w} = 2.0/screenHeightInPixels + FxaaFloat4 fxaaConsoleRcpFrameOpt2, + // + // Only used on FXAA Console. + // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. + // This must be from a constant/uniform. + // {x__} = 8.0/screenWidthInPixels + // {_y_} = 8.0/screenHeightInPixels + // {_z_} = -4.0/screenWidthInPixels + // {__w} = -4.0/screenHeightInPixels + FxaaFloat4 fxaaConsole360RcpFrameOpt2, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + FxaaFloat fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + FxaaFloat fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaQualityEdgeThresholdMin, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_EDGE_SHARPNESS define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE_PS3_EDGE_SHARPNESS for PS3. + // Due to the PS3 being ALU bound, + // there are only three safe values here: 2 and 4 and 8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // For all other platforms can be a non-power of two. + // 8.0 is sharper (default!!!) + // 4.0 is softer + // 2.0 is really soft (good only for vector graphics inputs) + FxaaFloat fxaaConsoleEdgeSharpness, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // This does not effect PS3, as this needs to be compiled in. + // Use FXAA_CONSOLE_PS3_EDGE_THRESHOLD for PS3. + // Due to the PS3 being ALU bound, + // there are only two safe values here: 1/4 and 1/8. + // These options use the shaders ability to a free *|/ by 2|4|8. + // The console setting has a different mapping than the quality setting. + // Other platforms can use other values. + // 0.125 leaves less aliasing, but is softer (default!!!) + // 0.25 leaves more aliasing, and is sharper + FxaaFloat fxaaConsoleEdgeThreshold, + // + // Only used on FXAA Console. + // This used to be the FXAA_CONSOLE_EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // The console setting has a different mapping than the quality setting. + // This only applies when FXAA_EARLY_EXIT is 1. + // This does not apply to PS3, + // PS3 was simplified to avoid more shader instructions. + // 0.06 - faster but more aliasing in darks + // 0.05 - default + // 0.04 - slower and less aliasing in darks + // Special notes when using FXAA_GREEN_AS_LUMA, + // Likely want to set this to zero. + // As colors that are mostly not-green + // will appear very dark in the green channel! + // Tune by looking at mostly non-green content, + // then start at zero and increase until aliasing is a problem. + FxaaFloat fxaaConsoleEdgeThresholdMin, + // + // Extra constants for 360 FXAA Console only. + // Use zeros or anything else for other platforms. + // These must be in physical constant registers and NOT immediates. + // Immediates will result in compiler un-optimizing. + // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) + FxaaFloat4 fxaaConsole360ConstDir + ) { + /*--------------------------------------------------------------------------*/ + FxaaFloat2 posM; + posM.x = pos.x; + posM.y = pos.y; + #if (FXAA_GATHER4_ALPHA == 1) + #if (FXAA_DISCARD == 0) + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #endif + #if (FXAA_GREEN_AS_LUMA == 0) + FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); + #else + FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); + FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); + #endif + #if (FXAA_DISCARD == 1) + #define lumaM luma4A.w + #endif + #define lumaE luma4A.z + #define lumaS luma4A.x + #define lumaSE luma4A.y + #define lumaNW luma4B.w + #define lumaN luma4B.z + #define lumaW luma4B.x + #else + FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); + #if (FXAA_GREEN_AS_LUMA == 0) + #define lumaM rgbyM.w + #else + #define lumaM rgbyM.y + #endif + #if (FXAA_GLSL_100 == 1) + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 0.0, 1.0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0, 0.0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 0.0,-1.0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0, 0.0), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); + #endif + #endif + /*--------------------------------------------------------------------------*/ + FxaaFloat maxSM = max(lumaS, lumaM); + FxaaFloat minSM = min(lumaS, lumaM); + FxaaFloat maxESM = max(lumaE, maxSM); + FxaaFloat minESM = min(lumaE, minSM); + FxaaFloat maxWN = max(lumaN, lumaW); + FxaaFloat minWN = min(lumaN, lumaW); + FxaaFloat rangeMax = max(maxWN, maxESM); + FxaaFloat rangeMin = min(minWN, minESM); + FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + FxaaFloat range = rangeMax - rangeMin; + FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + FxaaBool earlyExit = range < rangeMaxClamped; + /*--------------------------------------------------------------------------*/ + if(earlyExit) + #if (FXAA_DISCARD == 1) + FxaaDiscard; + #else + return rgbyM; + #endif + /*--------------------------------------------------------------------------*/ + #if (FXAA_GATHER4_ALPHA == 0) + #if (FXAA_GLSL_100 == 1) + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0,-1.0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0, 1.0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2( 1.0,-1.0), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaFloat2(-1.0, 1.0), fxaaQualityRcpFrame.xy)); + #else + FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif + #else + FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); + FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); + #endif + /*--------------------------------------------------------------------------*/ + FxaaFloat lumaNS = lumaN + lumaS; + FxaaFloat lumaWE = lumaW + lumaE; + FxaaFloat subpixRcpRange = 1.0/range; + FxaaFloat subpixNSWE = lumaNS + lumaWE; + FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; + FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; + /*--------------------------------------------------------------------------*/ + FxaaFloat lumaNESE = lumaNE + lumaSE; + FxaaFloat lumaNWNE = lumaNW + lumaNE; + FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; + /*--------------------------------------------------------------------------*/ + FxaaFloat lumaNWSW = lumaNW + lumaSW; + FxaaFloat lumaSWSE = lumaSW + lumaSE; + FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; + FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; + /*--------------------------------------------------------------------------*/ + FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; + FxaaFloat lengthSign = fxaaQualityRcpFrame.x; + FxaaBool horzSpan = edgeHorz >= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; + /*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; + /*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); + /*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; + /*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY_P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY_P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY_P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY_P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); + /*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; + /*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1; + /*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11; + /*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY_PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12; + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + #endif + /*--------------------------------------------------------------------------*/ + } + /*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; + /*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; + /*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; + /*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif + } + /*==========================================================================*/ + #endif + + void main() { + gl_FragColor = FxaaPixelShader( + vUv, + vec4(0.0), + tDiffuse, + tDiffuse, + tDiffuse, + resolution, + vec4(0.0), + vec4(0.0), + vec4(0.0), + 0.75, + 0.166, + 0.0833, + 0.0, + 0.0, + 0.0, + vec4(0.0) + ); + + // TODO avoid querying texture twice for same texel + gl_FragColor.a = texture2D(tDiffuse, vUv).a; + }` }; diff --git a/examples/jsm/shaders/FilmShader.js b/examples/jsm/shaders/FilmShader.js index 1bb352af2aa4ce..201097ce6608e8 100644 --- a/examples/jsm/shaders/FilmShader.js +++ b/examples/jsm/shaders/FilmShader.js @@ -18,7 +18,7 @@ * http://creativecommons.org/licenses/by/3.0/ */ -var FilmShader = { +const FilmShader = { uniforms: { @@ -31,73 +31,69 @@ var FilmShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ - - '#include ', + #include // control parameter - 'uniform float time;', + uniform float time; - 'uniform bool grayscale;', + uniform bool grayscale; // noise effect intensity value (0 = no effect, 1 = full effect) - 'uniform float nIntensity;', + uniform float nIntensity; // scanlines effect intensity value (0 = no effect, 1 = full effect) - 'uniform float sIntensity;', + uniform float sIntensity; // scanlines effect count value (0 = no effect, 4096 = full effect) - 'uniform float sCount;', + uniform float sCount; - 'uniform sampler2D tDiffuse;', + uniform sampler2D tDiffuse; - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { // sample the source - ' vec4 cTextureScreen = texture2D( tDiffuse, vUv );', + vec4 cTextureScreen = texture2D( tDiffuse, vUv ); // make some noise - ' float dx = rand( vUv + time );', + float dx = rand( vUv + time ); // add noise - ' vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx, 0.0, 1.0 );', + vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx, 0.0, 1.0 ); // get us a sine and cosine - ' vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );', + vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) ); // add scanlines - ' cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;', + cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity; // interpolate between source and result by intensity - ' cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );', + cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb ); // convert to grayscale if desired - ' if( grayscale ) {', - - ' cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );', + if( grayscale ) { - ' }', + cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 ); - ' gl_FragColor = vec4( cResult, cTextureScreen.a );', + } - '}' + gl_FragColor = vec4( cResult, cTextureScreen.a ); - ].join( '\n' ) + }`, }; diff --git a/examples/jsm/shaders/FocusShader.js b/examples/jsm/shaders/FocusShader.js index c78cd257287c7c..e15259c69f03e7 100644 --- a/examples/jsm/shaders/FocusShader.js +++ b/examples/jsm/shaders/FocusShader.js @@ -4,7 +4,7 @@ * http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js */ -var FocusShader = { +const FocusShader = { uniforms: { @@ -16,76 +16,72 @@ var FocusShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float screenWidth; + uniform float screenHeight; + uniform float sampleDistance; + uniform float waveFactor; - 'uniform float screenWidth;', - 'uniform float screenHeight;', - 'uniform float sampleDistance;', - 'uniform float waveFactor;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 color, org, tmp, add; + float sample_dist, f; + vec2 vin; + vec2 uv = vUv; - ' vec4 color, org, tmp, add;', - ' float sample_dist, f;', - ' vec2 vin;', - ' vec2 uv = vUv;', + add = color = org = texture2D( tDiffuse, uv ); - ' add = color = org = texture2D( tDiffuse, uv );', + vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 ); + sample_dist = dot( vin, vin ) * 2.0; - ' vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );', - ' sample_dist = dot( vin, vin ) * 2.0;', + f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0; - ' f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;', + vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f ); - ' vec2 sampleSize = vec2( 1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );', + add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize ); + if( tmp.b < color.b ) color = tmp; - ' add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );', - ' if( tmp.b < color.b ) color = tmp;', + color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) ); + color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) ); - ' color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );', - ' color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );', + gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 ); - ' gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );', + }` - '}' - - - ].join( '\n' ) }; export { FocusShader }; diff --git a/examples/jsm/shaders/FreiChenShader.js b/examples/jsm/shaders/FreiChenShader.js index 420a4782bc6d81..37246fc8c9f69e 100644 --- a/examples/jsm/shaders/FreiChenShader.js +++ b/examples/jsm/shaders/FreiChenShader.js @@ -17,81 +17,78 @@ var FreiChenShader = { 'aspect': { value: new Vector2( 512, 512 ) } }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + varying vec2 vUv; - 'uniform sampler2D tDiffuse;', - 'varying vec2 vUv;', + uniform vec2 aspect; - 'uniform vec2 aspect;', + vec2 texel = vec2( 1.0 / aspect.x, 1.0 / aspect.y ); - 'vec2 texel = vec2(1.0 / aspect.x, 1.0 / aspect.y);', - - 'mat3 G[9];', + mat3 G[9]; // hard coded matrix values!!!! as suggested in https://github.com/neilmendoza/ofxPostProcessing/blob/master/src/EdgePass.cpp#L45 - 'const mat3 g0 = mat3( 0.3535533845424652, 0, -0.3535533845424652, 0.5, 0, -0.5, 0.3535533845424652, 0, -0.3535533845424652 );', - 'const mat3 g1 = mat3( 0.3535533845424652, 0.5, 0.3535533845424652, 0, 0, 0, -0.3535533845424652, -0.5, -0.3535533845424652 );', - 'const mat3 g2 = mat3( 0, 0.3535533845424652, -0.5, -0.3535533845424652, 0, 0.3535533845424652, 0.5, -0.3535533845424652, 0 );', - 'const mat3 g3 = mat3( 0.5, -0.3535533845424652, 0, -0.3535533845424652, 0, 0.3535533845424652, 0, 0.3535533845424652, -0.5 );', - 'const mat3 g4 = mat3( 0, -0.5, 0, 0.5, 0, 0.5, 0, -0.5, 0 );', - 'const mat3 g5 = mat3( -0.5, 0, 0.5, 0, 0, 0, 0.5, 0, -0.5 );', - 'const mat3 g6 = mat3( 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.6666666865348816, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204 );', - 'const mat3 g7 = mat3( -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, 0.6666666865348816, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408 );', - 'const mat3 g8 = mat3( 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408 );', - - 'void main(void)', - '{', - - ' G[0] = g0,', - ' G[1] = g1,', - ' G[2] = g2,', - ' G[3] = g3,', - ' G[4] = g4,', - ' G[5] = g5,', - ' G[6] = g6,', - ' G[7] = g7,', - ' G[8] = g8;', - - ' mat3 I;', - ' float cnv[9];', - ' vec3 sample;', + const mat3 g0 = mat3( 0.3535533845424652, 0, -0.3535533845424652, 0.5, 0, -0.5, 0.3535533845424652, 0, -0.3535533845424652 ); + const mat3 g1 = mat3( 0.3535533845424652, 0.5, 0.3535533845424652, 0, 0, 0, -0.3535533845424652, -0.5, -0.3535533845424652 ); + const mat3 g2 = mat3( 0, 0.3535533845424652, -0.5, -0.3535533845424652, 0, 0.3535533845424652, 0.5, -0.3535533845424652, 0 ); + const mat3 g3 = mat3( 0.5, -0.3535533845424652, 0, -0.3535533845424652, 0, 0.3535533845424652, 0, 0.3535533845424652, -0.5 ); + const mat3 g4 = mat3( 0, -0.5, 0, 0.5, 0, 0.5, 0, -0.5, 0 ); + const mat3 g5 = mat3( -0.5, 0, 0.5, 0, 0, 0, 0.5, 0, -0.5 ); + const mat3 g6 = mat3( 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.6666666865348816, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204 ); + const mat3 g7 = mat3( -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, 0.6666666865348816, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408 ); + const mat3 g8 = mat3( 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408 ); + + void main(void) + { + + G[0] = g0, + G[1] = g1, + G[2] = g2, + G[3] = g3, + G[4] = g4, + G[5] = g5, + G[6] = g6, + G[7] = g7, + G[8] = g8; + + mat3 I; + float cnv[9]; + vec3 sample; /* fetch the 3x3 neighbourhood and use the RGB vector's length as intensity value */ - ' for (float i=0.0; i<3.0; i++) {', - ' for (float j=0.0; j<3.0; j++) {', - ' sample = texture2D(tDiffuse, vUv + texel * vec2(i-1.0,j-1.0) ).rgb;', - ' I[int(i)][int(j)] = length(sample);', - ' }', - ' }', + for (float i=0.0; i<3.0; i++) { + for (float j=0.0; j<3.0; j++) { + sample = texture2D(tDiffuse, vUv + texel * vec2(i-1.0,j-1.0) ).rgb; + I[int(i)][int(j)] = length(sample); + } + } /* calculate the convolution values for all the masks */ - ' for (int i=0; i<9; i++) {', - ' float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]);', - ' cnv[i] = dp3 * dp3;', - ' }', + for (int i=0; i<9; i++) { + float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]); + cnv[i] = dp3 * dp3; + } - ' float M = (cnv[0] + cnv[1]) + (cnv[2] + cnv[3]);', - ' float S = (cnv[4] + cnv[5]) + (cnv[6] + cnv[7]) + (cnv[8] + M);', + float M = (cnv[0] + cnv[1]) + (cnv[2] + cnv[3]); + float S = (cnv[4] + cnv[5]) + (cnv[6] + cnv[7]) + (cnv[8] + M); - ' gl_FragColor = vec4(vec3(sqrt(M/S)), 1.0);', - '}' + gl_FragColor = vec4(vec3(sqrt(M/S)), 1.0); + }` - ].join( '\n' ) }; export { FreiChenShader }; diff --git a/examples/jsm/shaders/FresnelShader.js b/examples/jsm/shaders/FresnelShader.js index 1909e8c4c7f924..ab758a7629d728 100644 --- a/examples/jsm/shaders/FresnelShader.js +++ b/examples/jsm/shaders/FresnelShader.js @@ -2,7 +2,7 @@ * Based on Nvidia Cg tutorial */ -var FresnelShader = { +const FresnelShader = { uniforms: { @@ -14,60 +14,56 @@ var FresnelShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'uniform float mRefractionRatio;', - 'uniform float mFresnelBias;', - 'uniform float mFresnelScale;', - 'uniform float mFresnelPower;', + uniform float mRefractionRatio; + uniform float mFresnelBias; + uniform float mFresnelScale; + uniform float mFresnelPower; - 'varying vec3 vReflect;', - 'varying vec3 vRefract[3];', - 'varying float vReflectionFactor;', + varying vec3 vReflect; + varying vec3 vRefract[3]; + varying float vReflectionFactor; - 'void main() {', + void main() { - ' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );', - ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', + vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); + vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); - ' vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );', + vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal ); - ' vec3 I = worldPosition.xyz - cameraPosition;', + vec3 I = worldPosition.xyz - cameraPosition; - ' vReflect = reflect( I, worldNormal );', - ' vRefract[0] = refract( normalize( I ), worldNormal, mRefractionRatio );', - ' vRefract[1] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.99 );', - ' vRefract[2] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.98 );', - ' vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), mFresnelPower );', + vReflect = reflect( I, worldNormal ); + vRefract[0] = refract( normalize( I ), worldNormal, mRefractionRatio ); + vRefract[1] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.99 ); + vRefract[2] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.98 ); + vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), mFresnelPower ); - ' gl_Position = projectionMatrix * mvPosition;', + gl_Position = projectionMatrix * mvPosition; - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform samplerCube tCube; - 'uniform samplerCube tCube;', + varying vec3 vReflect; + varying vec3 vRefract[3]; + varying float vReflectionFactor; - 'varying vec3 vReflect;', - 'varying vec3 vRefract[3];', - 'varying float vReflectionFactor;', + void main() { - 'void main() {', + vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) ); + vec4 refractedColor = vec4( 1.0 ); - ' vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );', - ' vec4 refractedColor = vec4( 1.0 );', + refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r; + refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g; + refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b; - ' refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;', - ' refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;', - ' refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;', + gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) ); - ' gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/GammaCorrectionShader.js b/examples/jsm/shaders/GammaCorrectionShader.js index f6ca0895458b8b..e2f9546e2a53fd 100644 --- a/examples/jsm/shaders/GammaCorrectionShader.js +++ b/examples/jsm/shaders/GammaCorrectionShader.js @@ -3,7 +3,7 @@ * http://en.wikipedia.org/wiki/gamma_correction */ -var GammaCorrectionShader = { +const GammaCorrectionShader = { uniforms: { @@ -11,34 +11,30 @@ var GammaCorrectionShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 tex = texture2D( tDiffuse, vUv ); - ' vec4 tex = texture2D( tDiffuse, vUv );', + gl_FragColor = LinearTosRGB( tex ); // optional: LinearToGamma( tex, float( GAMMA_FACTOR ) ); - ' gl_FragColor = LinearTosRGB( tex );', // optional: LinearToGamma( tex, float( GAMMA_FACTOR ) ); - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/GodRaysShader.js b/examples/jsm/shaders/GodRaysShader.js index a6bee108ba0f6d..90b14686313dae 100644 --- a/examples/jsm/shaders/GodRaysShader.js +++ b/examples/jsm/shaders/GodRaysShader.js @@ -21,7 +21,7 @@ import { * Sousa2008 - Crysis Next Gen Effects, GDC2008, http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt */ -var GodRaysDepthMaskShader = { +const GodRaysDepthMaskShader = { uniforms: { @@ -31,33 +31,28 @@ var GodRaysDepthMaskShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + varying vec2 vUv; - 'varying vec2 vUv;', + uniform sampler2D tInput; - 'uniform sampler2D tInput;', + void main() { - 'void main() {', + gl_FragColor = vec4( 1.0 ) - texture2D( tInput, vUv ); - ' gl_FragColor = vec4( 1.0 ) - texture2D( tInput, vUv );', - - - '}' - - ].join( '\n' ) + }` }; @@ -77,7 +72,7 @@ var GodRaysDepthMaskShader = { * decreased distance between samples. */ -var GodRaysGenerateShader = { +const GodRaysGenerateShader = { uniforms: { @@ -93,47 +88,45 @@ var GodRaysGenerateShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + #define TAPS_PER_PASS 6.0 - '#define TAPS_PER_PASS 6.0', + varying vec2 vUv; - 'varying vec2 vUv;', + uniform sampler2D tInput; - 'uniform sampler2D tInput;', + uniform vec3 vSunPositionScreenSpace; + uniform float fStepSize; // filter step size - 'uniform vec3 vSunPositionScreenSpace;', - 'uniform float fStepSize;', // filter step size - - 'void main() {', + void main() { // delta from current pixel to "sun" position - ' vec2 delta = vSunPositionScreenSpace.xy - vUv;', - ' float dist = length( delta );', + vec2 delta = vSunPositionScreenSpace.xy - vUv; + float dist = length( delta ); // Step vector (uv space) - ' vec2 stepv = fStepSize * delta / dist;', + vec2 stepv = fStepSize * delta / dist; // Number of iterations between pixel and sun - ' float iters = dist/fStepSize;', + float iters = dist/fStepSize; - ' vec2 uv = vUv.xy;', - ' float col = 0.0;', + vec2 uv = vUv.xy; + float col = 0.0; // This breaks ANGLE in Chrome 22 // - see http://code.google.com/p/chromium/issues/detail?id=153105 @@ -160,39 +153,37 @@ var GodRaysGenerateShader = { // Unrolling loop manually makes it work in ANGLE - ' float f = min( 1.0, max( vSunPositionScreenSpace.z / 1000.0, 0.0 ) );', // used to fade out godrays + float f = min( 1.0, max( vSunPositionScreenSpace.z / 1000.0, 0.0 ) ); // used to fade out godrays - ' if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f;', - ' uv += stepv;', + if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; + uv += stepv; - ' if ( 1.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f;', - ' uv += stepv;', + if ( 1.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; + uv += stepv; - ' if ( 2.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f;', - ' uv += stepv;', + if ( 2.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; + uv += stepv; - ' if ( 3.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f;', - ' uv += stepv;', + if ( 3.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; + uv += stepv; - ' if ( 4.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f;', - ' uv += stepv;', + if ( 4.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; + uv += stepv; - ' if ( 5.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f;', - ' uv += stepv;', + if ( 5.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; + uv += stepv; - // Should technically be dividing by 'iters', but 'TAPS_PER_PASS' smooths out + // Should technically be dividing by 'iters but 'TAPS_PER_PASS' smooths out // objectionable artifacts, in particular near the sun position. The side // effect is that the result is darker than it should be around the sun, as // TAPS_PER_PASS is greater than the number of samples actually accumulated. - // When the result is inverted (in the shader 'godrays_combine', this produces + // When the result is inverted (in the shader 'godrays_combine this produces // a slight bright spot at the position of the sun, even when it is occluded. - ' gl_FragColor = vec4( col/TAPS_PER_PASS );', - ' gl_FragColor.a = 1.0;', - - '}' + gl_FragColor = vec4( col/TAPS_PER_PASS ); + gl_FragColor.a = 1.0; - ].join( '\n' ) + }` }; @@ -201,7 +192,7 @@ var GodRaysGenerateShader = { * fGodRayIntensity attenuates the god rays. */ -var GodRaysCombineShader = { +const GodRaysCombineShader = { uniforms: { @@ -219,40 +210,36 @@ var GodRaysCombineShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + varying vec2 vUv; - 'varying vec2 vUv;', + uniform sampler2D tColors; + uniform sampler2D tGodRays; - 'uniform sampler2D tColors;', - 'uniform sampler2D tGodRays;', + uniform float fGodRayIntensity; - 'uniform float fGodRayIntensity;', - - 'void main() {', + void main() { // Since THREE.MeshDepthMaterial renders foreground objects white and background // objects black, the god-rays will be white streaks. Therefore value is inverted // before being combined with tColors - ' gl_FragColor = texture2D( tColors, vUv ) + fGodRayIntensity * vec4( 1.0 - texture2D( tGodRays, vUv ).r );', - ' gl_FragColor.a = 1.0;', - - '}' + gl_FragColor = texture2D( tColors, vUv ) + fGodRayIntensity * vec4( 1.0 - texture2D( tGodRays, vUv ).r ); + gl_FragColor.a = 1.0; - ].join( '\n' ) + }` }; @@ -262,7 +249,7 @@ var GodRaysCombineShader = { * cheaper/faster/simpler to implement this as a simple sun sprite. */ -var GodRaysFakeSunShader = { +const GodRaysFakeSunShader = { uniforms: { @@ -284,46 +271,42 @@ var GodRaysFakeSunShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + varying vec2 vUv; - 'varying vec2 vUv;', + uniform vec3 vSunPositionScreenSpace; + uniform float fAspect; - 'uniform vec3 vSunPositionScreenSpace;', - 'uniform float fAspect;', + uniform vec3 sunColor; + uniform vec3 bgColor; - 'uniform vec3 sunColor;', - 'uniform vec3 bgColor;', + void main() { - 'void main() {', - - ' vec2 diff = vUv - vSunPositionScreenSpace.xy;', + vec2 diff = vUv - vSunPositionScreenSpace.xy; // Correct for aspect ratio - ' diff.x *= fAspect;', - - ' float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 );', - ' prop = 0.35 * pow( 1.0 - prop, 3.0 );', + diff.x *= fAspect; - ' gl_FragColor.xyz = ( vSunPositionScreenSpace.z > 0.0 ) ? mix( sunColor, bgColor, 1.0 - prop ) : bgColor;', - ' gl_FragColor.w = 1.0;', + float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 ); + prop = 0.35 * pow( 1.0 - prop, 3.0 ); - '}' + gl_FragColor.xyz = ( vSunPositionScreenSpace.z > 0.0 ) ? mix( sunColor, bgColor, 1.0 - prop ) : bgColor; + gl_FragColor.w = 1.0; - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/HalftoneShader.js b/examples/jsm/shaders/HalftoneShader.js index d34ed6baec5b4f..b586070349fc84 100644 --- a/examples/jsm/shaders/HalftoneShader.js +++ b/examples/jsm/shaders/HalftoneShader.js @@ -5,7 +5,7 @@ * Blending Mode (1 = Linear, 2 = Multiply, 3 = Add, 4 = Lighter, 5 = Darker) */ -var HalftoneShader = { +const HalftoneShader = { uniforms: { 'tDiffuse': { value: null }, @@ -23,291 +23,287 @@ var HalftoneShader = { 'disable': { value: false } }, - vertexShader: [ - - 'varying vec2 vUV;', - - 'void main() {', - - ' vUV = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);', - - '}' - - ].join( '\n' ), - - fragmentShader: [ - - '#define SQRT2_MINUS_ONE 0.41421356', - '#define SQRT2_HALF_MINUS_ONE 0.20710678', - '#define PI2 6.28318531', - '#define SHAPE_DOT 1', - '#define SHAPE_ELLIPSE 2', - '#define SHAPE_LINE 3', - '#define SHAPE_SQUARE 4', - '#define BLENDING_LINEAR 1', - '#define BLENDING_MULTIPLY 2', - '#define BLENDING_ADD 3', - '#define BLENDING_LIGHTER 4', - '#define BLENDING_DARKER 5', - 'uniform sampler2D tDiffuse;', - 'uniform float radius;', - 'uniform float rotateR;', - 'uniform float rotateG;', - 'uniform float rotateB;', - 'uniform float scatter;', - 'uniform float width;', - 'uniform float height;', - 'uniform int shape;', - 'uniform bool disable;', - 'uniform float blending;', - 'uniform int blendingMode;', - 'varying vec2 vUV;', - 'uniform bool greyscale;', - 'const int samples = 8;', - - 'float blend( float a, float b, float t ) {', + vertexShader: /* glsl */` + + varying vec2 vUV; + + void main() { + + vUV = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + + }`, + + fragmentShader: /* glsl */` + + #define SQRT2_MINUS_ONE 0.41421356 + #define SQRT2_HALF_MINUS_ONE 0.20710678 + #define PI2 6.28318531 + #define SHAPE_DOT 1 + #define SHAPE_ELLIPSE 2 + #define SHAPE_LINE 3 + #define SHAPE_SQUARE 4 + #define BLENDING_LINEAR 1 + #define BLENDING_MULTIPLY 2 + #define BLENDING_ADD 3 + #define BLENDING_LIGHTER 4 + #define BLENDING_DARKER 5 + uniform sampler2D tDiffuse; + uniform float radius; + uniform float rotateR; + uniform float rotateG; + uniform float rotateB; + uniform float scatter; + uniform float width; + uniform float height; + uniform int shape; + uniform bool disable; + uniform float blending; + uniform int blendingMode; + varying vec2 vUV; + uniform bool greyscale; + const int samples = 8; + + float blend( float a, float b, float t ) { // linear blend - ' return a * ( 1.0 - t ) + b * t;', + return a * ( 1.0 - t ) + b * t; - '}', + } - 'float hypot( float x, float y ) {', + float hypot( float x, float y ) { // vector magnitude - ' return sqrt( x * x + y * y );', + return sqrt( x * x + y * y ); - '}', + } - 'float rand( vec2 seed ){', + float rand( vec2 seed ){ // get pseudo-random number - 'return fract( sin( dot( seed.xy, vec2( 12.9898, 78.233 ) ) ) * 43758.5453 );', + return fract( sin( dot( seed.xy, vec2( 12.9898, 78.233 ) ) ) * 43758.5453 ); - '}', + } - 'float distanceToDotRadius( float channel, vec2 coord, vec2 normal, vec2 p, float angle, float rad_max ) {', + float distanceToDotRadius( float channel, vec2 coord, vec2 normal, vec2 p, float angle, float rad_max ) { // apply shape-specific transforms - ' float dist = hypot( coord.x - p.x, coord.y - p.y );', - ' float rad = channel;', + float dist = hypot( coord.x - p.x, coord.y - p.y ); + float rad = channel; - ' if ( shape == SHAPE_DOT ) {', + if ( shape == SHAPE_DOT ) { - ' rad = pow( abs( rad ), 1.125 ) * rad_max;', + rad = pow( abs( rad ), 1.125 ) * rad_max; - ' } else if ( shape == SHAPE_ELLIPSE ) {', + } else if ( shape == SHAPE_ELLIPSE ) { - ' rad = pow( abs( rad ), 1.125 ) * rad_max;', + rad = pow( abs( rad ), 1.125 ) * rad_max; - ' if ( dist != 0.0 ) {', - ' float dot_p = abs( ( p.x - coord.x ) / dist * normal.x + ( p.y - coord.y ) / dist * normal.y );', - ' dist = ( dist * ( 1.0 - SQRT2_HALF_MINUS_ONE ) ) + dot_p * dist * SQRT2_MINUS_ONE;', - ' }', + if ( dist != 0.0 ) { + float dot_p = abs( ( p.x - coord.x ) / dist * normal.x + ( p.y - coord.y ) / dist * normal.y ); + dist = ( dist * ( 1.0 - SQRT2_HALF_MINUS_ONE ) ) + dot_p * dist * SQRT2_MINUS_ONE; + } - ' } else if ( shape == SHAPE_LINE ) {', + } else if ( shape == SHAPE_LINE ) { - ' rad = pow( abs( rad ), 1.5) * rad_max;', - ' float dot_p = ( p.x - coord.x ) * normal.x + ( p.y - coord.y ) * normal.y;', - ' dist = hypot( normal.x * dot_p, normal.y * dot_p );', + rad = pow( abs( rad ), 1.5) * rad_max; + float dot_p = ( p.x - coord.x ) * normal.x + ( p.y - coord.y ) * normal.y; + dist = hypot( normal.x * dot_p, normal.y * dot_p ); - ' } else if ( shape == SHAPE_SQUARE ) {', + } else if ( shape == SHAPE_SQUARE ) { - ' float theta = atan( p.y - coord.y, p.x - coord.x ) - angle;', - ' float sin_t = abs( sin( theta ) );', - ' float cos_t = abs( cos( theta ) );', - ' rad = pow( abs( rad ), 1.4 );', - ' rad = rad_max * ( rad + ( ( sin_t > cos_t ) ? rad - sin_t * rad : rad - cos_t * rad ) );', + float theta = atan( p.y - coord.y, p.x - coord.x ) - angle; + float sin_t = abs( sin( theta ) ); + float cos_t = abs( cos( theta ) ); + rad = pow( abs( rad ), 1.4 ); + rad = rad_max * ( rad + ( ( sin_t > cos_t ) ? rad - sin_t * rad : rad - cos_t * rad ) ); - ' }', + } - ' return rad - dist;', + return rad - dist; - '}', + } - 'struct Cell {', + struct Cell { // grid sample positions - ' vec2 normal;', - ' vec2 p1;', - ' vec2 p2;', - ' vec2 p3;', - ' vec2 p4;', - ' float samp2;', - ' float samp1;', - ' float samp3;', - ' float samp4;', + vec2 normal; + vec2 p1; + vec2 p2; + vec2 p3; + vec2 p4; + float samp2; + float samp1; + float samp3; + float samp4; - '};', + }; - 'vec4 getSample( vec2 point ) {', + vec4 getSample( vec2 point ) { // multi-sampled point - ' vec4 tex = texture2D( tDiffuse, vec2( point.x / width, point.y / height ) );', - ' float base = rand( vec2( floor( point.x ), floor( point.y ) ) ) * PI2;', - ' float step = PI2 / float( samples );', - ' float dist = radius * 0.66;', + vec4 tex = texture2D( tDiffuse, vec2( point.x / width, point.y / height ) ); + float base = rand( vec2( floor( point.x ), floor( point.y ) ) ) * PI2; + float step = PI2 / float( samples ); + float dist = radius * 0.66; - ' for ( int i = 0; i < samples; ++i ) {', + for ( int i = 0; i < samples; ++i ) { - ' float r = base + step * float( i );', - ' vec2 coord = point + vec2( cos( r ) * dist, sin( r ) * dist );', - ' tex += texture2D( tDiffuse, vec2( coord.x / width, coord.y / height ) );', + float r = base + step * float( i ); + vec2 coord = point + vec2( cos( r ) * dist, sin( r ) * dist ); + tex += texture2D( tDiffuse, vec2( coord.x / width, coord.y / height ) ); - ' }', + } - ' tex /= float( samples ) + 1.0;', - ' return tex;', + tex /= float( samples ) + 1.0; + return tex; - '}', + } - 'float getDotColour( Cell c, vec2 p, int channel, float angle, float aa ) {', + float getDotColour( Cell c, vec2 p, int channel, float angle, float aa ) { // get colour for given point - ' float dist_c_1, dist_c_2, dist_c_3, dist_c_4, res;', + float dist_c_1, dist_c_2, dist_c_3, dist_c_4, res; - ' if ( channel == 0 ) {', + if ( channel == 0 ) { - ' c.samp1 = getSample( c.p1 ).r;', - ' c.samp2 = getSample( c.p2 ).r;', - ' c.samp3 = getSample( c.p3 ).r;', - ' c.samp4 = getSample( c.p4 ).r;', + c.samp1 = getSample( c.p1 ).r; + c.samp2 = getSample( c.p2 ).r; + c.samp3 = getSample( c.p3 ).r; + c.samp4 = getSample( c.p4 ).r; - ' } else if (channel == 1) {', + } else if (channel == 1) { - ' c.samp1 = getSample( c.p1 ).g;', - ' c.samp2 = getSample( c.p2 ).g;', - ' c.samp3 = getSample( c.p3 ).g;', - ' c.samp4 = getSample( c.p4 ).g;', + c.samp1 = getSample( c.p1 ).g; + c.samp2 = getSample( c.p2 ).g; + c.samp3 = getSample( c.p3 ).g; + c.samp4 = getSample( c.p4 ).g; - ' } else {', + } else { - ' c.samp1 = getSample( c.p1 ).b;', - ' c.samp3 = getSample( c.p3 ).b;', - ' c.samp2 = getSample( c.p2 ).b;', - ' c.samp4 = getSample( c.p4 ).b;', + c.samp1 = getSample( c.p1 ).b; + c.samp3 = getSample( c.p3 ).b; + c.samp2 = getSample( c.p2 ).b; + c.samp4 = getSample( c.p4 ).b; - ' }', + } - ' dist_c_1 = distanceToDotRadius( c.samp1, c.p1, c.normal, p, angle, radius );', - ' dist_c_2 = distanceToDotRadius( c.samp2, c.p2, c.normal, p, angle, radius );', - ' dist_c_3 = distanceToDotRadius( c.samp3, c.p3, c.normal, p, angle, radius );', - ' dist_c_4 = distanceToDotRadius( c.samp4, c.p4, c.normal, p, angle, radius );', - ' res = ( dist_c_1 > 0.0 ) ? clamp( dist_c_1 / aa, 0.0, 1.0 ) : 0.0;', - ' res += ( dist_c_2 > 0.0 ) ? clamp( dist_c_2 / aa, 0.0, 1.0 ) : 0.0;', - ' res += ( dist_c_3 > 0.0 ) ? clamp( dist_c_3 / aa, 0.0, 1.0 ) : 0.0;', - ' res += ( dist_c_4 > 0.0 ) ? clamp( dist_c_4 / aa, 0.0, 1.0 ) : 0.0;', - ' res = clamp( res, 0.0, 1.0 );', + dist_c_1 = distanceToDotRadius( c.samp1, c.p1, c.normal, p, angle, radius ); + dist_c_2 = distanceToDotRadius( c.samp2, c.p2, c.normal, p, angle, radius ); + dist_c_3 = distanceToDotRadius( c.samp3, c.p3, c.normal, p, angle, radius ); + dist_c_4 = distanceToDotRadius( c.samp4, c.p4, c.normal, p, angle, radius ); + res = ( dist_c_1 > 0.0 ) ? clamp( dist_c_1 / aa, 0.0, 1.0 ) : 0.0; + res += ( dist_c_2 > 0.0 ) ? clamp( dist_c_2 / aa, 0.0, 1.0 ) : 0.0; + res += ( dist_c_3 > 0.0 ) ? clamp( dist_c_3 / aa, 0.0, 1.0 ) : 0.0; + res += ( dist_c_4 > 0.0 ) ? clamp( dist_c_4 / aa, 0.0, 1.0 ) : 0.0; + res = clamp( res, 0.0, 1.0 ); - ' return res;', + return res; - '}', + } - 'Cell getReferenceCell( vec2 p, vec2 origin, float grid_angle, float step ) {', + Cell getReferenceCell( vec2 p, vec2 origin, float grid_angle, float step ) { // get containing cell - ' Cell c;', + Cell c; // calc grid - ' vec2 n = vec2( cos( grid_angle ), sin( grid_angle ) );', - ' float threshold = step * 0.5;', - ' float dot_normal = n.x * ( p.x - origin.x ) + n.y * ( p.y - origin.y );', - ' float dot_line = -n.y * ( p.x - origin.x ) + n.x * ( p.y - origin.y );', - ' vec2 offset = vec2( n.x * dot_normal, n.y * dot_normal );', - ' float offset_normal = mod( hypot( offset.x, offset.y ), step );', - ' float normal_dir = ( dot_normal < 0.0 ) ? 1.0 : -1.0;', - ' float normal_scale = ( ( offset_normal < threshold ) ? -offset_normal : step - offset_normal ) * normal_dir;', - ' float offset_line = mod( hypot( ( p.x - offset.x ) - origin.x, ( p.y - offset.y ) - origin.y ), step );', - ' float line_dir = ( dot_line < 0.0 ) ? 1.0 : -1.0;', - ' float line_scale = ( ( offset_line < threshold ) ? -offset_line : step - offset_line ) * line_dir;', + vec2 n = vec2( cos( grid_angle ), sin( grid_angle ) ); + float threshold = step * 0.5; + float dot_normal = n.x * ( p.x - origin.x ) + n.y * ( p.y - origin.y ); + float dot_line = -n.y * ( p.x - origin.x ) + n.x * ( p.y - origin.y ); + vec2 offset = vec2( n.x * dot_normal, n.y * dot_normal ); + float offset_normal = mod( hypot( offset.x, offset.y ), step ); + float normal_dir = ( dot_normal < 0.0 ) ? 1.0 : -1.0; + float normal_scale = ( ( offset_normal < threshold ) ? -offset_normal : step - offset_normal ) * normal_dir; + float offset_line = mod( hypot( ( p.x - offset.x ) - origin.x, ( p.y - offset.y ) - origin.y ), step ); + float line_dir = ( dot_line < 0.0 ) ? 1.0 : -1.0; + float line_scale = ( ( offset_line < threshold ) ? -offset_line : step - offset_line ) * line_dir; // get closest corner - ' c.normal = n;', - ' c.p1.x = p.x - n.x * normal_scale + n.y * line_scale;', - ' c.p1.y = p.y - n.y * normal_scale - n.x * line_scale;', + c.normal = n; + c.p1.x = p.x - n.x * normal_scale + n.y * line_scale; + c.p1.y = p.y - n.y * normal_scale - n.x * line_scale; // scatter - ' if ( scatter != 0.0 ) {', + if ( scatter != 0.0 ) { - ' float off_mag = scatter * threshold * 0.5;', - ' float off_angle = rand( vec2( floor( c.p1.x ), floor( c.p1.y ) ) ) * PI2;', - ' c.p1.x += cos( off_angle ) * off_mag;', - ' c.p1.y += sin( off_angle ) * off_mag;', + float off_mag = scatter * threshold * 0.5; + float off_angle = rand( vec2( floor( c.p1.x ), floor( c.p1.y ) ) ) * PI2; + c.p1.x += cos( off_angle ) * off_mag; + c.p1.y += sin( off_angle ) * off_mag; - ' }', + } // find corners - ' float normal_step = normal_dir * ( ( offset_normal < threshold ) ? step : -step );', - ' float line_step = line_dir * ( ( offset_line < threshold ) ? step : -step );', - ' c.p2.x = c.p1.x - n.x * normal_step;', - ' c.p2.y = c.p1.y - n.y * normal_step;', - ' c.p3.x = c.p1.x + n.y * line_step;', - ' c.p3.y = c.p1.y - n.x * line_step;', - ' c.p4.x = c.p1.x - n.x * normal_step + n.y * line_step;', - ' c.p4.y = c.p1.y - n.y * normal_step - n.x * line_step;', + float normal_step = normal_dir * ( ( offset_normal < threshold ) ? step : -step ); + float line_step = line_dir * ( ( offset_line < threshold ) ? step : -step ); + c.p2.x = c.p1.x - n.x * normal_step; + c.p2.y = c.p1.y - n.y * normal_step; + c.p3.x = c.p1.x + n.y * line_step; + c.p3.y = c.p1.y - n.x * line_step; + c.p4.x = c.p1.x - n.x * normal_step + n.y * line_step; + c.p4.y = c.p1.y - n.y * normal_step - n.x * line_step; - ' return c;', + return c; - '}', + } - 'float blendColour( float a, float b, float t ) {', + float blendColour( float a, float b, float t ) { // blend colours - ' if ( blendingMode == BLENDING_LINEAR ) {', - ' return blend( a, b, 1.0 - t );', - ' } else if ( blendingMode == BLENDING_ADD ) {', - ' return blend( a, min( 1.0, a + b ), t );', - ' } else if ( blendingMode == BLENDING_MULTIPLY ) {', - ' return blend( a, max( 0.0, a * b ), t );', - ' } else if ( blendingMode == BLENDING_LIGHTER ) {', - ' return blend( a, max( a, b ), t );', - ' } else if ( blendingMode == BLENDING_DARKER ) {', - ' return blend( a, min( a, b ), t );', - ' } else {', - ' return blend( a, b, 1.0 - t );', - ' }', - - '}', - - 'void main() {', - - ' if ( ! disable ) {', + if ( blendingMode == BLENDING_LINEAR ) { + return blend( a, b, 1.0 - t ); + } else if ( blendingMode == BLENDING_ADD ) { + return blend( a, min( 1.0, a + b ), t ); + } else if ( blendingMode == BLENDING_MULTIPLY ) { + return blend( a, max( 0.0, a * b ), t ); + } else if ( blendingMode == BLENDING_LIGHTER ) { + return blend( a, max( a, b ), t ); + } else if ( blendingMode == BLENDING_DARKER ) { + return blend( a, min( a, b ), t ); + } else { + return blend( a, b, 1.0 - t ); + } + + } + + void main() { + + if ( ! disable ) { // setup - ' vec2 p = vec2( vUV.x * width, vUV.y * height );', - ' vec2 origin = vec2( 0, 0 );', - ' float aa = ( radius < 2.5 ) ? radius * 0.5 : 1.25;', + vec2 p = vec2( vUV.x * width, vUV.y * height ); + vec2 origin = vec2( 0, 0 ); + float aa = ( radius < 2.5 ) ? radius * 0.5 : 1.25; // get channel samples - ' Cell cell_r = getReferenceCell( p, origin, rotateR, radius );', - ' Cell cell_g = getReferenceCell( p, origin, rotateG, radius );', - ' Cell cell_b = getReferenceCell( p, origin, rotateB, radius );', - ' float r = getDotColour( cell_r, p, 0, rotateR, aa );', - ' float g = getDotColour( cell_g, p, 1, rotateG, aa );', - ' float b = getDotColour( cell_b, p, 2, rotateB, aa );', + Cell cell_r = getReferenceCell( p, origin, rotateR, radius ); + Cell cell_g = getReferenceCell( p, origin, rotateG, radius ); + Cell cell_b = getReferenceCell( p, origin, rotateB, radius ); + float r = getDotColour( cell_r, p, 0, rotateR, aa ); + float g = getDotColour( cell_g, p, 1, rotateG, aa ); + float b = getDotColour( cell_b, p, 2, rotateB, aa ); // blend with original - ' vec4 colour = texture2D( tDiffuse, vUV );', - ' r = blendColour( r, colour.r, blending );', - ' g = blendColour( g, colour.g, blending );', - ' b = blendColour( b, colour.b, blending );', + vec4 colour = texture2D( tDiffuse, vUV ); + r = blendColour( r, colour.r, blending ); + g = blendColour( g, colour.g, blending ); + b = blendColour( b, colour.b, blending ); - ' if ( greyscale ) {', - ' r = g = b = (r + b + g) / 3.0;', - ' }', + if ( greyscale ) { + r = g = b = (r + b + g) / 3.0; + } - ' gl_FragColor = vec4( r, g, b, 1.0 );', + gl_FragColor = vec4( r, g, b, 1.0 ); - ' } else {', + } else { - ' gl_FragColor = texture2D( tDiffuse, vUV );', + gl_FragColor = texture2D( tDiffuse, vUV ); - ' }', + } - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/HorizontalBlurShader.js b/examples/jsm/shaders/HorizontalBlurShader.js index 256640a17eb622..2892bffd24162c 100644 --- a/examples/jsm/shaders/HorizontalBlurShader.js +++ b/examples/jsm/shaders/HorizontalBlurShader.js @@ -17,45 +17,41 @@ var HorizontalBlurShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float h; - 'uniform sampler2D tDiffuse;', - 'uniform float h;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 sum = vec4( 0.0 ); - ' vec4 sum = vec4( 0.0 );', + sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051; + sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633; + sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051; - ' sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;', - ' sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;', + gl_FragColor = sum; - ' gl_FragColor = sum;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/HorizontalTiltShiftShader.js b/examples/jsm/shaders/HorizontalTiltShiftShader.js index 5af4585bd18191..26a4db2e44be4c 100644 --- a/examples/jsm/shaders/HorizontalTiltShiftShader.js +++ b/examples/jsm/shaders/HorizontalTiltShiftShader.js @@ -17,48 +17,44 @@ var HorizontalTiltShiftShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float h; + uniform float r; - 'uniform sampler2D tDiffuse;', - 'uniform float h;', - 'uniform float r;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 sum = vec4( 0.0 ); - ' vec4 sum = vec4( 0.0 );', + float hh = h * abs( r - vUv.y ); - ' float hh = h * abs( r - vUv.y );', + sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051; + sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633; + sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051; - ' sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;', - ' sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;', + gl_FragColor = sum; - ' gl_FragColor = sum;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/HueSaturationShader.js b/examples/jsm/shaders/HueSaturationShader.js index e1b1f474780de6..880dcae07325eb 100644 --- a/examples/jsm/shaders/HueSaturationShader.js +++ b/examples/jsm/shaders/HueSaturationShader.js @@ -5,7 +5,7 @@ * saturation: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast) */ -var HueSaturationShader = { +const HueSaturationShader = { uniforms: { @@ -15,54 +15,50 @@ var HueSaturationShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float hue; + uniform float saturation; - 'uniform sampler2D tDiffuse;', - 'uniform float hue;', - 'uniform float saturation;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + gl_FragColor = texture2D( tDiffuse, vUv ); - ' gl_FragColor = texture2D( tDiffuse, vUv );', + // hue + float angle = hue * 3.14159265; + float s = sin(angle), c = cos(angle); + vec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0; + float len = length(gl_FragColor.rgb); + gl_FragColor.rgb = vec3( + dot(gl_FragColor.rgb, weights.xyz), + dot(gl_FragColor.rgb, weights.zxy), + dot(gl_FragColor.rgb, weights.yzx) + ); - // hue - ' float angle = hue * 3.14159265;', - ' float s = sin(angle), c = cos(angle);', - ' vec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0;', - ' float len = length(gl_FragColor.rgb);', - ' gl_FragColor.rgb = vec3(', - ' dot(gl_FragColor.rgb, weights.xyz),', - ' dot(gl_FragColor.rgb, weights.zxy),', - ' dot(gl_FragColor.rgb, weights.yzx)', - ' );', + // saturation + float average = (gl_FragColor.r + gl_FragColor.g + gl_FragColor.b) / 3.0; + if (saturation > 0.0) { + gl_FragColor.rgb += (average - gl_FragColor.rgb) * (1.0 - 1.0 / (1.001 - saturation)); + } else { + gl_FragColor.rgb += (average - gl_FragColor.rgb) * (-saturation); + } - // saturation - ' float average = (gl_FragColor.r + gl_FragColor.g + gl_FragColor.b) / 3.0;', - ' if (saturation > 0.0) {', - ' gl_FragColor.rgb += (average - gl_FragColor.rgb) * (1.0 - 1.0 / (1.001 - saturation));', - ' } else {', - ' gl_FragColor.rgb += (average - gl_FragColor.rgb) * (-saturation);', - ' }', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/KaleidoShader.js b/examples/jsm/shaders/KaleidoShader.js index 8604c688dcff59..9f1fb0aa2f18bf 100644 --- a/examples/jsm/shaders/KaleidoShader.js +++ b/examples/jsm/shaders/KaleidoShader.js @@ -8,7 +8,7 @@ * angle: initial angle in radians */ -var KaleidoShader = { +const KaleidoShader = { uniforms: { @@ -18,42 +18,38 @@ var KaleidoShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float sides; + uniform float angle; - 'uniform sampler2D tDiffuse;', - 'uniform float sides;', - 'uniform float angle;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec2 p = vUv - 0.5; + float r = length(p); + float a = atan(p.y, p.x) + angle; + float tau = 2. * 3.1416 ; + a = mod(a, tau/sides); + a = abs(a - tau/sides/2.) ; + p = r * vec2(cos(a), sin(a)); + vec4 color = texture2D(tDiffuse, p + 0.5); + gl_FragColor = color; - ' vec2 p = vUv - 0.5;', - ' float r = length(p);', - ' float a = atan(p.y, p.x) + angle;', - ' float tau = 2. * 3.1416 ;', - ' a = mod(a, tau/sides);', - ' a = abs(a - tau/sides/2.) ;', - ' p = r * vec2(cos(a), sin(a));', - ' vec4 color = texture2D(tDiffuse, p + 0.5);', - ' gl_FragColor = color;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/LuminosityHighPassShader.js b/examples/jsm/shaders/LuminosityHighPassShader.js index 06a124e8b7d8c3..da92b52a359566 100644 --- a/examples/jsm/shaders/LuminosityHighPassShader.js +++ b/examples/jsm/shaders/LuminosityHighPassShader.js @@ -7,7 +7,7 @@ import { * http://en.wikipedia.org/wiki/Luminosity */ -var LuminosityHighPassShader = { +const LuminosityHighPassShader = { shaderID: 'luminosityHighPass', @@ -21,47 +21,43 @@ var LuminosityHighPassShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform vec3 defaultColor; + uniform float defaultOpacity; + uniform float luminosityThreshold; + uniform float smoothWidth; - 'uniform sampler2D tDiffuse;', - 'uniform vec3 defaultColor;', - 'uniform float defaultOpacity;', - 'uniform float luminosityThreshold;', - 'uniform float smoothWidth;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 texel = texture2D( tDiffuse, vUv ); - ' vec4 texel = texture2D( tDiffuse, vUv );', + vec3 luma = vec3( 0.299, 0.587, 0.114 ); - ' vec3 luma = vec3( 0.299, 0.587, 0.114 );', + float v = dot( texel.xyz, luma ); - ' float v = dot( texel.xyz, luma );', + vec4 outputColor = vec4( defaultColor.rgb, defaultOpacity ); - ' vec4 outputColor = vec4( defaultColor.rgb, defaultOpacity );', + float alpha = smoothstep( luminosityThreshold, luminosityThreshold + smoothWidth, v ); - ' float alpha = smoothstep( luminosityThreshold, luminosityThreshold + smoothWidth, v );', + gl_FragColor = mix( outputColor, texel, alpha ); - ' gl_FragColor = mix( outputColor, texel, alpha );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/LuminosityShader.js b/examples/jsm/shaders/LuminosityShader.js index e0a4c381f10280..1325af32c02175 100644 --- a/examples/jsm/shaders/LuminosityShader.js +++ b/examples/jsm/shaders/LuminosityShader.js @@ -3,7 +3,7 @@ * http://en.wikipedia.org/wiki/Luminosity */ -var LuminosityShader = { +const LuminosityShader = { uniforms: { @@ -11,39 +11,35 @@ var LuminosityShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + #include - '#include ', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 texel = texture2D( tDiffuse, vUv ); - ' vec4 texel = texture2D( tDiffuse, vUv );', + float l = linearToRelativeLuminance( texel.rgb ); - ' float l = linearToRelativeLuminance( texel.rgb );', + gl_FragColor = vec4( l, l, l, texel.w ); - ' gl_FragColor = vec4( l, l, l, texel.w );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/MirrorShader.js b/examples/jsm/shaders/MirrorShader.js index c086e44841f5c4..6544cec03f652a 100644 --- a/examples/jsm/shaders/MirrorShader.js +++ b/examples/jsm/shaders/MirrorShader.js @@ -5,7 +5,7 @@ * side: side of input to mirror (0 = left, 1 = right, 2 = top, 3 = bottom) */ -var MirrorShader = { +const MirrorShader = { uniforms: { @@ -14,44 +14,40 @@ var MirrorShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform int side; - 'uniform sampler2D tDiffuse;', - 'uniform int side;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec2 p = vUv; + if (side == 0){ + if (p.x > 0.5) p.x = 1.0 - p.x; + }else if (side == 1){ + if (p.x < 0.5) p.x = 1.0 - p.x; + }else if (side == 2){ + if (p.y < 0.5) p.y = 1.0 - p.y; + }else if (side == 3){ + if (p.y > 0.5) p.y = 1.0 - p.y; + } + vec4 color = texture2D(tDiffuse, p); + gl_FragColor = color; - ' vec2 p = vUv;', - ' if (side == 0){', - ' if (p.x > 0.5) p.x = 1.0 - p.x;', - ' }else if (side == 1){', - ' if (p.x < 0.5) p.x = 1.0 - p.x;', - ' }else if (side == 2){', - ' if (p.y < 0.5) p.y = 1.0 - p.y;', - ' }else if (side == 3){', - ' if (p.y > 0.5) p.y = 1.0 - p.y;', - ' } ', - ' vec4 color = texture2D(tDiffuse, p);', - ' gl_FragColor = color;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/NormalMapShader.js b/examples/jsm/shaders/NormalMapShader.js index d520c2577d59f0..a9b326da704153 100644 --- a/examples/jsm/shaders/NormalMapShader.js +++ b/examples/jsm/shaders/NormalMapShader.js @@ -7,7 +7,7 @@ import { * - compute normals from heightmap */ -var NormalMapShader = { +const NormalMapShader = { uniforms: { @@ -18,39 +18,35 @@ var NormalMapShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float height; + uniform vec2 resolution; + uniform sampler2D heightMap; - 'uniform float height;', - 'uniform vec2 resolution;', - 'uniform sampler2D heightMap;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + float val = texture2D( heightMap, vUv ).x; - ' float val = texture2D( heightMap, vUv ).x;', + float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x; + float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x; - ' float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;', - ' float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;', + gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 ); - ' gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height ) ) + 0.5 ), 1.0 );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/ParallaxShader.js b/examples/jsm/shaders/ParallaxShader.js index 1ca00c87da35d7..a5ec71b461ea3f 100644 --- a/examples/jsm/shaders/ParallaxShader.js +++ b/examples/jsm/shaders/ParallaxShader.js @@ -3,7 +3,7 @@ // No tangent-space transforms logic based on // http://mmikkelsen3d.blogspot.sk/2012/02/parallaxpoc-mapping-and-no-tangent.html -var ParallaxShader = { +const ParallaxShader = { // Ordered from fastest to best quality. modes: { none: 'NO_PARALLAX', @@ -21,165 +21,163 @@ var ParallaxShader = { 'parallaxMaxLayers': { value: null } }, - vertexShader: [ - 'varying vec2 vUv;', - 'varying vec3 vViewPosition;', - 'varying vec3 vNormal;', + vertexShader: /* glsl */` - 'void main() {', + varying vec2 vUv; + varying vec3 vViewPosition; + varying vec3 vNormal; - ' vUv = uv;', - ' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );', - ' vViewPosition = -mvPosition.xyz;', - ' vNormal = normalize( normalMatrix * normal );', - ' gl_Position = projectionMatrix * mvPosition;', + void main() { - '}' + vUv = uv; + vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); + vViewPosition = -mvPosition.xyz; + vNormal = normalize( normalMatrix * normal ); + gl_Position = projectionMatrix * mvPosition; - ].join( '\n' ), + }`, - fragmentShader: [ - 'uniform sampler2D bumpMap;', - 'uniform sampler2D map;', + fragmentShader: /* glsl */` - 'uniform float parallaxScale;', - 'uniform float parallaxMinLayers;', - 'uniform float parallaxMaxLayers;', + uniform sampler2D bumpMap; + uniform sampler2D map; - 'varying vec2 vUv;', - 'varying vec3 vViewPosition;', - 'varying vec3 vNormal;', + uniform float parallaxScale; + uniform float parallaxMinLayers; + uniform float parallaxMaxLayers; - '#ifdef USE_BASIC_PARALLAX', + varying vec2 vUv; + varying vec3 vViewPosition; + varying vec3 vNormal; - ' vec2 parallaxMap( in vec3 V ) {', + #ifdef USE_BASIC_PARALLAX - ' float initialHeight = texture2D( bumpMap, vUv ).r;', + vec2 parallaxMap( in vec3 V ) { - // No Offset Limitting: messy, floating output at grazing angles. - //"vec2 texCoordOffset = parallaxScale * V.xy / V.z * initialHeight;", + float initialHeight = texture2D( bumpMap, vUv ).r; - // Offset Limiting - ' vec2 texCoordOffset = parallaxScale * V.xy * initialHeight;', - ' return vUv - texCoordOffset;', + // No Offset Limitting: messy, floating output at grazing angles. + //"vec2 texCoordOffset = parallaxScale * V.xy / V.z * initialHeight;", - ' }', + // Offset Limiting + vec2 texCoordOffset = parallaxScale * V.xy * initialHeight; + return vUv - texCoordOffset; - '#else', + } - ' vec2 parallaxMap( in vec3 V ) {', + #else - // Determine number of layers from angle between V and N - ' float numLayers = mix( parallaxMaxLayers, parallaxMinLayers, abs( dot( vec3( 0.0, 0.0, 1.0 ), V ) ) );', + vec2 parallaxMap( in vec3 V ) { - ' float layerHeight = 1.0 / numLayers;', - ' float currentLayerHeight = 0.0;', - // Shift of texture coordinates for each iteration - ' vec2 dtex = parallaxScale * V.xy / V.z / numLayers;', + // Determine number of layers from angle between V and N + float numLayers = mix( parallaxMaxLayers, parallaxMinLayers, abs( dot( vec3( 0.0, 0.0, 1.0 ), V ) ) ); - ' vec2 currentTextureCoords = vUv;', + float layerHeight = 1.0 / numLayers; + float currentLayerHeight = 0.0; + // Shift of texture coordinates for each iteration + vec2 dtex = parallaxScale * V.xy / V.z / numLayers; - ' float heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;', + vec2 currentTextureCoords = vUv; - // while ( heightFromTexture > currentLayerHeight ) - // Infinite loops are not well supported. Do a "large" finite - // loop, but not too large, as it slows down some compilers. - ' for ( int i = 0; i < 30; i += 1 ) {', - ' if ( heightFromTexture <= currentLayerHeight ) {', - ' break;', - ' }', - ' currentLayerHeight += layerHeight;', - // Shift texture coordinates along vector V - ' currentTextureCoords -= dtex;', - ' heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;', - ' }', + float heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r; - ' #ifdef USE_STEEP_PARALLAX', + // while ( heightFromTexture > currentLayerHeight ) + // Infinite loops are not well supported. Do a "large" finite + // loop, but not too large, as it slows down some compilers. + for ( int i = 0; i < 30; i += 1 ) { + if ( heightFromTexture <= currentLayerHeight ) { + break; + } + currentLayerHeight += layerHeight; + // Shift texture coordinates along vector V + currentTextureCoords -= dtex; + heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r; + } - ' return currentTextureCoords;', + #ifdef USE_STEEP_PARALLAX - ' #elif defined( USE_RELIEF_PARALLAX )', + return currentTextureCoords; - ' vec2 deltaTexCoord = dtex / 2.0;', - ' float deltaHeight = layerHeight / 2.0;', + #elif defined( USE_RELIEF_PARALLAX ) - // Return to the mid point of previous layer - ' currentTextureCoords += deltaTexCoord;', - ' currentLayerHeight -= deltaHeight;', + vec2 deltaTexCoord = dtex / 2.0; + float deltaHeight = layerHeight / 2.0; - // Binary search to increase precision of Steep Parallax Mapping - ' const int numSearches = 5;', - ' for ( int i = 0; i < numSearches; i += 1 ) {', + // Return to the mid point of previous layer + currentTextureCoords += deltaTexCoord; + currentLayerHeight -= deltaHeight; - ' deltaTexCoord /= 2.0;', - ' deltaHeight /= 2.0;', - ' heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;', - // Shift along or against vector V - ' if( heightFromTexture > currentLayerHeight ) {', // Below the surface + // Binary search to increase precision of Steep Parallax Mapping + const int numSearches = 5; + for ( int i = 0; i < numSearches; i += 1 ) { - ' currentTextureCoords -= deltaTexCoord;', - ' currentLayerHeight += deltaHeight;', + deltaTexCoord /= 2.0; + deltaHeight /= 2.0; + heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r; + // Shift along or against vector V + if( heightFromTexture > currentLayerHeight ) { // Below the surface - ' } else {', // above the surface + currentTextureCoords -= deltaTexCoord; + currentLayerHeight += deltaHeight; - ' currentTextureCoords += deltaTexCoord;', - ' currentLayerHeight -= deltaHeight;', + } else { // above the surface - ' }', + currentTextureCoords += deltaTexCoord; + currentLayerHeight -= deltaHeight; - ' }', - ' return currentTextureCoords;', + } - ' #elif defined( USE_OCLUSION_PARALLAX )', + } + return currentTextureCoords; - ' vec2 prevTCoords = currentTextureCoords + dtex;', + #elif defined( USE_OCLUSION_PARALLAX ) - // Heights for linear interpolation - ' float nextH = heightFromTexture - currentLayerHeight;', - ' float prevH = texture2D( bumpMap, prevTCoords ).r - currentLayerHeight + layerHeight;', + vec2 prevTCoords = currentTextureCoords + dtex; - // Proportions for linear interpolation - ' float weight = nextH / ( nextH - prevH );', + // Heights for linear interpolation + float nextH = heightFromTexture - currentLayerHeight; + float prevH = texture2D( bumpMap, prevTCoords ).r - currentLayerHeight + layerHeight; - // Interpolation of texture coordinates - ' return prevTCoords * weight + currentTextureCoords * ( 1.0 - weight );', + // Proportions for linear interpolation + float weight = nextH / ( nextH - prevH ); - ' #else', // NO_PARALLAX + // Interpolation of texture coordinates + return prevTCoords * weight + currentTextureCoords * ( 1.0 - weight ); - ' return vUv;', + #else // NO_PARALLAX - ' #endif', + return vUv; - ' }', - '#endif', + #endif - 'vec2 perturbUv( vec3 surfPosition, vec3 surfNormal, vec3 viewPosition ) {', + } + #endif - ' vec2 texDx = dFdx( vUv );', - ' vec2 texDy = dFdy( vUv );', + vec2 perturbUv( vec3 surfPosition, vec3 surfNormal, vec3 viewPosition ) { - ' vec3 vSigmaX = dFdx( surfPosition );', - ' vec3 vSigmaY = dFdy( surfPosition );', - ' vec3 vR1 = cross( vSigmaY, surfNormal );', - ' vec3 vR2 = cross( surfNormal, vSigmaX );', - ' float fDet = dot( vSigmaX, vR1 );', + vec2 texDx = dFdx( vUv ); + vec2 texDy = dFdy( vUv ); - ' vec2 vProjVscr = ( 1.0 / fDet ) * vec2( dot( vR1, viewPosition ), dot( vR2, viewPosition ) );', - ' vec3 vProjVtex;', - ' vProjVtex.xy = texDx * vProjVscr.x + texDy * vProjVscr.y;', - ' vProjVtex.z = dot( surfNormal, viewPosition );', + vec3 vSigmaX = dFdx( surfPosition ); + vec3 vSigmaY = dFdy( surfPosition ); + vec3 vR1 = cross( vSigmaY, surfNormal ); + vec3 vR2 = cross( surfNormal, vSigmaX ); + float fDet = dot( vSigmaX, vR1 ); - ' return parallaxMap( vProjVtex );', - '}', + vec2 vProjVscr = ( 1.0 / fDet ) * vec2( dot( vR1, viewPosition ), dot( vR2, viewPosition ) ); + vec3 vProjVtex; + vProjVtex.xy = texDx * vProjVscr.x + texDy * vProjVscr.y; + vProjVtex.z = dot( surfNormal, viewPosition ); - 'void main() {', + return parallaxMap( vProjVtex ); + } - ' vec2 mapUv = perturbUv( -vViewPosition, normalize( vNormal ), normalize( vViewPosition ) );', - ' gl_FragColor = texture2D( map, mapUv );', + void main() { - '}' + vec2 mapUv = perturbUv( -vViewPosition, normalize( vNormal ), normalize( vViewPosition ) ); + gl_FragColor = texture2D( map, mapUv ); - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/PixelShader.js b/examples/jsm/shaders/PixelShader.js index 37d2421f4f427e..c4ebaa9aca94bd 100644 --- a/examples/jsm/shaders/PixelShader.js +++ b/examples/jsm/shaders/PixelShader.js @@ -2,46 +2,43 @@ * Pixelation shader */ -var PixelShader = { +const PixelShader = { uniforms: { 'tDiffuse': { value: null }, 'resolution': { value: null }, - 'pixelSize': { value: 1. }, + 'pixelSize': { value: 1 }, }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying highp vec2 vUv;', + varying highp vec2 vUv; - 'void main() {', + void main() { - 'vUv = uv;', - 'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float pixelSize; + uniform vec2 resolution; - 'uniform sampler2D tDiffuse;', - 'uniform float pixelSize;', - 'uniform vec2 resolution;', + varying highp vec2 vUv; - 'varying highp vec2 vUv;', + void main(){ - 'void main(){', + vec2 dxy = pixelSize / resolution; + vec2 coord = dxy * floor( vUv / dxy ); + gl_FragColor = texture2D(tDiffuse, coord); - 'vec2 dxy = pixelSize / resolution;', - 'vec2 coord = dxy * floor( vUv / dxy );', - 'gl_FragColor = texture2D(tDiffuse, coord);', + }` - '}' - - ].join( '\n' ) }; export { PixelShader }; diff --git a/examples/jsm/shaders/RGBShiftShader.js b/examples/jsm/shaders/RGBShiftShader.js index bf638911f8755a..7851d0e3701217 100644 --- a/examples/jsm/shaders/RGBShiftShader.js +++ b/examples/jsm/shaders/RGBShiftShader.js @@ -8,7 +8,7 @@ * angle: shift angle in radians */ -var RGBShiftShader = { +const RGBShiftShader = { uniforms: { @@ -18,38 +18,34 @@ var RGBShiftShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float amount; + uniform float angle; - 'uniform sampler2D tDiffuse;', - 'uniform float amount;', - 'uniform float angle;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec2 offset = amount * vec2( cos(angle), sin(angle)); + vec4 cr = texture2D(tDiffuse, vUv + offset); + vec4 cga = texture2D(tDiffuse, vUv); + vec4 cb = texture2D(tDiffuse, vUv - offset); + gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a); - ' vec2 offset = amount * vec2( cos(angle), sin(angle));', - ' vec4 cr = texture2D(tDiffuse, vUv + offset);', - ' vec4 cga = texture2D(tDiffuse, vUv);', - ' vec4 cb = texture2D(tDiffuse, vUv - offset);', - ' gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/SAOShader.js b/examples/jsm/shaders/SAOShader.js index a767d8bb50bb3c..37d7c159ba5622 100644 --- a/examples/jsm/shaders/SAOShader.js +++ b/examples/jsm/shaders/SAOShader.js @@ -7,7 +7,7 @@ import { * TODO */ -var SAOShader = { +const SAOShader = { defines: { 'NUM_SAMPLES': 7, 'NUM_RINGS': 4, @@ -36,153 +36,153 @@ var SAOShader = { 'kernelRadius': { value: 100.0 }, 'randomSeed': { value: 0.0 } }, - vertexShader: [ - 'varying vec2 vUv;', - - 'void main() {', - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - '}' - - ].join( '\n' ), - fragmentShader: [ - '#include ', - - 'varying vec2 vUv;', - - '#if DIFFUSE_TEXTURE == 1', - 'uniform sampler2D tDiffuse;', - '#endif', - - 'uniform sampler2D tDepth;', - - '#if NORMAL_TEXTURE == 1', - 'uniform sampler2D tNormal;', - '#endif', - - 'uniform float cameraNear;', - 'uniform float cameraFar;', - 'uniform mat4 cameraProjectionMatrix;', - 'uniform mat4 cameraInverseProjectionMatrix;', - - 'uniform float scale;', - 'uniform float intensity;', - 'uniform float bias;', - 'uniform float kernelRadius;', - 'uniform float minResolution;', - 'uniform vec2 size;', - 'uniform float randomSeed;', - - '// RGBA depth', - - '#include ', - - 'vec4 getDefaultColor( const in vec2 screenPosition ) {', - ' #if DIFFUSE_TEXTURE == 1', - ' return texture2D( tDiffuse, vUv );', - ' #else', - ' return vec4( 1.0 );', - ' #endif', - '}', - - 'float getDepth( const in vec2 screenPosition ) {', - ' #if DEPTH_PACKING == 1', - ' return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );', - ' #else', - ' return texture2D( tDepth, screenPosition ).x;', - ' #endif', - '}', - - 'float getViewZ( const in float depth ) {', - ' #if PERSPECTIVE_CAMERA == 1', - ' return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );', - ' #else', - ' return orthographicDepthToViewZ( depth, cameraNear, cameraFar );', - ' #endif', - '}', - - 'vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {', - ' float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];', - ' vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );', - ' clipPosition *= clipW; // unprojection.', - - ' return ( cameraInverseProjectionMatrix * clipPosition ).xyz;', - '}', - - 'vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {', - ' #if NORMAL_TEXTURE == 1', - ' return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );', - ' #else', - ' return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );', - ' #endif', - '}', - - 'float scaleDividedByCameraFar;', - 'float minResolutionMultipliedByCameraFar;', - - 'float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {', - ' vec3 viewDelta = sampleViewPosition - centerViewPosition;', - ' float viewDistance = length( viewDelta );', - ' float scaledScreenDistance = scaleDividedByCameraFar * viewDistance;', - - ' return max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - bias) / (1.0 + pow2( scaledScreenDistance ) );', - '}', - - '// moving costly divides into consts', - 'const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );', - 'const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );', - - 'float getAmbientOcclusion( const in vec3 centerViewPosition ) {', - ' // precompute some variables require in getOcclusion.', - ' scaleDividedByCameraFar = scale / cameraFar;', - ' minResolutionMultipliedByCameraFar = minResolution * cameraFar;', - ' vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );', - - ' // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/', - ' float angle = rand( vUv + randomSeed ) * PI2;', - ' vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size;', - ' vec2 radiusStep = radius;', - - ' float occlusionSum = 0.0;', - ' float weightSum = 0.0;', - - ' for( int i = 0; i < NUM_SAMPLES; i ++ ) {', - ' vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius;', - ' radius += radiusStep;', - ' angle += ANGLE_STEP;', - - ' float sampleDepth = getDepth( sampleUv );', - ' if( sampleDepth >= ( 1.0 - EPSILON ) ) {', - ' continue;', - ' }', - - ' float sampleViewZ = getViewZ( sampleDepth );', - ' vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );', - ' occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );', - ' weightSum += 1.0;', - ' }', - - ' if( weightSum == 0.0 ) discard;', - - ' return occlusionSum * ( intensity / weightSum );', - '}', - - - 'void main() {', - ' float centerDepth = getDepth( vUv );', - ' if( centerDepth >= ( 1.0 - EPSILON ) ) {', - ' discard;', - ' }', - - ' float centerViewZ = getViewZ( centerDepth );', - ' vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );', - - ' float ambientOcclusion = getAmbientOcclusion( viewPosition );', - - ' gl_FragColor = getDefaultColor( vUv );', - ' gl_FragColor.xyz *= 1.0 - ambientOcclusion;', - '}' - ].join( '\n' ) + vertexShader: /* glsl */` + + varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + }`, + + fragmentShader: /* glsl */` + + #include + + varying vec2 vUv; + + #if DIFFUSE_TEXTURE == 1 + uniform sampler2D tDiffuse; + #endif + + uniform sampler2D tDepth; + + #if NORMAL_TEXTURE == 1 + uniform sampler2D tNormal; + #endif + + uniform float cameraNear; + uniform float cameraFar; + uniform mat4 cameraProjectionMatrix; + uniform mat4 cameraInverseProjectionMatrix; + + uniform float scale; + uniform float intensity; + uniform float bias; + uniform float kernelRadius; + uniform float minResolution; + uniform vec2 size; + uniform float randomSeed; + + // RGBA depth + + #include + + vec4 getDefaultColor( const in vec2 screenPosition ) { + #if DIFFUSE_TEXTURE == 1 + return texture2D( tDiffuse, vUv ); + #else + return vec4( 1.0 ); + #endif + } + + float getDepth( const in vec2 screenPosition ) { + #if DEPTH_PACKING == 1 + return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) ); + #else + return texture2D( tDepth, screenPosition ).x; + #endif + } + + float getViewZ( const in float depth ) { + #if PERSPECTIVE_CAMERA == 1 + return perspectiveDepthToViewZ( depth, cameraNear, cameraFar ); + #else + return orthographicDepthToViewZ( depth, cameraNear, cameraFar ); + #endif + } + + vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) { + float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3]; + vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 ); + clipPosition *= clipW; // unprojection. + + return ( cameraInverseProjectionMatrix * clipPosition ).xyz; + } + + vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) { + #if NORMAL_TEXTURE == 1 + return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz ); + #else + return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) ); + #endif + } + + float scaleDividedByCameraFar; + float minResolutionMultipliedByCameraFar; + + float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) { + vec3 viewDelta = sampleViewPosition - centerViewPosition; + float viewDistance = length( viewDelta ); + float scaledScreenDistance = scaleDividedByCameraFar * viewDistance; + + return max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - bias) / (1.0 + pow2( scaledScreenDistance ) ); + } + + // moving costly divides into consts + const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES ); + const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES ); + + float getAmbientOcclusion( const in vec3 centerViewPosition ) { + // precompute some variables require in getOcclusion. + scaleDividedByCameraFar = scale / cameraFar; + minResolutionMultipliedByCameraFar = minResolution * cameraFar; + vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv ); + + // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/ + float angle = rand( vUv + randomSeed ) * PI2; + vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size; + vec2 radiusStep = radius; + + float occlusionSum = 0.0; + float weightSum = 0.0; + + for( int i = 0; i < NUM_SAMPLES; i ++ ) { + vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius; + radius += radiusStep; + angle += ANGLE_STEP; + + float sampleDepth = getDepth( sampleUv ); + if( sampleDepth >= ( 1.0 - EPSILON ) ) { + continue; + } + + float sampleViewZ = getViewZ( sampleDepth ); + vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ ); + occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition ); + weightSum += 1.0; + } + + if( weightSum == 0.0 ) discard; + + return occlusionSum * ( intensity / weightSum ); + } + + void main() { + float centerDepth = getDepth( vUv ); + if( centerDepth >= ( 1.0 - EPSILON ) ) { + discard; + } + + float centerViewZ = getViewZ( centerDepth ); + vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ ); + + float ambientOcclusion = getAmbientOcclusion( viewPosition ); + + gl_FragColor = getDefaultColor( vUv ); + gl_FragColor.xyz *= 1.0 - ambientOcclusion; + }` + }; export { SAOShader }; diff --git a/examples/jsm/shaders/SMAAShader.js b/examples/jsm/shaders/SMAAShader.js index c09eb110499c54..765ba3bc9935ec 100644 --- a/examples/jsm/shaders/SMAAShader.js +++ b/examples/jsm/shaders/SMAAShader.js @@ -8,7 +8,7 @@ import { * https://github.com/iryoku/smaa/releases/tag/v2.8 */ -var SMAAEdgesShader = { +const SMAAEdgesShader = { defines: { @@ -23,101 +23,97 @@ var SMAAEdgesShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'uniform vec2 resolution;', + uniform vec2 resolution; - 'varying vec2 vUv;', - 'varying vec4 vOffset[ 3 ];', + varying vec2 vUv; + varying vec4 vOffset[ 3 ]; - 'void SMAAEdgeDetectionVS( vec2 texcoord ) {', - ' vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 );', // WebGL port note: Changed sign in W component - ' vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 );', // WebGL port note: Changed sign in W component - ' vOffset[ 2 ] = texcoord.xyxy + resolution.xyxy * vec4( -2.0, 0.0, 0.0, 2.0 );', // WebGL port note: Changed sign in W component - '}', + void SMAAEdgeDetectionVS( vec2 texcoord ) { + vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 ); // WebGL port note: Changed sign in W component + vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 ); // WebGL port note: Changed sign in W component + vOffset[ 2 ] = texcoord.xyxy + resolution.xyxy * vec4( -2.0, 0.0, 0.0, 2.0 ); // WebGL port note: Changed sign in W component + } - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' SMAAEdgeDetectionVS( vUv );', + SMAAEdgeDetectionVS( vUv ); - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; + varying vec4 vOffset[ 3 ]; - 'varying vec2 vUv;', - 'varying vec4 vOffset[ 3 ];', + vec4 SMAAColorEdgeDetectionPS( vec2 texcoord, vec4 offset[3], sampler2D colorTex ) { + vec2 threshold = vec2( SMAA_THRESHOLD, SMAA_THRESHOLD ); - 'vec4 SMAAColorEdgeDetectionPS( vec2 texcoord, vec4 offset[3], sampler2D colorTex ) {', - ' vec2 threshold = vec2( SMAA_THRESHOLD, SMAA_THRESHOLD );', + // Calculate color deltas: + vec4 delta; + vec3 C = texture2D( colorTex, texcoord ).rgb; - // Calculate color deltas: - ' vec4 delta;', - ' vec3 C = texture2D( colorTex, texcoord ).rgb;', + vec3 Cleft = texture2D( colorTex, offset[0].xy ).rgb; + vec3 t = abs( C - Cleft ); + delta.x = max( max( t.r, t.g ), t.b ); - ' vec3 Cleft = texture2D( colorTex, offset[0].xy ).rgb;', - ' vec3 t = abs( C - Cleft );', - ' delta.x = max( max( t.r, t.g ), t.b );', + vec3 Ctop = texture2D( colorTex, offset[0].zw ).rgb; + t = abs( C - Ctop ); + delta.y = max( max( t.r, t.g ), t.b ); - ' vec3 Ctop = texture2D( colorTex, offset[0].zw ).rgb;', - ' t = abs( C - Ctop );', - ' delta.y = max( max( t.r, t.g ), t.b );', + // We do the usual threshold: + vec2 edges = step( threshold, delta.xy ); - // We do the usual threshold: - ' vec2 edges = step( threshold, delta.xy );', + // Then discard if there is no edge: + if ( dot( edges, vec2( 1.0, 1.0 ) ) == 0.0 ) + discard; - // Then discard if there is no edge: - ' if ( dot( edges, vec2( 1.0, 1.0 ) ) == 0.0 )', - ' discard;', + // Calculate right and bottom deltas: + vec3 Cright = texture2D( colorTex, offset[1].xy ).rgb; + t = abs( C - Cright ); + delta.z = max( max( t.r, t.g ), t.b ); - // Calculate right and bottom deltas: - ' vec3 Cright = texture2D( colorTex, offset[1].xy ).rgb;', - ' t = abs( C - Cright );', - ' delta.z = max( max( t.r, t.g ), t.b );', + vec3 Cbottom = texture2D( colorTex, offset[1].zw ).rgb; + t = abs( C - Cbottom ); + delta.w = max( max( t.r, t.g ), t.b ); - ' vec3 Cbottom = texture2D( colorTex, offset[1].zw ).rgb;', - ' t = abs( C - Cbottom );', - ' delta.w = max( max( t.r, t.g ), t.b );', + // Calculate the maximum delta in the direct neighborhood: + float maxDelta = max( max( max( delta.x, delta.y ), delta.z ), delta.w ); - // Calculate the maximum delta in the direct neighborhood: - ' float maxDelta = max( max( max( delta.x, delta.y ), delta.z ), delta.w );', + // Calculate left-left and top-top deltas: + vec3 Cleftleft = texture2D( colorTex, offset[2].xy ).rgb; + t = abs( C - Cleftleft ); + delta.z = max( max( t.r, t.g ), t.b ); - // Calculate left-left and top-top deltas: - ' vec3 Cleftleft = texture2D( colorTex, offset[2].xy ).rgb;', - ' t = abs( C - Cleftleft );', - ' delta.z = max( max( t.r, t.g ), t.b );', + vec3 Ctoptop = texture2D( colorTex, offset[2].zw ).rgb; + t = abs( C - Ctoptop ); + delta.w = max( max( t.r, t.g ), t.b ); - ' vec3 Ctoptop = texture2D( colorTex, offset[2].zw ).rgb;', - ' t = abs( C - Ctoptop );', - ' delta.w = max( max( t.r, t.g ), t.b );', + // Calculate the final maximum delta: + maxDelta = max( max( maxDelta, delta.z ), delta.w ); - // Calculate the final maximum delta: - ' maxDelta = max( max( maxDelta, delta.z ), delta.w );', + // Local contrast adaptation in action: + edges.xy *= step( 0.5 * maxDelta, delta.xy ); - // Local contrast adaptation in action: - ' edges.xy *= step( 0.5 * maxDelta, delta.xy );', + return vec4( edges, 0.0, 0.0 ); + } - ' return vec4( edges, 0.0, 0.0 );', - '}', + void main() { - 'void main() {', + gl_FragColor = SMAAColorEdgeDetectionPS( vUv, vOffset, tDiffuse ); - ' gl_FragColor = SMAAColorEdgeDetectionPS( vUv, vOffset, tDiffuse );', - - '}' - - ].join( '\n' ) + }` }; -var SMAAWeightsShader = { +const SMAAWeightsShader = { defines: { @@ -137,245 +133,241 @@ var SMAAWeightsShader = { }, - vertexShader: [ - - 'uniform vec2 resolution;', + vertexShader: /* glsl */` - 'varying vec2 vUv;', - 'varying vec4 vOffset[ 3 ];', - 'varying vec2 vPixcoord;', + uniform vec2 resolution; - 'void SMAABlendingWeightCalculationVS( vec2 texcoord ) {', - ' vPixcoord = texcoord / resolution;', + varying vec2 vUv; + varying vec4 vOffset[ 3 ]; + varying vec2 vPixcoord; - // We will use these offsets for the searches later on (see @PSEUDO_GATHER4): - ' vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.25, 0.125, 1.25, 0.125 );', // WebGL port note: Changed sign in Y and W components - ' vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.125, 0.25, -0.125, -1.25 );', // WebGL port note: Changed sign in Y and W components + void SMAABlendingWeightCalculationVS( vec2 texcoord ) { + vPixcoord = texcoord / resolution; - // And these for the searches, they indicate the ends of the loops: - ' vOffset[ 2 ] = vec4( vOffset[ 0 ].xz, vOffset[ 1 ].yw ) + vec4( -2.0, 2.0, -2.0, 2.0 ) * resolution.xxyy * float( SMAA_MAX_SEARCH_STEPS );', + // We will use these offsets for the searches later on (see @PSEUDO_GATHER4): + vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.25, 0.125, 1.25, 0.125 ); // WebGL port note: Changed sign in Y and W components + vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.125, 0.25, -0.125, -1.25 ); // WebGL port note: Changed sign in Y and W components - '}', + // And these for the searches, they indicate the ends of the loops: + vOffset[ 2 ] = vec4( vOffset[ 0 ].xz, vOffset[ 1 ].yw ) + vec4( -2.0, 2.0, -2.0, 2.0 ) * resolution.xxyy * float( SMAA_MAX_SEARCH_STEPS ); - 'void main() {', + } - ' vUv = uv;', + void main() { - ' SMAABlendingWeightCalculationVS( vUv );', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + SMAABlendingWeightCalculationVS( vUv ); - '}' + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - ].join( '\n' ), + }`, - fragmentShader: [ + fragmentShader: /* glsl */` - '#define SMAASampleLevelZeroOffset( tex, coord, offset ) texture2D( tex, coord + float( offset ) * resolution, 0.0 )', + #define SMAASampleLevelZeroOffset( tex, coord, offset ) texture2D( tex, coord + float( offset ) * resolution, 0.0 ) - 'uniform sampler2D tDiffuse;', - 'uniform sampler2D tArea;', - 'uniform sampler2D tSearch;', - 'uniform vec2 resolution;', + uniform sampler2D tDiffuse; + uniform sampler2D tArea; + uniform sampler2D tSearch; + uniform vec2 resolution; - 'varying vec2 vUv;', - 'varying vec4 vOffset[3];', - 'varying vec2 vPixcoord;', + varying vec2 vUv; + varying vec4 vOffset[3]; + varying vec2 vPixcoord; - '#if __VERSION__ == 100', - 'vec2 round( vec2 x ) {', - ' return sign( x ) * floor( abs( x ) + 0.5 );', - '}', - '#endif', + #if __VERSION__ == 100 + vec2 round( vec2 x ) { + return sign( x ) * floor( abs( x ) + 0.5 ); + } + #endif - 'float SMAASearchLength( sampler2D searchTex, vec2 e, float bias, float scale ) {', - // Not required if searchTex accesses are set to point: - // float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0); - // e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE + - // e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE; - ' e.r = bias + e.r * scale;', - ' return 255.0 * texture2D( searchTex, e, 0.0 ).r;', - '}', + float SMAASearchLength( sampler2D searchTex, vec2 e, float bias, float scale ) { + // Not required if searchTex accesses are set to point: + // float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0); + // e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE + + // e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE; + e.r = bias + e.r * scale; + return 255.0 * texture2D( searchTex, e, 0.0 ).r; + } - 'float SMAASearchXLeft( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {', - /** - * @PSEUDO_GATHER4 - * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to - * sample between edge, thus fetching four edges in a row. - * Sampling with different offsets in each direction allows to disambiguate - * which edges are active from the four fetched ones. - */ - ' vec2 e = vec2( 0.0, 1.0 );', + float SMAASearchXLeft( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) { + /** + * @PSEUDO_GATHER4 + * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to + * sample between edge, thus fetching four edges in a row. + * Sampling with different offsets in each direction allows to disambiguate + * which edges are active from the four fetched ones. + */ + vec2 e = vec2( 0.0, 1.0 ); - ' for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {', // WebGL port note: Changed while to for - ' e = texture2D( edgesTex, texcoord, 0.0 ).rg;', - ' texcoord -= vec2( 2.0, 0.0 ) * resolution;', - ' if ( ! ( texcoord.x > end && e.g > 0.8281 && e.r == 0.0 ) ) break;', - ' }', + for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for + e = texture2D( edgesTex, texcoord, 0.0 ).rg; + texcoord -= vec2( 2.0, 0.0 ) * resolution; + if ( ! ( texcoord.x > end && e.g > 0.8281 && e.r == 0.0 ) ) break; + } - // We correct the previous (-0.25, -0.125) offset we applied: - ' texcoord.x += 0.25 * resolution.x;', + // We correct the previous (-0.25, -0.125) offset we applied: + texcoord.x += 0.25 * resolution.x; - // The searches are bias by 1, so adjust the coords accordingly: - ' texcoord.x += resolution.x;', + // The searches are bias by 1, so adjust the coords accordingly: + texcoord.x += resolution.x; - // Disambiguate the length added by the last step: - ' texcoord.x += 2.0 * resolution.x;', // Undo last step - ' texcoord.x -= resolution.x * SMAASearchLength(searchTex, e, 0.0, 0.5);', + // Disambiguate the length added by the last step: + texcoord.x += 2.0 * resolution.x; // Undo last step + texcoord.x -= resolution.x * SMAASearchLength(searchTex, e, 0.0, 0.5); - ' return texcoord.x;', - '}', + return texcoord.x; + } - 'float SMAASearchXRight( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {', - ' vec2 e = vec2( 0.0, 1.0 );', + float SMAASearchXRight( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) { + vec2 e = vec2( 0.0, 1.0 ); - ' for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {', // WebGL port note: Changed while to for - ' e = texture2D( edgesTex, texcoord, 0.0 ).rg;', - ' texcoord += vec2( 2.0, 0.0 ) * resolution;', - ' if ( ! ( texcoord.x < end && e.g > 0.8281 && e.r == 0.0 ) ) break;', - ' }', + for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for + e = texture2D( edgesTex, texcoord, 0.0 ).rg; + texcoord += vec2( 2.0, 0.0 ) * resolution; + if ( ! ( texcoord.x < end && e.g > 0.8281 && e.r == 0.0 ) ) break; + } - ' texcoord.x -= 0.25 * resolution.x;', - ' texcoord.x -= resolution.x;', - ' texcoord.x -= 2.0 * resolution.x;', - ' texcoord.x += resolution.x * SMAASearchLength( searchTex, e, 0.5, 0.5 );', + texcoord.x -= 0.25 * resolution.x; + texcoord.x -= resolution.x; + texcoord.x -= 2.0 * resolution.x; + texcoord.x += resolution.x * SMAASearchLength( searchTex, e, 0.5, 0.5 ); - ' return texcoord.x;', - '}', + return texcoord.x; + } - 'float SMAASearchYUp( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {', - ' vec2 e = vec2( 1.0, 0.0 );', + float SMAASearchYUp( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) { + vec2 e = vec2( 1.0, 0.0 ); - ' for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {', // WebGL port note: Changed while to for - ' e = texture2D( edgesTex, texcoord, 0.0 ).rg;', - ' texcoord += vec2( 0.0, 2.0 ) * resolution;', // WebGL port note: Changed sign - ' if ( ! ( texcoord.y > end && e.r > 0.8281 && e.g == 0.0 ) ) break;', - ' }', + for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for + e = texture2D( edgesTex, texcoord, 0.0 ).rg; + texcoord += vec2( 0.0, 2.0 ) * resolution; // WebGL port note: Changed sign + if ( ! ( texcoord.y > end && e.r > 0.8281 && e.g == 0.0 ) ) break; + } - ' texcoord.y -= 0.25 * resolution.y;', // WebGL port note: Changed sign - ' texcoord.y -= resolution.y;', // WebGL port note: Changed sign - ' texcoord.y -= 2.0 * resolution.y;', // WebGL port note: Changed sign - ' texcoord.y += resolution.y * SMAASearchLength( searchTex, e.gr, 0.0, 0.5 );', // WebGL port note: Changed sign + texcoord.y -= 0.25 * resolution.y; // WebGL port note: Changed sign + texcoord.y -= resolution.y; // WebGL port note: Changed sign + texcoord.y -= 2.0 * resolution.y; // WebGL port note: Changed sign + texcoord.y += resolution.y * SMAASearchLength( searchTex, e.gr, 0.0, 0.5 ); // WebGL port note: Changed sign - ' return texcoord.y;', - '}', + return texcoord.y; + } - 'float SMAASearchYDown( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {', - ' vec2 e = vec2( 1.0, 0.0 );', + float SMAASearchYDown( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) { + vec2 e = vec2( 1.0, 0.0 ); - ' for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {', // WebGL port note: Changed while to for - ' e = texture2D( edgesTex, texcoord, 0.0 ).rg;', - ' texcoord -= vec2( 0.0, 2.0 ) * resolution;', // WebGL port note: Changed sign - ' if ( ! ( texcoord.y < end && e.r > 0.8281 && e.g == 0.0 ) ) break;', - ' }', + for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) { // WebGL port note: Changed while to for + e = texture2D( edgesTex, texcoord, 0.0 ).rg; + texcoord -= vec2( 0.0, 2.0 ) * resolution; // WebGL port note: Changed sign + if ( ! ( texcoord.y < end && e.r > 0.8281 && e.g == 0.0 ) ) break; + } - ' texcoord.y += 0.25 * resolution.y;', // WebGL port note: Changed sign - ' texcoord.y += resolution.y;', // WebGL port note: Changed sign - ' texcoord.y += 2.0 * resolution.y;', // WebGL port note: Changed sign - ' texcoord.y -= resolution.y * SMAASearchLength( searchTex, e.gr, 0.5, 0.5 );', // WebGL port note: Changed sign + texcoord.y += 0.25 * resolution.y; // WebGL port note: Changed sign + texcoord.y += resolution.y; // WebGL port note: Changed sign + texcoord.y += 2.0 * resolution.y; // WebGL port note: Changed sign + texcoord.y -= resolution.y * SMAASearchLength( searchTex, e.gr, 0.5, 0.5 ); // WebGL port note: Changed sign - ' return texcoord.y;', - '}', + return texcoord.y; + } - 'vec2 SMAAArea( sampler2D areaTex, vec2 dist, float e1, float e2, float offset ) {', - // Rounding prevents precision errors of bilinear filtering: - ' vec2 texcoord = float( SMAA_AREATEX_MAX_DISTANCE ) * round( 4.0 * vec2( e1, e2 ) ) + dist;', + vec2 SMAAArea( sampler2D areaTex, vec2 dist, float e1, float e2, float offset ) { + // Rounding prevents precision errors of bilinear filtering: + vec2 texcoord = float( SMAA_AREATEX_MAX_DISTANCE ) * round( 4.0 * vec2( e1, e2 ) ) + dist; - // We do a scale and bias for mapping to texel space: - ' texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + ( 0.5 * SMAA_AREATEX_PIXEL_SIZE );', + // We do a scale and bias for mapping to texel space: + texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + ( 0.5 * SMAA_AREATEX_PIXEL_SIZE ); - // Move to proper place, according to the subpixel offset: - ' texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;', + // Move to proper place, according to the subpixel offset: + texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset; - ' return texture2D( areaTex, texcoord, 0.0 ).rg;', - '}', + return texture2D( areaTex, texcoord, 0.0 ).rg; + } - 'vec4 SMAABlendingWeightCalculationPS( vec2 texcoord, vec2 pixcoord, vec4 offset[ 3 ], sampler2D edgesTex, sampler2D areaTex, sampler2D searchTex, ivec4 subsampleIndices ) {', - ' vec4 weights = vec4( 0.0, 0.0, 0.0, 0.0 );', + vec4 SMAABlendingWeightCalculationPS( vec2 texcoord, vec2 pixcoord, vec4 offset[ 3 ], sampler2D edgesTex, sampler2D areaTex, sampler2D searchTex, ivec4 subsampleIndices ) { + vec4 weights = vec4( 0.0, 0.0, 0.0, 0.0 ); - ' vec2 e = texture2D( edgesTex, texcoord ).rg;', + vec2 e = texture2D( edgesTex, texcoord ).rg; - ' if ( e.g > 0.0 ) {', // Edge at north - ' vec2 d;', + if ( e.g > 0.0 ) { // Edge at north + vec2 d; - // Find the distance to the left: - ' vec2 coords;', - ' coords.x = SMAASearchXLeft( edgesTex, searchTex, offset[ 0 ].xy, offset[ 2 ].x );', - ' coords.y = offset[ 1 ].y;', // offset[1].y = texcoord.y - 0.25 * resolution.y (@CROSSING_OFFSET) - ' d.x = coords.x;', + // Find the distance to the left: + vec2 coords; + coords.x = SMAASearchXLeft( edgesTex, searchTex, offset[ 0 ].xy, offset[ 2 ].x ); + coords.y = offset[ 1 ].y; // offset[1].y = texcoord.y - 0.25 * resolution.y (@CROSSING_OFFSET) + d.x = coords.x; - // Now fetch the left crossing edges, two at a time using bilinear - // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to - // discern what value each edge has: - ' float e1 = texture2D( edgesTex, coords, 0.0 ).r;', + // Now fetch the left crossing edges, two at a time using bilinear + // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to + // discern what value each edge has: + float e1 = texture2D( edgesTex, coords, 0.0 ).r; - // Find the distance to the right: - ' coords.x = SMAASearchXRight( edgesTex, searchTex, offset[ 0 ].zw, offset[ 2 ].y );', - ' d.y = coords.x;', + // Find the distance to the right: + coords.x = SMAASearchXRight( edgesTex, searchTex, offset[ 0 ].zw, offset[ 2 ].y ); + d.y = coords.x; - // We want the distances to be in pixel units (doing this here allow to - // better interleave arithmetic and memory accesses): - ' d = d / resolution.x - pixcoord.x;', + // We want the distances to be in pixel units (doing this here allow to + // better interleave arithmetic and memory accesses): + d = d / resolution.x - pixcoord.x; - // SMAAArea below needs a sqrt, as the areas texture is compressed - // quadratically: - ' vec2 sqrt_d = sqrt( abs( d ) );', + // SMAAArea below needs a sqrt, as the areas texture is compressed + // quadratically: + vec2 sqrt_d = sqrt( abs( d ) ); - // Fetch the right crossing edges: - ' coords.y -= 1.0 * resolution.y;', // WebGL port note: Added - ' float e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 1, 0 ) ).r;', + // Fetch the right crossing edges: + coords.y -= 1.0 * resolution.y; // WebGL port note: Added + float e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 1, 0 ) ).r; - // Ok, we know how this pattern looks like, now it is time for getting - // the actual area: - ' weights.rg = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.y ) );', - ' }', + // Ok, we know how this pattern looks like, now it is time for getting + // the actual area: + weights.rg = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.y ) ); + } - ' if ( e.r > 0.0 ) {', // Edge at west - ' vec2 d;', + if ( e.r > 0.0 ) { // Edge at west + vec2 d; - // Find the distance to the top: - ' vec2 coords;', + // Find the distance to the top: + vec2 coords; - ' coords.y = SMAASearchYUp( edgesTex, searchTex, offset[ 1 ].xy, offset[ 2 ].z );', - ' coords.x = offset[ 0 ].x;', // offset[1].x = texcoord.x - 0.25 * resolution.x; - ' d.x = coords.y;', + coords.y = SMAASearchYUp( edgesTex, searchTex, offset[ 1 ].xy, offset[ 2 ].z ); + coords.x = offset[ 0 ].x; // offset[1].x = texcoord.x - 0.25 * resolution.x; + d.x = coords.y; - // Fetch the top crossing edges: - ' float e1 = texture2D( edgesTex, coords, 0.0 ).g;', + // Fetch the top crossing edges: + float e1 = texture2D( edgesTex, coords, 0.0 ).g; - // Find the distance to the bottom: - ' coords.y = SMAASearchYDown( edgesTex, searchTex, offset[ 1 ].zw, offset[ 2 ].w );', - ' d.y = coords.y;', + // Find the distance to the bottom: + coords.y = SMAASearchYDown( edgesTex, searchTex, offset[ 1 ].zw, offset[ 2 ].w ); + d.y = coords.y; - // We want the distances to be in pixel units: - ' d = d / resolution.y - pixcoord.y;', + // We want the distances to be in pixel units: + d = d / resolution.y - pixcoord.y; - // SMAAArea below needs a sqrt, as the areas texture is compressed - // quadratically: - ' vec2 sqrt_d = sqrt( abs( d ) );', + // SMAAArea below needs a sqrt, as the areas texture is compressed + // quadratically: + vec2 sqrt_d = sqrt( abs( d ) ); - // Fetch the bottom crossing edges: - ' coords.y -= 1.0 * resolution.y;', // WebGL port note: Added - ' float e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 0, 1 ) ).g;', + // Fetch the bottom crossing edges: + coords.y -= 1.0 * resolution.y; // WebGL port note: Added + float e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 0, 1 ) ).g; - // Get the area for this direction: - ' weights.ba = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.x ) );', - ' }', + // Get the area for this direction: + weights.ba = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.x ) ); + } - ' return weights;', - '}', + return weights; + } - 'void main() {', + void main() { - ' gl_FragColor = SMAABlendingWeightCalculationPS( vUv, vPixcoord, vOffset, tDiffuse, tArea, tSearch, ivec4( 0.0 ) );', + gl_FragColor = SMAABlendingWeightCalculationPS( vUv, vPixcoord, vOffset, tDiffuse, tArea, tSearch, ivec4( 0.0 ) ); - '}' - - ].join( '\n' ) + }` }; -var SMAABlendShader = { +const SMAABlendShader = { uniforms: { @@ -385,87 +377,83 @@ var SMAABlendShader = { }, - vertexShader: [ - - 'uniform vec2 resolution;', - - 'varying vec2 vUv;', - 'varying vec4 vOffset[ 2 ];', + vertexShader: /* glsl */` - 'void SMAANeighborhoodBlendingVS( vec2 texcoord ) {', - ' vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 );', // WebGL port note: Changed sign in W component - ' vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 );', // WebGL port note: Changed sign in W component - '}', + uniform vec2 resolution; - 'void main() {', + varying vec2 vUv; + varying vec4 vOffset[ 2 ]; - ' vUv = uv;', + void SMAANeighborhoodBlendingVS( vec2 texcoord ) { + vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 ); // WebGL port note: Changed sign in W component + vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 ); // WebGL port note: Changed sign in W component + } - ' SMAANeighborhoodBlendingVS( vUv );', + void main() { - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; - '}' + SMAANeighborhoodBlendingVS( vUv ); - ].join( '\n' ), + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - fragmentShader: [ + }`, - 'uniform sampler2D tDiffuse;', - 'uniform sampler2D tColor;', - 'uniform vec2 resolution;', + fragmentShader: /* glsl */` - 'varying vec2 vUv;', - 'varying vec4 vOffset[ 2 ];', + uniform sampler2D tDiffuse; + uniform sampler2D tColor; + uniform vec2 resolution; - 'vec4 SMAANeighborhoodBlendingPS( vec2 texcoord, vec4 offset[ 2 ], sampler2D colorTex, sampler2D blendTex ) {', - // Fetch the blending weights for current pixel: - ' vec4 a;', - ' a.xz = texture2D( blendTex, texcoord ).xz;', - ' a.y = texture2D( blendTex, offset[ 1 ].zw ).g;', - ' a.w = texture2D( blendTex, offset[ 1 ].xy ).a;', + varying vec2 vUv; + varying vec4 vOffset[ 2 ]; - // Is there any blending weight with a value greater than 0.0? - ' if ( dot(a, vec4( 1.0, 1.0, 1.0, 1.0 )) < 1e-5 ) {', - ' return texture2D( colorTex, texcoord, 0.0 );', - ' } else {', - // Up to 4 lines can be crossing a pixel (one through each edge). We - // favor blending by choosing the line with the maximum weight for each - // direction: - ' vec2 offset;', - ' offset.x = a.a > a.b ? a.a : -a.b;', // left vs. right - ' offset.y = a.g > a.r ? -a.g : a.r;', // top vs. bottom // WebGL port note: Changed signs + vec4 SMAANeighborhoodBlendingPS( vec2 texcoord, vec4 offset[ 2 ], sampler2D colorTex, sampler2D blendTex ) { + // Fetch the blending weights for current pixel: + vec4 a; + a.xz = texture2D( blendTex, texcoord ).xz; + a.y = texture2D( blendTex, offset[ 1 ].zw ).g; + a.w = texture2D( blendTex, offset[ 1 ].xy ).a; - // Then we go in the direction that has the maximum weight: - ' if ( abs( offset.x ) > abs( offset.y )) {', // horizontal vs. vertical - ' offset.y = 0.0;', - ' } else {', - ' offset.x = 0.0;', - ' }', + // Is there any blending weight with a value greater than 0.0? + if ( dot(a, vec4( 1.0, 1.0, 1.0, 1.0 )) < 1e-5 ) { + return texture2D( colorTex, texcoord, 0.0 ); + } else { + // Up to 4 lines can be crossing a pixel (one through each edge). We + // favor blending by choosing the line with the maximum weight for each + // direction: + vec2 offset; + offset.x = a.a > a.b ? a.a : -a.b; // left vs. right + offset.y = a.g > a.r ? -a.g : a.r; // top vs. bottom // WebGL port note: Changed signs - // Fetch the opposite color and lerp by hand: - ' vec4 C = texture2D( colorTex, texcoord, 0.0 );', - ' texcoord += sign( offset ) * resolution;', - ' vec4 Cop = texture2D( colorTex, texcoord, 0.0 );', - ' float s = abs( offset.x ) > abs( offset.y ) ? abs( offset.x ) : abs( offset.y );', + // Then we go in the direction that has the maximum weight: + if ( abs( offset.x ) > abs( offset.y )) { // horizontal vs. vertical + offset.y = 0.0; + } else { + offset.x = 0.0; + } - // WebGL port note: Added gamma correction - ' C.xyz = pow(C.xyz, vec3(2.2));', - ' Cop.xyz = pow(Cop.xyz, vec3(2.2));', - ' vec4 mixed = mix(C, Cop, s);', - ' mixed.xyz = pow(mixed.xyz, vec3(1.0 / 2.2));', + // Fetch the opposite color and lerp by hand: + vec4 C = texture2D( colorTex, texcoord, 0.0 ); + texcoord += sign( offset ) * resolution; + vec4 Cop = texture2D( colorTex, texcoord, 0.0 ); + float s = abs( offset.x ) > abs( offset.y ) ? abs( offset.x ) : abs( offset.y ); - ' return mixed;', - ' }', - '}', + // WebGL port note: Added gamma correction + C.xyz = pow(C.xyz, vec3(2.2)); + Cop.xyz = pow(Cop.xyz, vec3(2.2)); + vec4 mixed = mix(C, Cop, s); + mixed.xyz = pow(mixed.xyz, vec3(1.0 / 2.2)); - 'void main() {', + return mixed; + } + } - ' gl_FragColor = SMAANeighborhoodBlendingPS( vUv, vOffset, tColor, tDiffuse );', + void main() { - '}' + gl_FragColor = SMAANeighborhoodBlendingPS( vUv, vOffset, tColor, tDiffuse ); - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/SSAOShader.js b/examples/jsm/shaders/SSAOShader.js index ecfe32de615871..116676e60e6ab6 100644 --- a/examples/jsm/shaders/SSAOShader.js +++ b/examples/jsm/shaders/SSAOShader.js @@ -10,7 +10,7 @@ import { * https://github.com/McNopper/OpenGL/blob/master/Example28/shader/ssao.frag.glsl */ -var SSAOShader = { +const SSAOShader = { defines: { 'PERSPECTIVE_CAMERA': 1, @@ -35,150 +35,146 @@ var SSAOShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform sampler2D tNormal; + uniform sampler2D tDepth; + uniform sampler2D tNoise; - 'uniform sampler2D tDiffuse;', - 'uniform sampler2D tNormal;', - 'uniform sampler2D tDepth;', - 'uniform sampler2D tNoise;', + uniform vec3 kernel[ KERNEL_SIZE ]; - 'uniform vec3 kernel[ KERNEL_SIZE ];', + uniform vec2 resolution; - 'uniform vec2 resolution;', + uniform float cameraNear; + uniform float cameraFar; + uniform mat4 cameraProjectionMatrix; + uniform mat4 cameraInverseProjectionMatrix; - 'uniform float cameraNear;', - 'uniform float cameraFar;', - 'uniform mat4 cameraProjectionMatrix;', - 'uniform mat4 cameraInverseProjectionMatrix;', + uniform float kernelRadius; + uniform float minDistance; // avoid artifacts caused by neighbour fragments with minimal depth difference + uniform float maxDistance; // avoid the influence of fragments which are too far away - 'uniform float kernelRadius;', - 'uniform float minDistance;', // avoid artifacts caused by neighbour fragments with minimal depth difference - 'uniform float maxDistance;', // avoid the influence of fragments which are too far away + varying vec2 vUv; - 'varying vec2 vUv;', + #include - '#include ', + float getDepth( const in vec2 screenPosition ) { - 'float getDepth( const in vec2 screenPosition ) {', + return texture2D( tDepth, screenPosition ).x; - ' return texture2D( tDepth, screenPosition ).x;', + } - '}', + float getLinearDepth( const in vec2 screenPosition ) { - 'float getLinearDepth( const in vec2 screenPosition ) {', + #if PERSPECTIVE_CAMERA == 1 - ' #if PERSPECTIVE_CAMERA == 1', + float fragCoordZ = texture2D( tDepth, screenPosition ).x; + float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar ); + return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); - ' float fragCoordZ = texture2D( tDepth, screenPosition ).x;', - ' float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );', - ' return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );', + #else - ' #else', + return texture2D( tDepth, screenPosition ).x; - ' return texture2D( tDepth, screenPosition ).x;', + #endif - ' #endif', + } - '}', + float getViewZ( const in float depth ) { - 'float getViewZ( const in float depth ) {', + #if PERSPECTIVE_CAMERA == 1 - ' #if PERSPECTIVE_CAMERA == 1', + return perspectiveDepthToViewZ( depth, cameraNear, cameraFar ); - ' return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );', + #else - ' #else', + return orthographicDepthToViewZ( depth, cameraNear, cameraFar ); - ' return orthographicDepthToViewZ( depth, cameraNear, cameraFar );', + #endif - ' #endif', + } - '}', + vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) { - 'vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {', + float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3]; - ' float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];', + vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 ); - ' vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );', + clipPosition *= clipW; // unprojection. - ' clipPosition *= clipW; // unprojection.', + return ( cameraInverseProjectionMatrix * clipPosition ).xyz; - ' return ( cameraInverseProjectionMatrix * clipPosition ).xyz;', + } - '}', + vec3 getViewNormal( const in vec2 screenPosition ) { - 'vec3 getViewNormal( const in vec2 screenPosition ) {', + return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz ); - ' return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );', + } - '}', + void main() { - 'void main() {', + float depth = getDepth( vUv ); + float viewZ = getViewZ( depth ); - ' float depth = getDepth( vUv );', - ' float viewZ = getViewZ( depth );', + vec3 viewPosition = getViewPosition( vUv, depth, viewZ ); + vec3 viewNormal = getViewNormal( vUv ); - ' vec3 viewPosition = getViewPosition( vUv, depth, viewZ );', - ' vec3 viewNormal = getViewNormal( vUv );', + vec2 noiseScale = vec2( resolution.x / 4.0, resolution.y / 4.0 ); + vec3 random = texture2D( tNoise, vUv * noiseScale ).xyz; - ' vec2 noiseScale = vec2( resolution.x / 4.0, resolution.y / 4.0 );', - ' vec3 random = texture2D( tNoise, vUv * noiseScale ).xyz;', + // compute matrix used to reorient a kernel vector - // compute matrix used to reorient a kernel vector + vec3 tangent = normalize( random - viewNormal * dot( random, viewNormal ) ); + vec3 bitangent = cross( viewNormal, tangent ); + mat3 kernelMatrix = mat3( tangent, bitangent, viewNormal ); - ' vec3 tangent = normalize( random - viewNormal * dot( random, viewNormal ) );', - ' vec3 bitangent = cross( viewNormal, tangent );', - ' mat3 kernelMatrix = mat3( tangent, bitangent, viewNormal );', + float occlusion = 0.0; - ' float occlusion = 0.0;', + for ( int i = 0; i < KERNEL_SIZE; i ++ ) { - ' for ( int i = 0; i < KERNEL_SIZE; i ++ ) {', + vec3 sampleVector = kernelMatrix * kernel[ i ]; // reorient sample vector in view space + vec3 samplePoint = viewPosition + ( sampleVector * kernelRadius ); // calculate sample point - ' vec3 sampleVector = kernelMatrix * kernel[ i ];', // reorient sample vector in view space - ' vec3 samplePoint = viewPosition + ( sampleVector * kernelRadius );', // calculate sample point + vec4 samplePointNDC = cameraProjectionMatrix * vec4( samplePoint, 1.0 ); // project point and calculate NDC + samplePointNDC /= samplePointNDC.w; - ' vec4 samplePointNDC = cameraProjectionMatrix * vec4( samplePoint, 1.0 );', // project point and calculate NDC - ' samplePointNDC /= samplePointNDC.w;', + vec2 samplePointUv = samplePointNDC.xy * 0.5 + 0.5; // compute uv coordinates - ' vec2 samplePointUv = samplePointNDC.xy * 0.5 + 0.5;', // compute uv coordinates + float realDepth = getLinearDepth( samplePointUv ); // get linear depth from depth texture + float sampleDepth = viewZToOrthographicDepth( samplePoint.z, cameraNear, cameraFar ); // compute linear depth of the sample view Z value + float delta = sampleDepth - realDepth; - ' float realDepth = getLinearDepth( samplePointUv );', // get linear depth from depth texture - ' float sampleDepth = viewZToOrthographicDepth( samplePoint.z, cameraNear, cameraFar );', // compute linear depth of the sample view Z value - ' float delta = sampleDepth - realDepth;', + if ( delta > minDistance && delta < maxDistance ) { // if fragment is before sample point, increase occlusion - ' if ( delta > minDistance && delta < maxDistance ) {', // if fragment is before sample point, increase occlusion + occlusion += 1.0; - ' occlusion += 1.0;', + } - ' }', + } - ' }', + occlusion = clamp( occlusion / float( KERNEL_SIZE ), 0.0, 1.0 ); - ' occlusion = clamp( occlusion / float( KERNEL_SIZE ), 0.0, 1.0 );', + gl_FragColor = vec4( vec3( 1.0 - occlusion ), 1.0 ); - ' gl_FragColor = vec4( vec3( 1.0 - occlusion ), 1.0 );', - - '}' - - ].join( '\n' ) + }` }; -var SSAODepthShader = { +const SSAODepthShader = { defines: { 'PERSPECTIVE_CAMERA': 1 @@ -192,58 +188,54 @@ var SSAODepthShader = { }, - vertexShader: [ - - 'varying vec2 vUv;', + vertexShader: - 'void main() {', + `varying vec2 vUv; - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + void main() { - '}' + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - ].join( '\n' ), + }`, - fragmentShader: [ + fragmentShader: - 'uniform sampler2D tDepth;', + `uniform sampler2D tDepth; - 'uniform float cameraNear;', - 'uniform float cameraFar;', + uniform float cameraNear; + uniform float cameraFar; - 'varying vec2 vUv;', + varying vec2 vUv; - '#include ', + #include - 'float getLinearDepth( const in vec2 screenPosition ) {', + float getLinearDepth( const in vec2 screenPosition ) { - ' #if PERSPECTIVE_CAMERA == 1', + #if PERSPECTIVE_CAMERA == 1 - ' float fragCoordZ = texture2D( tDepth, screenPosition ).x;', - ' float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );', - ' return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );', + float fragCoordZ = texture2D( tDepth, screenPosition ).x; + float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar ); + return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); - ' #else', + #else - ' return texture2D( tDepth, screenPosition ).x;', + return texture2D( tDepth, screenPosition ).x; - ' #endif', + #endif - '}', + } - 'void main() {', + void main() { - ' float depth = getLinearDepth( vUv );', - ' gl_FragColor = vec4( vec3( 1.0 - depth ), 1.0 );', + float depth = getLinearDepth( vUv ); + gl_FragColor = vec4( vec3( 1.0 - depth ), 1.0 ); - '}' - - ].join( '\n' ) + }` }; -var SSAOBlurShader = { +const SSAOBlurShader = { uniforms: { @@ -252,48 +244,44 @@ var SSAOBlurShader = { }, - vertexShader: [ - - 'varying vec2 vUv;', - - 'void main() {', + vertexShader: - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + `varying vec2 vUv; - '}' + void main() { - ].join( '\n' ), + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - fragmentShader: [ + }`, - 'uniform sampler2D tDiffuse;', + fragmentShader: - 'uniform vec2 resolution;', + `uniform sampler2D tDiffuse; - 'varying vec2 vUv;', + uniform vec2 resolution; - 'void main() {', + varying vec2 vUv; - ' vec2 texelSize = ( 1.0 / resolution );', - ' float result = 0.0;', + void main() { - ' for ( int i = - 2; i <= 2; i ++ ) {', + vec2 texelSize = ( 1.0 / resolution ); + float result = 0.0; - ' for ( int j = - 2; j <= 2; j ++ ) {', + for ( int i = - 2; i <= 2; i ++ ) { - ' vec2 offset = ( vec2( float( i ), float( j ) ) ) * texelSize;', - ' result += texture2D( tDiffuse, vUv + offset ).r;', + for ( int j = - 2; j <= 2; j ++ ) { - ' }', + vec2 offset = ( vec2( float( i ), float( j ) ) ) * texelSize; + result += texture2D( tDiffuse, vUv + offset ).r; - ' }', + } - ' gl_FragColor = vec4( vec3( result / ( 5.0 * 5.0 ) ), 1.0 );', + } - '}' + gl_FragColor = vec4( vec3( result / ( 5.0 * 5.0 ) ), 1.0 ); - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/SSRShader.js b/examples/jsm/shaders/SSRShader.js index 7b9083baac8e55..95a5a290097719 100644 --- a/examples/jsm/shaders/SSRShader.js +++ b/examples/jsm/shaders/SSRShader.js @@ -1,7 +1,7 @@ import { - Matrix4, - Vector2 -} from "../../../build/three.module.js"; + Matrix4, + Vector2 +} from '../../../build/three.module.js'; /** * References: * https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html @@ -9,49 +9,48 @@ import { var SSRShader = { - defines: { - MAX_STEP: 0, - PERSPECTIVE_CAMERA: true, - DISTANCE_ATTENUATION: true, - FRESNEL: true, - INFINITE_THICK: false, - SELECTIVE: false, - }, + defines: { + MAX_STEP: 0, + PERSPECTIVE_CAMERA: true, + DISTANCE_ATTENUATION: true, + FRESNEL: true, + INFINITE_THICK: false, + SELECTIVE: false, + }, + + uniforms: { + + 'tDiffuse': { value: null }, + 'tNormal': { value: null }, + 'tMetalness': { value: null }, + 'tDepth': { value: null }, + 'cameraNear': { value: null }, + 'cameraFar': { value: null }, + 'resolution': { value: new Vector2() }, + 'cameraProjectionMatrix': { value: new Matrix4() }, + 'cameraInverseProjectionMatrix': { value: new Matrix4() }, + 'opacity': { value: .5 }, + 'maxDistance': { value: 180 }, + 'cameraRange': { value: 0 }, + 'thickness': { value: .018 }, + + }, + + vertexShader: /* glsl */` - uniforms: { - - "tDiffuse": { value: null }, - "tNormal": { value: null }, - "tMetalness": { value: null }, - "tDepth": { value: null }, - "cameraNear": { value: null }, - "cameraFar": { value: null }, - "resolution": { value: new Vector2() }, - "cameraProjectionMatrix": { value: new Matrix4() }, - "cameraInverseProjectionMatrix": { value: new Matrix4() }, - "opacity": { value: .5 }, - "maxDistance": { value: 180 }, - "cameraRange": { value: 0 }, - "surfDist": { value: .007 }, - "thickTolerance": { value: .03 }, - - }, - - vertexShader: /* glsl */` - - varying vec2 vUv; + varying vec2 vUv; - void main() { + void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - } + } - `, + `, - fragmentShader: /* glsl */` + fragmentShader: /* glsl */` // precision highp float; precision highp sampler2D; varying vec2 vUv; @@ -65,10 +64,9 @@ var SSRShader = { uniform float cameraNear; uniform float cameraFar; uniform float maxDistance; - uniform float surfDist; + uniform float thickness; uniform mat4 cameraProjectionMatrix; uniform mat4 cameraInverseProjectionMatrix; - uniform float thickTolerance; #include float pointToLineDistance(vec3 x0, vec3 x1, vec3 x2) { //x0: point, x1: linePointA, x2: linePointB @@ -180,38 +178,52 @@ var SSRShader = { // https://www.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)); - float sD=surfDist*cW; #else float viewReflectRayZ=viewPosition.z+s*(d1viewPosition.z-viewPosition.z); - float sD=surfDist; #endif - if(viewReflectRayZ-sD>vZ) continue; - #ifdef INFINITE_THICK - if(viewReflectRayZ+thickTolerance*clipW=0.) continue; - float distance=pointPlaneDistance(vP,viewPosition,viewNormal); - if(distance>maxDistance) break; - #ifdef DISTANCE_ATTENUATION - float ratio=1.-(distance/maxDistance); - float attenuation=ratio*ratio; - op=opacity*attenuation; + // if(viewReflectRayZ>vZ) continue; // will cause "npm run make-screenshot webgl_postprocessing_ssr" high probability hang. + // https://github.com/mrdoob/three.js/pull/21539#issuecomment-821061164 + if(viewReflectRayZ<=vZ){ + + bool hit; + #ifdef INFINITE_THICK + hit=true; + #else + float away=pointToLineDistance(vP,viewPosition,d1viewPosition); + + float minThickness; + vec2 xyNeighbor=xy; + xyNeighbor.x+=1.; + vec2 uvNeighbor=xyNeighbor/resolution; + vec3 vPNeighbor=getViewPosition(uvNeighbor,d,cW); + minThickness=vPNeighbor.x-vP.x; + minThickness*=3.; + float tk=max(minThickness,thickness); + + hit=away<=tk; #endif - #ifdef FRESNEL - float fresnelCoe=(dot(viewIncidentDir,viewReflectDir)+1.)/2.; - op*=fresnelCoe; - #endif - vec4 reflectColor=texture2D(tDiffuse,uv); - gl_FragColor.xyz=reflectColor.xyz; - gl_FragColor.a=op; - break; + + if(hit){ + vec3 vN=getViewNormal( uv ); + if(dot(viewReflectDir,vN)>=0.) continue; + float distance=pointPlaneDistance(vP,viewPosition,viewNormal); + if(distance>maxDistance) break; + float op=opacity; + #ifdef DISTANCE_ATTENUATION + float ratio=1.-(distance/maxDistance); + float attenuation=ratio*ratio; + op=opacity*attenuation; + #endif + #ifdef FRESNEL + float fresnelCoe=(dot(viewIncidentDir,viewReflectDir)+1.)/2.; + op*=fresnelCoe; + #endif + vec4 reflectColor=texture2D(tDiffuse,uv); + gl_FragColor.xyz=reflectColor.xyz; + gl_FragColor.a=op; + break; + } } } } @@ -221,41 +233,41 @@ var SSRShader = { var SSRDepthShader = { - defines: { - "PERSPECTIVE_CAMERA": 1 - }, + defines: { + 'PERSPECTIVE_CAMERA': 1 + }, - uniforms: { + uniforms: { - "tDepth": { value: null }, - "cameraNear": { value: null }, - "cameraFar": { value: null }, + 'tDepth': { value: null }, + 'cameraNear': { value: null }, + 'cameraFar': { value: null }, - }, + }, - vertexShader: /* glsl */` + vertexShader: /* glsl */` - varying vec2 vUv; + varying vec2 vUv; - void main() { + void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - } + } - `, + `, - fragmentShader: /* glsl */` + fragmentShader: /* glsl */` - uniform sampler2D tDepth; + uniform sampler2D tDepth; - uniform float cameraNear; - uniform float cameraFar; + uniform float cameraNear; + uniform float cameraFar; - varying vec2 vUv; + varying vec2 vUv; - #include + #include float getLinearDepth( const in vec2 uv ) { @@ -273,51 +285,51 @@ var SSRDepthShader = { } - void main() { + void main() { - float depth = getLinearDepth( vUv ); + float depth = getLinearDepth( vUv ); float d = 1.0 - depth; // d=(d-.999)*1000.; - gl_FragColor = vec4( vec3( d ), 1.0 ); + gl_FragColor = vec4( vec3( d ), 1.0 ); - } + } - ` + ` }; var SSRBlurShader = { - uniforms: { + uniforms: { - "tDiffuse": { value: null }, - "resolution": { value: new Vector2() }, - "opacity": { value: .5 }, + 'tDiffuse': { value: null }, + 'resolution': { value: new Vector2() }, + 'opacity': { value: .5 }, - }, + }, - vertexShader: /* glsl */` + vertexShader: /* glsl */` - varying vec2 vUv; + varying vec2 vUv; - void main() { + void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - } + } - `, + `, - fragmentShader: /* glsl */` + fragmentShader: /* glsl */` - uniform sampler2D tDiffuse; - uniform vec2 resolution; - varying vec2 vUv; - void main() { + uniform sampler2D tDiffuse; + uniform vec2 resolution; + varying vec2 vUv; + void main() { //reverse engineering from PhotoShop blur filter, then change coefficient - vec2 texelSize = ( 1.0 / resolution ); + vec2 texelSize = ( 1.0 / resolution ); vec4 c=texture2D(tDiffuse,vUv); diff --git a/examples/jsm/shaders/SSRrShader.js b/examples/jsm/shaders/SSRrShader.js index b999acfecc400e..b6b0a847b9b5b9 100644 --- a/examples/jsm/shaders/SSRrShader.js +++ b/examples/jsm/shaders/SSRrShader.js @@ -1,9 +1,9 @@ import { Matrix4, Vector2 -} from "../../../build/three.module.js"; +} from '../../../build/three.module.js'; -var SSRrShader = { +const SSRrShader = { defines: { MAX_STEP: 0, @@ -15,21 +15,21 @@ var SSRrShader = { uniforms: { - "tDiffuse": { value: null }, - "tSpecular": { value: null }, - "tNormalSelects": { value: null }, - "tRefractive": { value: null }, - "tDepth": { value: null }, - "tDepthSelects": { value: null }, - "cameraNear": { value: null }, - "cameraFar": { value: null }, - "resolution": { value: new Vector2() }, - "cameraProjectionMatrix": { value: new Matrix4() }, - "cameraInverseProjectionMatrix": { value: new Matrix4() }, - "ior": { value: 1.03 }, - "cameraRange": { value: 0 }, - "maxDistance": { value: 180 }, - "surfDist": { value: .007 }, + 'tDiffuse': { value: null }, + 'tSpecular': { value: null }, + 'tNormalSelects': { value: null }, + 'tRefractive': { value: null }, + 'tDepth': { value: null }, + 'tDepthSelects': { value: null }, + 'cameraNear': { value: null }, + 'cameraFar': { value: null }, + 'resolution': { value: new Vector2() }, + 'cameraProjectionMatrix': { value: new Matrix4() }, + 'cameraInverseProjectionMatrix': { value: new Matrix4() }, + 'ior': { value: 1.03 }, + 'cameraRange': { value: 0 }, + 'maxDistance': { value: 180 }, + 'surfDist': { value: .007 }, }, @@ -240,14 +240,14 @@ var SSRrShader = { var SSRrDepthShader = { defines: { - "PERSPECTIVE_CAMERA": 1 + 'PERSPECTIVE_CAMERA': 1 }, uniforms: { - "tDepth": { value: null }, - "cameraNear": { value: null }, - "cameraFar": { value: null }, + 'tDepth': { value: null }, + 'cameraNear': { value: null }, + 'cameraFar': { value: null }, }, diff --git a/examples/jsm/shaders/SepiaShader.js b/examples/jsm/shaders/SepiaShader.js index 63fbd404ca6fe9..01a6daa98eac8a 100644 --- a/examples/jsm/shaders/SepiaShader.js +++ b/examples/jsm/shaders/SepiaShader.js @@ -4,7 +4,7 @@ * https://github.com/evanw/glfx.js */ -var SepiaShader = { +const SepiaShader = { uniforms: { @@ -13,41 +13,37 @@ var SepiaShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float amount; - 'uniform float amount;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 color = texture2D( tDiffuse, vUv ); + vec3 c = color.rgb; - ' vec4 color = texture2D( tDiffuse, vUv );', - ' vec3 c = color.rgb;', + color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) ); + color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) ); + color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) ); - ' color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );', - ' color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );', - ' color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );', + gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a ); - ' gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/SobelOperatorShader.js b/examples/jsm/shaders/SobelOperatorShader.js index 8021fa0d322823..9c8f148c58e63b 100644 --- a/examples/jsm/shaders/SobelOperatorShader.js +++ b/examples/jsm/shaders/SobelOperatorShader.js @@ -9,7 +9,7 @@ import { * */ -var SobelOperatorShader = { +const SobelOperatorShader = { uniforms: { @@ -18,76 +18,72 @@ var SobelOperatorShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform vec2 resolution; + varying vec2 vUv; - 'uniform sampler2D tDiffuse;', - 'uniform vec2 resolution;', - 'varying vec2 vUv;', + void main() { - 'void main() {', - - ' vec2 texel = vec2( 1.0 / resolution.x, 1.0 / resolution.y );', + vec2 texel = vec2( 1.0 / resolution.x, 1.0 / resolution.y ); // kernel definition (in glsl matrices are filled in column-major order) - ' const mat3 Gx = mat3( -1, -2, -1, 0, 0, 0, 1, 2, 1 );', // x direction kernel - ' const mat3 Gy = mat3( -1, 0, 1, -2, 0, 2, -1, 0, 1 );', // y direction kernel + const mat3 Gx = mat3( -1, -2, -1, 0, 0, 0, 1, 2, 1 ); // x direction kernel + const mat3 Gy = mat3( -1, 0, 1, -2, 0, 2, -1, 0, 1 ); // y direction kernel // fetch the 3x3 neighbourhood of a fragment // first column - ' float tx0y0 = texture2D( tDiffuse, vUv + texel * vec2( -1, -1 ) ).r;', - ' float tx0y1 = texture2D( tDiffuse, vUv + texel * vec2( -1, 0 ) ).r;', - ' float tx0y2 = texture2D( tDiffuse, vUv + texel * vec2( -1, 1 ) ).r;', + float tx0y0 = texture2D( tDiffuse, vUv + texel * vec2( -1, -1 ) ).r; + float tx0y1 = texture2D( tDiffuse, vUv + texel * vec2( -1, 0 ) ).r; + float tx0y2 = texture2D( tDiffuse, vUv + texel * vec2( -1, 1 ) ).r; // second column - ' float tx1y0 = texture2D( tDiffuse, vUv + texel * vec2( 0, -1 ) ).r;', - ' float tx1y1 = texture2D( tDiffuse, vUv + texel * vec2( 0, 0 ) ).r;', - ' float tx1y2 = texture2D( tDiffuse, vUv + texel * vec2( 0, 1 ) ).r;', + float tx1y0 = texture2D( tDiffuse, vUv + texel * vec2( 0, -1 ) ).r; + float tx1y1 = texture2D( tDiffuse, vUv + texel * vec2( 0, 0 ) ).r; + float tx1y2 = texture2D( tDiffuse, vUv + texel * vec2( 0, 1 ) ).r; // third column - ' float tx2y0 = texture2D( tDiffuse, vUv + texel * vec2( 1, -1 ) ).r;', - ' float tx2y1 = texture2D( tDiffuse, vUv + texel * vec2( 1, 0 ) ).r;', - ' float tx2y2 = texture2D( tDiffuse, vUv + texel * vec2( 1, 1 ) ).r;', + float tx2y0 = texture2D( tDiffuse, vUv + texel * vec2( 1, -1 ) ).r; + float tx2y1 = texture2D( tDiffuse, vUv + texel * vec2( 1, 0 ) ).r; + float tx2y2 = texture2D( tDiffuse, vUv + texel * vec2( 1, 1 ) ).r; // gradient value in x direction - ' float valueGx = Gx[0][0] * tx0y0 + Gx[1][0] * tx1y0 + Gx[2][0] * tx2y0 + ', - ' Gx[0][1] * tx0y1 + Gx[1][1] * tx1y1 + Gx[2][1] * tx2y1 + ', - ' Gx[0][2] * tx0y2 + Gx[1][2] * tx1y2 + Gx[2][2] * tx2y2; ', + float valueGx = Gx[0][0] * tx0y0 + Gx[1][0] * tx1y0 + Gx[2][0] * tx2y0 + + Gx[0][1] * tx0y1 + Gx[1][1] * tx1y1 + Gx[2][1] * tx2y1 + + Gx[0][2] * tx0y2 + Gx[1][2] * tx1y2 + Gx[2][2] * tx2y2; // gradient value in y direction - ' float valueGy = Gy[0][0] * tx0y0 + Gy[1][0] * tx1y0 + Gy[2][0] * tx2y0 + ', - ' Gy[0][1] * tx0y1 + Gy[1][1] * tx1y1 + Gy[2][1] * tx2y1 + ', - ' Gy[0][2] * tx0y2 + Gy[1][2] * tx1y2 + Gy[2][2] * tx2y2; ', + float valueGy = Gy[0][0] * tx0y0 + Gy[1][0] * tx1y0 + Gy[2][0] * tx2y0 + + Gy[0][1] * tx0y1 + Gy[1][1] * tx1y1 + Gy[2][1] * tx2y1 + + Gy[0][2] * tx0y2 + Gy[1][2] * tx1y2 + Gy[2][2] * tx2y2; // magnitute of the total gradient - ' float G = sqrt( ( valueGx * valueGx ) + ( valueGy * valueGy ) );', - - ' gl_FragColor = vec4( vec3( G ), 1 );', + float G = sqrt( ( valueGx * valueGx ) + ( valueGy * valueGy ) ); - '}' + gl_FragColor = vec4( vec3( G ), 1 ); - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/SubsurfaceScatteringShader.js b/examples/jsm/shaders/SubsurfaceScatteringShader.js index 4e26c7b1084b82..050da7cd46cf46 100644 --- a/examples/jsm/shaders/SubsurfaceScatteringShader.js +++ b/examples/jsm/shaders/SubsurfaceScatteringShader.js @@ -19,10 +19,10 @@ function replaceAll( string, find, replace ) { } -var meshphong_frag_head = ShaderChunk[ 'meshphong_frag' ].slice( 0, ShaderChunk[ 'meshphong_frag' ].indexOf( 'void main() {' ) ); -var meshphong_frag_body = ShaderChunk[ 'meshphong_frag' ].slice( ShaderChunk[ 'meshphong_frag' ].indexOf( 'void main() {' ) ); +const meshphong_frag_head = ShaderChunk[ 'meshphong_frag' ].slice( 0, ShaderChunk[ 'meshphong_frag' ].indexOf( 'void main() {' ) ); +const meshphong_frag_body = ShaderChunk[ 'meshphong_frag' ].slice( ShaderChunk[ 'meshphong_frag' ].indexOf( 'void main() {' ) ); -var SubsurfaceScatteringShader = { +const SubsurfaceScatteringShader = { uniforms: UniformsUtils.merge( [ ShaderLib[ 'phong' ].uniforms, diff --git a/examples/jsm/shaders/TechnicolorShader.js b/examples/jsm/shaders/TechnicolorShader.js index c97db3ed1c76f3..ef0f2ff654e147 100644 --- a/examples/jsm/shaders/TechnicolorShader.js +++ b/examples/jsm/shaders/TechnicolorShader.js @@ -5,7 +5,7 @@ * Demo here: http://charliehoey.com/technicolor_shader/shader_test.html */ -var TechnicolorShader = { +const TechnicolorShader = { uniforms: { @@ -13,34 +13,30 @@ var TechnicolorShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + varying vec2 vUv; - 'uniform sampler2D tDiffuse;', - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 tex = texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ); + vec4 newTex = vec4(tex.r, (tex.g + tex.b) * .5, (tex.g + tex.b) * .5, 1.0); - ' vec4 tex = texture2D( tDiffuse, vec2( vUv.x, vUv.y ) );', - ' vec4 newTex = vec4(tex.r, (tex.g + tex.b) * .5, (tex.g + tex.b) * .5, 1.0);', + gl_FragColor = newTex; - ' gl_FragColor = newTex;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/ToneMapShader.js b/examples/jsm/shaders/ToneMapShader.js index b73cfb50d4a593..0d476a6f292a70 100644 --- a/examples/jsm/shaders/ToneMapShader.js +++ b/examples/jsm/shaders/ToneMapShader.js @@ -14,63 +14,59 @@ var ToneMapShader = { 'middleGrey': { value: 0.6 } }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + #include - '#include ', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + uniform float middleGrey; + uniform float minLuminance; + uniform float maxLuminance; + #ifdef ADAPTED_LUMINANCE + uniform sampler2D luminanceMap; + #else + uniform float averageLuminance; + #endif - 'uniform float middleGrey;', - 'uniform float minLuminance;', - 'uniform float maxLuminance;', - '#ifdef ADAPTED_LUMINANCE', - ' uniform sampler2D luminanceMap;', - '#else', - ' uniform float averageLuminance;', - '#endif', + vec3 ToneMap( vec3 vColor ) { + #ifdef ADAPTED_LUMINANCE + // Get the calculated average luminance + float fLumAvg = texture2D(luminanceMap, vec2(0.5, 0.5)).r; + #else + float fLumAvg = averageLuminance; + #endif - 'vec3 ToneMap( vec3 vColor ) {', - ' #ifdef ADAPTED_LUMINANCE', - // Get the calculated average luminance - ' float fLumAvg = texture2D(luminanceMap, vec2(0.5, 0.5)).r;', - ' #else', - ' float fLumAvg = averageLuminance;', - ' #endif', + // Calculate the luminance of the current pixel + float fLumPixel = linearToRelativeLuminance( vColor ); - // Calculate the luminance of the current pixel - ' float fLumPixel = linearToRelativeLuminance( vColor );', + // Apply the modified operator (Eq. 4) + float fLumScaled = (fLumPixel * middleGrey) / max( minLuminance, fLumAvg ); - // Apply the modified operator (Eq. 4) - ' float fLumScaled = (fLumPixel * middleGrey) / max( minLuminance, fLumAvg );', + float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (maxLuminance * maxLuminance)))) / (1.0 + fLumScaled); + return fLumCompressed * vColor; + } - ' float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (maxLuminance * maxLuminance)))) / (1.0 + fLumScaled);', - ' return fLumCompressed * vColor;', - '}', + void main() { - 'void main() {', + vec4 texel = texture2D( tDiffuse, vUv ); - ' vec4 texel = texture2D( tDiffuse, vUv );', + gl_FragColor = vec4( ToneMap( texel.xyz ), texel.w ); - ' gl_FragColor = vec4( ToneMap( texel.xyz ), texel.w );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/ToonShader.js b/examples/jsm/shaders/ToonShader.js index df79b97481455f..bdd4196191101f 100644 --- a/examples/jsm/shaders/ToonShader.js +++ b/examples/jsm/shaders/ToonShader.js @@ -12,7 +12,7 @@ import { * dotted */ -var ToonShader1 = { +const ToonShader1 = { uniforms: { @@ -25,70 +25,66 @@ var ToonShader1 = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec3 vNormal;', - 'varying vec3 vRefract;', + varying vec3 vNormal; + varying vec3 vRefract; - 'void main() {', + void main() { - ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );', - ' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );', - ' vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );', + vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); + vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); + vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal ); - ' vNormal = normalize( normalMatrix * normal );', + vNormal = normalize( normalMatrix * normal ); - ' vec3 I = worldPosition.xyz - cameraPosition;', - ' vRefract = refract( normalize( I ), worldNormal, 1.02 );', + vec3 I = worldPosition.xyz - cameraPosition; + vRefract = refract( normalize( I ), worldNormal, 1.02 ); - ' gl_Position = projectionMatrix * mvPosition;', + gl_Position = projectionMatrix * mvPosition; - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform vec3 uBaseColor; - 'uniform vec3 uBaseColor;', + uniform vec3 uDirLightPos; + uniform vec3 uDirLightColor; - 'uniform vec3 uDirLightPos;', - 'uniform vec3 uDirLightColor;', + uniform vec3 uAmbientLightColor; - 'uniform vec3 uAmbientLightColor;', + varying vec3 vNormal; - 'varying vec3 vNormal;', + varying vec3 vRefract; - 'varying vec3 vRefract;', + void main() { - 'void main() {', + float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0); + vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting; - ' float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);', - ' vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;', + float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) ); + intensity += length(lightWeighting) * 0.2; - ' float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );', - ' intensity += length(lightWeighting) * 0.2;', + float cameraWeighting = dot( normalize( vNormal ), vRefract ); + intensity += pow( 1.0 - length( cameraWeighting ), 6.0 ); + intensity = intensity * 0.2 + 0.3; - ' float cameraWeighting = dot( normalize( vNormal ), vRefract );', - ' intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );', - ' intensity = intensity * 0.2 + 0.3;', + if ( intensity < 0.50 ) { - ' if ( intensity < 0.50 ) {', + gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 ); - ' gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );', + } else { - ' } else {', + gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 ); - ' gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );', + } - '}', - - '}' - - ].join( '\n' ) + }` }; -var ToonShader2 = { +const ToonShader2 = { uniforms: { @@ -105,60 +101,56 @@ var ToonShader2 = { }, - vertexShader: [ - - 'varying vec3 vNormal;', - - 'void main() {', + vertexShader: /* glsl */` - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - ' vNormal = normalize( normalMatrix * normal );', + varying vec3 vNormal; - '}' + void main() { - ].join( '\n' ), + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + vNormal = normalize( normalMatrix * normal ); - fragmentShader: [ + }`, - 'uniform vec3 uBaseColor;', - 'uniform vec3 uLineColor1;', - 'uniform vec3 uLineColor2;', - 'uniform vec3 uLineColor3;', - 'uniform vec3 uLineColor4;', + fragmentShader: /* glsl */` - 'uniform vec3 uDirLightPos;', - 'uniform vec3 uDirLightColor;', + uniform vec3 uBaseColor; + uniform vec3 uLineColor1; + uniform vec3 uLineColor2; + uniform vec3 uLineColor3; + uniform vec3 uLineColor4; - 'uniform vec3 uAmbientLightColor;', + uniform vec3 uDirLightPos; + uniform vec3 uDirLightColor; - 'varying vec3 vNormal;', + uniform vec3 uAmbientLightColor; - 'void main() {', + varying vec3 vNormal; - ' float camera = max( dot( normalize( vNormal ), vec3( 0.0, 0.0, 1.0 ) ), 0.4);', - ' float light = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);', + void main() { - ' gl_FragColor = vec4( uBaseColor, 1.0 );', + float camera = max( dot( normalize( vNormal ), vec3( 0.0, 0.0, 1.0 ) ), 0.4); + float light = max( dot( normalize( vNormal ), uDirLightPos ), 0.0); - ' if ( length(uAmbientLightColor + uDirLightColor * light) < 1.00 ) {', + gl_FragColor = vec4( uBaseColor, 1.0 ); - ' gl_FragColor *= vec4( uLineColor1, 1.0 );', + if ( length(uAmbientLightColor + uDirLightColor * light) < 1.00 ) { - ' }', + gl_FragColor *= vec4( uLineColor1, 1.0 ); - ' if ( length(uAmbientLightColor + uDirLightColor * camera) < 0.50 ) {', + } - ' gl_FragColor *= vec4( uLineColor2, 1.0 );', + if ( length(uAmbientLightColor + uDirLightColor * camera) < 0.50 ) { - ' }', + gl_FragColor *= vec4( uLineColor2, 1.0 ); - '}' + } - ].join( '\n' ) + }` }; -var ToonShaderHatching = { +const ToonShaderHatching = { uniforms: { @@ -175,88 +167,84 @@ var ToonShaderHatching = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec3 vNormal;', + varying vec3 vNormal; - 'void main() {', + void main() { - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - ' vNormal = normalize( normalMatrix * normal );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + vNormal = normalize( normalMatrix * normal ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform vec3 uBaseColor; + uniform vec3 uLineColor1; + uniform vec3 uLineColor2; + uniform vec3 uLineColor3; + uniform vec3 uLineColor4; - 'uniform vec3 uBaseColor;', - 'uniform vec3 uLineColor1;', - 'uniform vec3 uLineColor2;', - 'uniform vec3 uLineColor3;', - 'uniform vec3 uLineColor4;', + uniform vec3 uDirLightPos; + uniform vec3 uDirLightColor; - 'uniform vec3 uDirLightPos;', - 'uniform vec3 uDirLightColor;', + uniform vec3 uAmbientLightColor; - 'uniform vec3 uAmbientLightColor;', + varying vec3 vNormal; - 'varying vec3 vNormal;', + void main() { - 'void main() {', + float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0); + vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting; - ' float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);', - ' vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;', + gl_FragColor = vec4( uBaseColor, 1.0 ); - ' gl_FragColor = vec4( uBaseColor, 1.0 );', + if ( length(lightWeighting) < 1.00 ) { - ' if ( length(lightWeighting) < 1.00 ) {', + if ( mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) { - ' if ( mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {', + gl_FragColor = vec4( uLineColor1, 1.0 ); - ' gl_FragColor = vec4( uLineColor1, 1.0 );', + } - ' }', + } - ' }', + if ( length(lightWeighting) < 0.75 ) { - ' if ( length(lightWeighting) < 0.75 ) {', + if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) { - ' if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {', + gl_FragColor = vec4( uLineColor2, 1.0 ); - ' gl_FragColor = vec4( uLineColor2, 1.0 );', + } - ' }', + } - ' }', + if ( length(lightWeighting) < 0.50 ) { - ' if ( length(lightWeighting) < 0.50 ) {', + if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) { - ' if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {', + gl_FragColor = vec4( uLineColor3, 1.0 ); - ' gl_FragColor = vec4( uLineColor3, 1.0 );', + } - ' }', + } - ' }', + if ( length(lightWeighting) < 0.3465 ) { - ' if ( length(lightWeighting) < 0.3465 ) {', + if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) { - ' if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {', + gl_FragColor = vec4( uLineColor4, 1.0 ); - ' gl_FragColor = vec4( uLineColor4, 1.0 );', + } - ' }', + } - ' }', - - '}' - - ].join( '\n' ) + }` }; -var ToonShaderDotted = { +const ToonShaderDotted = { uniforms: { @@ -270,64 +258,60 @@ var ToonShaderDotted = { }, - vertexShader: [ - - 'varying vec3 vNormal;', - - 'void main() {', + vertexShader: /* glsl */` - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', - ' vNormal = normalize( normalMatrix * normal );', + varying vec3 vNormal; - '}' + void main() { - ].join( '\n' ), + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); + vNormal = normalize( normalMatrix * normal ); - fragmentShader: [ + }`, - 'uniform vec3 uBaseColor;', - 'uniform vec3 uLineColor1;', - 'uniform vec3 uLineColor2;', - 'uniform vec3 uLineColor3;', - 'uniform vec3 uLineColor4;', + fragmentShader: /* glsl */` - 'uniform vec3 uDirLightPos;', - 'uniform vec3 uDirLightColor;', + uniform vec3 uBaseColor; + uniform vec3 uLineColor1; + uniform vec3 uLineColor2; + uniform vec3 uLineColor3; + uniform vec3 uLineColor4; - 'uniform vec3 uAmbientLightColor;', + uniform vec3 uDirLightPos; + uniform vec3 uDirLightColor; - 'varying vec3 vNormal;', + uniform vec3 uAmbientLightColor; - 'void main() {', + varying vec3 vNormal; - 'float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);', - 'vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;', + void main() { - 'gl_FragColor = vec4( uBaseColor, 1.0 );', + float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0); + vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting; - 'if ( length(lightWeighting) < 1.00 ) {', + gl_FragColor = vec4( uBaseColor, 1.0 ); - ' if ( ( mod(gl_FragCoord.x, 4.001) + mod(gl_FragCoord.y, 4.0) ) > 6.00 ) {', + if ( length(lightWeighting) < 1.00 ) { - ' gl_FragColor = vec4( uLineColor1, 1.0 );', + if ( ( mod(gl_FragCoord.x, 4.001) + mod(gl_FragCoord.y, 4.0) ) > 6.00 ) { - ' }', + gl_FragColor = vec4( uLineColor1, 1.0 ); - ' }', + } - ' if ( length(lightWeighting) < 0.50 ) {', + } - ' if ( ( mod(gl_FragCoord.x + 2.0, 4.001) + mod(gl_FragCoord.y + 2.0, 4.0) ) > 6.00 ) {', + if ( length(lightWeighting) < 0.50 ) { - ' gl_FragColor = vec4( uLineColor1, 1.0 );', + if ( ( mod(gl_FragCoord.x + 2.0, 4.001) + mod(gl_FragCoord.y + 2.0, 4.0) ) > 6.00 ) { - ' }', + gl_FragColor = vec4( uLineColor1, 1.0 ); - ' }', + } - '}' + } - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/TriangleBlurShader.js b/examples/jsm/shaders/TriangleBlurShader.js index 0c24390c985130..37b195037b5bdd 100644 --- a/examples/jsm/shaders/TriangleBlurShader.js +++ b/examples/jsm/shaders/TriangleBlurShader.js @@ -12,7 +12,7 @@ import { * perpendicular triangle filters. */ -var TriangleBlurShader = { +const TriangleBlurShader = { uniforms: { @@ -21,55 +21,51 @@ var TriangleBlurShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + #include - '#include ', + #define ITERATIONS 10.0 - '#define ITERATIONS 10.0', + uniform sampler2D texture; + uniform vec2 delta; - 'uniform sampler2D texture;', - 'uniform vec2 delta;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 color = vec4( 0.0 ); - ' vec4 color = vec4( 0.0 );', - - ' float total = 0.0;', + float total = 0.0; // randomize the lookup values to hide the fixed number of samples - ' float offset = rand( vUv );', - - ' for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {', + float offset = rand( vUv ); - ' float percent = ( t + offset - 0.5 ) / ITERATIONS;', - ' float weight = 1.0 - abs( percent );', + for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) { - ' color += texture2D( texture, vUv + delta * percent ) * weight;', - ' total += weight;', + float percent = ( t + offset - 0.5 ) / ITERATIONS; + float weight = 1.0 - abs( percent ); - ' }', + color += texture2D( texture, vUv + delta * percent ) * weight; + total += weight; - ' gl_FragColor = color / total;', + } - '}' + gl_FragColor = color / total; - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/UnpackDepthRGBAShader.js b/examples/jsm/shaders/UnpackDepthRGBAShader.js index 60a37c752dc294..eb72e6db0ff22c 100644 --- a/examples/jsm/shaders/UnpackDepthRGBAShader.js +++ b/examples/jsm/shaders/UnpackDepthRGBAShader.js @@ -3,7 +3,7 @@ * - show RGBA encoded depth as monochrome color */ -var UnpackDepthRGBAShader = { +const UnpackDepthRGBAShader = { uniforms: { @@ -12,37 +12,33 @@ var UnpackDepthRGBAShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float opacity; - 'uniform float opacity;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + #include - '#include ', + void main() { - 'void main() {', + float depth = 1.0 - unpackRGBAToDepth( texture2D( tDiffuse, vUv ) ); + gl_FragColor = vec4( vec3( depth ), opacity ); - ' float depth = 1.0 - unpackRGBAToDepth( texture2D( tDiffuse, vUv ) );', - ' gl_FragColor = vec4( vec3( depth ), opacity );', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/VerticalBlurShader.js b/examples/jsm/shaders/VerticalBlurShader.js index d1fb8bcd8dde33..8a28b1d5a36fff 100644 --- a/examples/jsm/shaders/VerticalBlurShader.js +++ b/examples/jsm/shaders/VerticalBlurShader.js @@ -8,7 +8,7 @@ * - "h" and "v" parameters should be set to "1 / width" and "1 / height" */ -var VerticalBlurShader = { +const VerticalBlurShader = { uniforms: { @@ -17,45 +17,41 @@ var VerticalBlurShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float v; - 'uniform sampler2D tDiffuse;', - 'uniform float v;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 sum = vec4( 0.0 ); - ' vec4 sum = vec4( 0.0 );', + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051; - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;', + gl_FragColor = sum; - ' gl_FragColor = sum;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/VerticalTiltShiftShader.js b/examples/jsm/shaders/VerticalTiltShiftShader.js index 512bafe0419af6..768c8aeda3426d 100644 --- a/examples/jsm/shaders/VerticalTiltShiftShader.js +++ b/examples/jsm/shaders/VerticalTiltShiftShader.js @@ -7,7 +7,7 @@ * - "r" parameter control where "focused" horizontal line lies */ -var VerticalTiltShiftShader = { +const VerticalTiltShiftShader = { uniforms: { @@ -17,48 +17,44 @@ var VerticalTiltShiftShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform sampler2D tDiffuse; + uniform float v; + uniform float r; - 'uniform sampler2D tDiffuse;', - 'uniform float v;', - 'uniform float r;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + vec4 sum = vec4( 0.0 ); - ' vec4 sum = vec4( 0.0 );', + float vv = v * abs( r - vUv.y ); - ' float vv = v * abs( r - vUv.y );', + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918; + sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051; - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;', - ' sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;', + gl_FragColor = sum; - ' gl_FragColor = sum;', - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/VignetteShader.js b/examples/jsm/shaders/VignetteShader.js index 3cd9044e34f782..839dc42afd026c 100644 --- a/examples/jsm/shaders/VignetteShader.js +++ b/examples/jsm/shaders/VignetteShader.js @@ -4,7 +4,7 @@ * http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js */ -var VignetteShader = { +const VignetteShader = { uniforms: { @@ -14,49 +14,35 @@ var VignetteShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'varying vec2 vUv;', + varying vec2 vUv; - 'void main() {', + void main() { - ' vUv = uv;', - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform float offset; + uniform float darkness; - 'uniform float offset;', - 'uniform float darkness;', + uniform sampler2D tDiffuse; - 'uniform sampler2D tDiffuse;', + varying vec2 vUv; - 'varying vec2 vUv;', + void main() { - 'void main() {', + // Eskil's vignette - // Eskil's vignette + vec4 texel = texture2D( tDiffuse, vUv ); + vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset ); + gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a ); - ' vec4 texel = texture2D( tDiffuse, vUv );', - ' vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );', - ' gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );', - - /* - // alternative version from glfx.js - // this one makes more "dusty" look (as opposed to "burned") - - " vec4 color = texture2D( tDiffuse, vUv );", - " float dist = distance( vUv, vec2( 0.5 ) );", - " color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );", - " gl_FragColor = color;", - */ - - '}' - - ].join( '\n' ) + }` }; diff --git a/examples/jsm/shaders/VolumeShader.js b/examples/jsm/shaders/VolumeShader.js index 66f8a777dee1b7..bdeeb296256162 100644 --- a/examples/jsm/shaders/VolumeShader.js +++ b/examples/jsm/shaders/VolumeShader.js @@ -9,7 +9,8 @@ import { * This is not the only approach, therefore it's marked 1. */ -var VolumeRenderShader1 = { +const VolumeRenderShader1 = { + uniforms: { 'u_size': { value: new Vector3( 1, 1, 1 ) }, 'u_renderstyle': { value: 0 }, @@ -18,268 +19,271 @@ var VolumeRenderShader1 = { 'u_data': { value: null }, 'u_cmdata': { value: null } }, - vertexShader: [ - ' varying vec4 v_nearpos;', - ' varying vec4 v_farpos;', - ' varying vec3 v_position;', - - ' void main() {', - // Prepare transforms to map to "camera view". See also: - // https://threejs.org/docs/#api/renderers/webgl/WebGLProgram - ' mat4 viewtransformf = modelViewMatrix;', - ' mat4 viewtransformi = inverse(modelViewMatrix);', - - // Project local vertex coordinate to camera position. Then do a step - // backward (in cam coords) to the near clipping plane, and project back. Do - // the same for the far clipping plane. This gives us all the information we - // need to calculate the ray and truncate it to the viewing cone. - ' vec4 position4 = vec4(position, 1.0);', - ' vec4 pos_in_cam = viewtransformf * position4;', - - // Intersection of ray and near clipping plane (z = -1 in clip coords) - ' pos_in_cam.z = -pos_in_cam.w;', - ' v_nearpos = viewtransformi * pos_in_cam;', - - // Intersection of ray and far clipping plane (z = +1 in clip coords) - ' pos_in_cam.z = pos_in_cam.w;', - ' v_farpos = viewtransformi * pos_in_cam;', - - // Set varyings and output pos - ' v_position = position;', - ' gl_Position = projectionMatrix * viewMatrix * modelMatrix * position4;', - ' }', - ].join( '\n' ), - fragmentShader: [ - ' precision highp float;', - ' precision mediump sampler3D;', - - ' uniform vec3 u_size;', - ' uniform int u_renderstyle;', - ' uniform float u_renderthreshold;', - ' uniform vec2 u_clim;', - - ' uniform sampler3D u_data;', - ' uniform sampler2D u_cmdata;', - - ' varying vec3 v_position;', - ' varying vec4 v_nearpos;', - ' varying vec4 v_farpos;', - - // The maximum distance through our rendering volume is sqrt(3). - ' const int MAX_STEPS = 887; // 887 for 512^3, 1774 for 1024^3', - ' const int REFINEMENT_STEPS = 4;', - ' const float relative_step_size = 1.0;', - ' const vec4 ambient_color = vec4(0.2, 0.4, 0.2, 1.0);', - ' const vec4 diffuse_color = vec4(0.8, 0.2, 0.2, 1.0);', - ' const vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0);', - ' const float shininess = 40.0;', - - ' void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);', - ' void cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);', - - ' float sample1(vec3 texcoords);', - ' vec4 apply_colormap(float val);', - ' vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray);', - - - ' void main() {', - // Normalize clipping plane info - ' vec3 farpos = v_farpos.xyz / v_farpos.w;', - ' vec3 nearpos = v_nearpos.xyz / v_nearpos.w;', - - // Calculate unit vector pointing in the view direction through this fragment. - ' vec3 view_ray = normalize(nearpos.xyz - farpos.xyz);', - - // Compute the (negative) distance to the front surface or near clipping plane. - // v_position is the back face of the cuboid, so the initial distance calculated in the dot - // product below is the distance from near clip plane to the back of the cuboid - ' float distance = dot(nearpos - v_position, view_ray);', - ' distance = max(distance, min((-0.5 - v_position.x) / view_ray.x,', - ' (u_size.x - 0.5 - v_position.x) / view_ray.x));', - ' distance = max(distance, min((-0.5 - v_position.y) / view_ray.y,', - ' (u_size.y - 0.5 - v_position.y) / view_ray.y));', - ' distance = max(distance, min((-0.5 - v_position.z) / view_ray.z,', - ' (u_size.z - 0.5 - v_position.z) / view_ray.z));', - - // Now we have the starting position on the front surface - ' vec3 front = v_position + view_ray * distance;', - - // Decide how many steps to take - ' int nsteps = int(-distance / relative_step_size + 0.5);', - ' if ( nsteps < 1 )', - ' discard;', - - // Get starting location and step vector in texture coordinates - ' vec3 step = ((v_position - front) / u_size) / float(nsteps);', - ' vec3 start_loc = front / u_size;', - - // For testing: show the number of steps. This helps to establish - // whether the rays are correctly oriented - //'gl_FragColor = vec4(0.0, float(nsteps) / 1.0 / u_size.x, 1.0, 1.0);', - //'return;', - - ' if (u_renderstyle == 0)', - ' cast_mip(start_loc, step, nsteps, view_ray);', - ' else if (u_renderstyle == 1)', - ' cast_iso(start_loc, step, nsteps, view_ray);', - - ' if (gl_FragColor.a < 0.05)', - ' discard;', - ' }', - - - ' float sample1(vec3 texcoords) {', - ' /* Sample float value from a 3D texture. Assumes intensity data. */', - ' return texture(u_data, texcoords.xyz).r;', - ' }', - - - ' vec4 apply_colormap(float val) {', - ' val = (val - u_clim[0]) / (u_clim[1] - u_clim[0]);', - ' return texture2D(u_cmdata, vec2(val, 0.5));', - ' }', - - - ' void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {', - - ' float max_val = -1e6;', - ' int max_i = 100;', - ' vec3 loc = start_loc;', - - // Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with - // non-constant expression. So we use a hard-coded max, and an additional condition - // inside the loop. - ' for (int iter=0; iter= nsteps)', - ' break;', - // Sample from the 3D texture - ' float val = sample1(loc);', - // Apply MIP operation - ' if (val > max_val) {', - ' max_val = val;', - ' max_i = iter;', - ' }', - // Advance location deeper into the volume - ' loc += step;', - ' }', - - // Refine location, gives crispier images - ' vec3 iloc = start_loc + step * (float(max_i) - 0.5);', - ' vec3 istep = step / float(REFINEMENT_STEPS);', - ' for (int i=0; i= nsteps)', - ' break;', - - // Sample from the 3D texture - ' float val = sample1(loc);', - - ' if (val > low_threshold) {', - // Take the last interval in smaller steps - ' vec3 iloc = loc - 0.5 * step;', - ' vec3 istep = step / float(REFINEMENT_STEPS);', - ' for (int i=0; i u_renderthreshold) {', - ' gl_FragColor = add_lighting(val, iloc, dstep, view_ray);', - ' return;', - ' }', - ' iloc += istep;', - ' }', - ' }', - - // Advance location deeper into the volume - ' loc += step;', - ' }', - ' }', - - - ' vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray)', - ' {', - // Calculate color by incorporating lighting - - // View direction - ' vec3 V = normalize(view_ray);', - - // calculate normal vector from gradient - ' vec3 N;', - ' float val1, val2;', - ' val1 = sample1(loc + vec3(-step[0], 0.0, 0.0));', - ' val2 = sample1(loc + vec3(+step[0], 0.0, 0.0));', - ' N[0] = val1 - val2;', - ' val = max(max(val1, val2), val);', - ' val1 = sample1(loc + vec3(0.0, -step[1], 0.0));', - ' val2 = sample1(loc + vec3(0.0, +step[1], 0.0));', - ' N[1] = val1 - val2;', - ' val = max(max(val1, val2), val);', - ' val1 = sample1(loc + vec3(0.0, 0.0, -step[2]));', - ' val2 = sample1(loc + vec3(0.0, 0.0, +step[2]));', - ' N[2] = val1 - val2;', - ' val = max(max(val1, val2), val);', - - ' float gm = length(N); // gradient magnitude', - ' N = normalize(N);', - - // Flip normal so it points towards viewer - ' float Nselect = float(dot(N, V) > 0.0);', - ' N = (2.0 * Nselect - 1.0) * N; // == Nselect * N - (1.0-Nselect)*N;', - - // Init colors - ' vec4 ambient_color = vec4(0.0, 0.0, 0.0, 0.0);', - ' vec4 diffuse_color = vec4(0.0, 0.0, 0.0, 0.0);', - ' vec4 specular_color = vec4(0.0, 0.0, 0.0, 0.0);', - - // note: could allow multiple lights - ' for (int i=0; i<1; i++)', - ' {', + + vertexShader: /* glsl */` + + varying vec4 v_nearpos; + varying vec4 v_farpos; + varying vec3 v_position; + + void main() { + // Prepare transforms to map to "camera view". See also: + // https://threejs.org/docs/#api/renderers/webgl/WebGLProgram + mat4 viewtransformf = modelViewMatrix; + mat4 viewtransformi = inverse(modelViewMatrix); + + // Project local vertex coordinate to camera position. Then do a step + // backward (in cam coords) to the near clipping plane, and project back. Do + // the same for the far clipping plane. This gives us all the information we + // need to calculate the ray and truncate it to the viewing cone. + vec4 position4 = vec4(position, 1.0); + vec4 pos_in_cam = viewtransformf * position4; + + // Intersection of ray and near clipping plane (z = -1 in clip coords) + pos_in_cam.z = -pos_in_cam.w; + v_nearpos = viewtransformi * pos_in_cam; + + // Intersection of ray and far clipping plane (z = +1 in clip coords) + pos_in_cam.z = pos_in_cam.w; + v_farpos = viewtransformi * pos_in_cam; + + // Set varyings and output pos + v_position = position; + gl_Position = projectionMatrix * viewMatrix * modelMatrix * position4; + }`, + + fragmentShader: /* glsl */` + + precision highp float; + precision mediump sampler3D; + + uniform vec3 u_size; + uniform int u_renderstyle; + uniform float u_renderthreshold; + uniform vec2 u_clim; + + uniform sampler3D u_data; + uniform sampler2D u_cmdata; + + varying vec3 v_position; + varying vec4 v_nearpos; + varying vec4 v_farpos; + + // The maximum distance through our rendering volume is sqrt(3). + const int MAX_STEPS = 887; // 887 for 512^3, 1774 for 1024^3 + const int REFINEMENT_STEPS = 4; + const float relative_step_size = 1.0; + const vec4 ambient_color = vec4(0.2, 0.4, 0.2, 1.0); + const vec4 diffuse_color = vec4(0.8, 0.2, 0.2, 1.0); + const vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0); + const float shininess = 40.0; + + void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray); + void cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray); + + float sample1(vec3 texcoords); + vec4 apply_colormap(float val); + vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray); + + + void main() { + // Normalize clipping plane info + vec3 farpos = v_farpos.xyz / v_farpos.w; + vec3 nearpos = v_nearpos.xyz / v_nearpos.w; + + // Calculate unit vector pointing in the view direction through this fragment. + vec3 view_ray = normalize(nearpos.xyz - farpos.xyz); + + // Compute the (negative) distance to the front surface or near clipping plane. + // v_position is the back face of the cuboid, so the initial distance calculated in the dot + // product below is the distance from near clip plane to the back of the cuboid + float distance = dot(nearpos - v_position, view_ray); + distance = max(distance, min((-0.5 - v_position.x) / view_ray.x, + (u_size.x - 0.5 - v_position.x) / view_ray.x)); + distance = max(distance, min((-0.5 - v_position.y) / view_ray.y, + (u_size.y - 0.5 - v_position.y) / view_ray.y)); + distance = max(distance, min((-0.5 - v_position.z) / view_ray.z, + (u_size.z - 0.5 - v_position.z) / view_ray.z)); + + // Now we have the starting position on the front surface + vec3 front = v_position + view_ray * distance; + + // Decide how many steps to take + int nsteps = int(-distance / relative_step_size + 0.5); + if ( nsteps < 1 ) + discard; + + // Get starting location and step vector in texture coordinates + vec3 step = ((v_position - front) / u_size) / float(nsteps); + vec3 start_loc = front / u_size; + + // For testing: show the number of steps. This helps to establish + // whether the rays are correctly oriented + //'gl_FragColor = vec4(0.0, float(nsteps) / 1.0 / u_size.x, 1.0, 1.0); + //'return; + + if (u_renderstyle == 0) + cast_mip(start_loc, step, nsteps, view_ray); + else if (u_renderstyle == 1) + cast_iso(start_loc, step, nsteps, view_ray); + + if (gl_FragColor.a < 0.05) + discard; + } + + + float sample1(vec3 texcoords) { + /* Sample float value from a 3D texture. Assumes intensity data. */ + return texture(u_data, texcoords.xyz).r; + } + + + vec4 apply_colormap(float val) { + val = (val - u_clim[0]) / (u_clim[1] - u_clim[0]); + return texture2D(u_cmdata, vec2(val, 0.5)); + } + + + void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) { + + float max_val = -1e6; + int max_i = 100; + vec3 loc = start_loc; + + // Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with + // non-constant expression. So we use a hard-coded max, and an additional condition + // inside the loop. + for (int iter=0; iter= nsteps) + break; + // Sample from the 3D texture + float val = sample1(loc); + // Apply MIP operation + if (val > max_val) { + max_val = val; + max_i = iter; + } + // Advance location deeper into the volume + loc += step; + } + + // Refine location, gives crispier images + vec3 iloc = start_loc + step * (float(max_i) - 0.5); + vec3 istep = step / float(REFINEMENT_STEPS); + for (int i=0; i= nsteps) + break; + + // Sample from the 3D texture + float val = sample1(loc); + + if (val > low_threshold) { + // Take the last interval in smaller steps + vec3 iloc = loc - 0.5 * step; + vec3 istep = step / float(REFINEMENT_STEPS); + for (int i=0; i u_renderthreshold) { + gl_FragColor = add_lighting(val, iloc, dstep, view_ray); + return; + } + iloc += istep; + } + } + + // Advance location deeper into the volume + loc += step; + } + } + + + vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray) + { + // Calculate color by incorporating lighting + + // View direction + vec3 V = normalize(view_ray); + + // calculate normal vector from gradient + vec3 N; + float val1, val2; + val1 = sample1(loc + vec3(-step[0], 0.0, 0.0)); + val2 = sample1(loc + vec3(+step[0], 0.0, 0.0)); + N[0] = val1 - val2; + val = max(max(val1, val2), val); + val1 = sample1(loc + vec3(0.0, -step[1], 0.0)); + val2 = sample1(loc + vec3(0.0, +step[1], 0.0)); + N[1] = val1 - val2; + val = max(max(val1, val2), val); + val1 = sample1(loc + vec3(0.0, 0.0, -step[2])); + val2 = sample1(loc + vec3(0.0, 0.0, +step[2])); + N[2] = val1 - val2; + val = max(max(val1, val2), val); + + float gm = length(N); // gradient magnitude + N = normalize(N); + + // Flip normal so it points towards viewer + float Nselect = float(dot(N, V) > 0.0); + N = (2.0 * Nselect - 1.0) * N; // == Nselect * N - (1.0-Nselect)*N; + + // Init colors + vec4 ambient_color = vec4(0.0, 0.0, 0.0, 0.0); + vec4 diffuse_color = vec4(0.0, 0.0, 0.0, 0.0); + vec4 specular_color = vec4(0.0, 0.0, 0.0, 0.0); + + // note: could allow multiple lights + for (int i=0; i<1; i++) + { // Get light direction (make sure to prevent zero devision) - ' vec3 L = normalize(view_ray); //lightDirs[i];', - ' float lightEnabled = float( length(L) > 0.0 );', - ' L = normalize(L + (1.0 - lightEnabled));', - - // Calculate lighting properties - ' float lambertTerm = clamp(dot(N, L), 0.0, 1.0);', - ' vec3 H = normalize(L+V); // Halfway vector', - ' float specularTerm = pow(max(dot(H, N), 0.0), shininess);', - - // Calculate mask - ' float mask1 = lightEnabled;', - - // Calculate colors - ' ambient_color += mask1 * ambient_color; // * gl_LightSource[i].ambient;', - ' diffuse_color += mask1 * lambertTerm;', - ' specular_color += mask1 * specularTerm * specular_color;', - ' }', - - // Calculate final color by componing different components - ' vec4 final_color;', - ' vec4 color = apply_colormap(val);', - ' final_color = color * (ambient_color + diffuse_color) + specular_color;', - ' final_color.a = color.a;', - ' return final_color;', - ' }', - ].join( '\n' ) + vec3 L = normalize(view_ray); //lightDirs[i]; + float lightEnabled = float( length(L) > 0.0 ); + L = normalize(L + (1.0 - lightEnabled)); + + // Calculate lighting properties + float lambertTerm = clamp(dot(N, L), 0.0, 1.0); + vec3 H = normalize(L+V); // Halfway vector + float specularTerm = pow(max(dot(H, N), 0.0), shininess); + + // Calculate mask + float mask1 = lightEnabled; + + // Calculate colors + ambient_color += mask1 * ambient_color; // * gl_LightSource[i].ambient; + diffuse_color += mask1 * lambertTerm; + specular_color += mask1 * specularTerm * specular_color; + } + + // Calculate final color by componing different components + vec4 final_color; + vec4 color = apply_colormap(val); + final_color = color * (ambient_color + diffuse_color) + specular_color; + final_color.a = color.a; + return final_color; + }` + }; export { VolumeRenderShader1 }; diff --git a/examples/jsm/shaders/WaterRefractionShader.js b/examples/jsm/shaders/WaterRefractionShader.js index d23372d2eb98f4..84c669d85f33e8 100644 --- a/examples/jsm/shaders/WaterRefractionShader.js +++ b/examples/jsm/shaders/WaterRefractionShader.js @@ -1,4 +1,4 @@ -var WaterRefractionShader = { +const WaterRefractionShader = { uniforms: { @@ -24,70 +24,67 @@ var WaterRefractionShader = { }, - vertexShader: [ + vertexShader: /* glsl */` - 'uniform mat4 textureMatrix;', + uniform mat4 textureMatrix; - 'varying vec2 vUv;', - 'varying vec4 vUvRefraction;', + varying vec2 vUv; + varying vec4 vUvRefraction; - 'void main() {', + void main() { - ' vUv = uv;', + vUv = uv; - ' vUvRefraction = textureMatrix * vec4( position, 1.0 );', + vUvRefraction = textureMatrix * vec4( position, 1.0 ); - ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - '}' + }`, - ].join( '\n' ), + fragmentShader: /* glsl */` - fragmentShader: [ + uniform vec3 color; + uniform float time; + uniform sampler2D tDiffuse; + uniform sampler2D tDudv; - 'uniform vec3 color;', - 'uniform float time;', - 'uniform sampler2D tDiffuse;', - 'uniform sampler2D tDudv;', + varying vec2 vUv; + varying vec4 vUvRefraction; - 'varying vec2 vUv;', - 'varying vec4 vUvRefraction;', + float blendOverlay( float base, float blend ) { - 'float blendOverlay( float base, float blend ) {', + return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) ); - ' return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );', - - '}', + } - 'vec3 blendOverlay( vec3 base, vec3 blend ) {', + vec3 blendOverlay( vec3 base, vec3 blend ) { - ' return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ),blendOverlay( base.b, blend.b ) );', + return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ),blendOverlay( base.b, blend.b ) ); - '}', + } - 'void main() {', + void main() { - ' float waveStrength = 0.1;', - ' float waveSpeed = 0.03;', + float waveStrength = 0.1; + float waveSpeed = 0.03; - // simple distortion (ripple) via dudv map (see https://www.youtube.com/watch?v=6B7IF6GOu7s) + // simple distortion (ripple) via dudv map (see https://www.youtube.com/watch?v=6B7IF6GOu7s) - ' vec2 distortedUv = texture2D( tDudv, vec2( vUv.x + time * waveSpeed, vUv.y ) ).rg * waveStrength;', - ' distortedUv = vUv.xy + vec2( distortedUv.x, distortedUv.y + time * waveSpeed );', - ' vec2 distortion = ( texture2D( tDudv, distortedUv ).rg * 2.0 - 1.0 ) * waveStrength;', + vec2 distortedUv = texture2D( tDudv, vec2( vUv.x + time * waveSpeed, vUv.y ) ).rg * waveStrength; + distortedUv = vUv.xy + vec2( distortedUv.x, distortedUv.y + time * waveSpeed ); + vec2 distortion = ( texture2D( tDudv, distortedUv ).rg * 2.0 - 1.0 ) * waveStrength; - // new uv coords + // new uv coords - ' vec4 uv = vec4( vUvRefraction );', - ' uv.xy += distortion;', + vec4 uv = vec4( vUvRefraction ); + uv.xy += distortion; - ' vec4 base = texture2DProj( tDiffuse, uv );', + vec4 base = texture2DProj( tDiffuse, uv ); - ' gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );', + gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 ); - '}' + }` - ].join( '\n' ) }; export { WaterRefractionShader }; diff --git a/examples/jsm/utils/BufferGeometryUtils.js b/examples/jsm/utils/BufferGeometryUtils.js index 1c5e570afb3821..4962fabeaaeeff 100644 --- a/examples/jsm/utils/BufferGeometryUtils.js +++ b/examples/jsm/utils/BufferGeometryUtils.js @@ -10,40 +10,40 @@ import { Vector3 } from '../../../build/three.module.js'; -var BufferGeometryUtils = { +class BufferGeometryUtils { - computeTangents: function ( geometry ) { + static computeTangents( geometry ) { geometry.computeTangents(); console.warn( 'THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead.' ); - }, + } /** * @param {Array} geometries * @param {Boolean} useGroups * @return {BufferGeometry} */ - mergeBufferGeometries: function ( geometries, useGroups ) { + static mergeBufferGeometries( geometries, useGroups = false ) { - var isIndexed = geometries[ 0 ].index !== null; + const isIndexed = geometries[ 0 ].index !== null; - var attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) ); - var morphAttributesUsed = new Set( Object.keys( geometries[ 0 ].morphAttributes ) ); + const attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) ); + const morphAttributesUsed = new Set( Object.keys( geometries[ 0 ].morphAttributes ) ); - var attributes = {}; - var morphAttributes = {}; + const attributes = {}; + const morphAttributes = {}; - var morphTargetsRelative = geometries[ 0 ].morphTargetsRelative; + const morphTargetsRelative = geometries[ 0 ].morphTargetsRelative; - var mergedGeometry = new BufferGeometry(); + const mergedGeometry = new BufferGeometry(); - var offset = 0; + let offset = 0; - for ( var i = 0; i < geometries.length; ++ i ) { + for ( let i = 0; i < geometries.length; ++ i ) { - var geometry = geometries[ i ]; - var attributesCount = 0; + const geometry = geometries[ i ]; + let attributesCount = 0; // ensure that all geometries are indexed, or none @@ -56,7 +56,7 @@ var BufferGeometryUtils = { // gather attributes, exit early if they're different - for ( var name in geometry.attributes ) { + for ( const name in geometry.attributes ) { if ( ! attributesUsed.has( name ) ) { @@ -91,7 +91,7 @@ var BufferGeometryUtils = { } - for ( var name in geometry.morphAttributes ) { + for ( const name in geometry.morphAttributes ) { if ( ! morphAttributesUsed.has( name ) ) { @@ -113,7 +113,7 @@ var BufferGeometryUtils = { if ( useGroups ) { - var count; + let count; if ( isIndexed ) { @@ -142,14 +142,14 @@ var BufferGeometryUtils = { if ( isIndexed ) { - var indexOffset = 0; - var mergedIndex = []; + let indexOffset = 0; + const mergedIndex = []; - for ( var i = 0; i < geometries.length; ++ i ) { + for ( let i = 0; i < geometries.length; ++ i ) { - var index = geometries[ i ].index; + const index = geometries[ i ].index; - for ( var j = 0; j < index.count; ++ j ) { + for ( let j = 0; j < index.count; ++ j ) { mergedIndex.push( index.getX( j ) + indexOffset ); @@ -165,9 +165,9 @@ var BufferGeometryUtils = { // merge attributes - for ( var name in attributes ) { + for ( const name in attributes ) { - var mergedAttribute = this.mergeBufferAttributes( attributes[ name ] ); + const mergedAttribute = this.mergeBufferAttributes( attributes[ name ] ); if ( ! mergedAttribute ) { @@ -182,26 +182,26 @@ var BufferGeometryUtils = { // merge morph attributes - for ( var name in morphAttributes ) { + for ( const name in morphAttributes ) { - var numMorphTargets = morphAttributes[ name ][ 0 ].length; + const numMorphTargets = morphAttributes[ name ][ 0 ].length; if ( numMorphTargets === 0 ) break; mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {}; mergedGeometry.morphAttributes[ name ] = []; - for ( var i = 0; i < numMorphTargets; ++ i ) { + for ( let i = 0; i < numMorphTargets; ++ i ) { - var morphAttributesToMerge = []; + const morphAttributesToMerge = []; - for ( var j = 0; j < morphAttributes[ name ].length; ++ j ) { + for ( let j = 0; j < morphAttributes[ name ].length; ++ j ) { morphAttributesToMerge.push( morphAttributes[ name ][ j ][ i ] ); } - var mergedMorphAttribute = this.mergeBufferAttributes( morphAttributesToMerge ); + const mergedMorphAttribute = this.mergeBufferAttributes( morphAttributesToMerge ); if ( ! mergedMorphAttribute ) { @@ -218,22 +218,22 @@ var BufferGeometryUtils = { return mergedGeometry; - }, + } /** * @param {Array} attributes * @return {BufferAttribute} */ - mergeBufferAttributes: function ( attributes ) { + static mergeBufferAttributes( attributes ) { - var TypedArray; - var itemSize; - var normalized; - var arrayLength = 0; + let TypedArray; + let itemSize; + let normalized; + let arrayLength = 0; - for ( var i = 0; i < attributes.length; ++ i ) { + for ( let i = 0; i < attributes.length; ++ i ) { - var attribute = attributes[ i ]; + const attribute = attributes[ i ]; if ( attribute.isInterleavedBufferAttribute ) { @@ -270,10 +270,10 @@ var BufferGeometryUtils = { } - var array = new TypedArray( arrayLength ); - var offset = 0; + const array = new TypedArray( arrayLength ); + let offset = 0; - for ( var i = 0; i < attributes.length; ++ i ) { + for ( let i = 0; i < attributes.length; ++ i ) { array.set( attributes[ i ].array, offset ); @@ -283,24 +283,24 @@ var BufferGeometryUtils = { return new BufferAttribute( array, itemSize, normalized ); - }, + } /** * @param {Array} attributes * @return {Array} */ - interleaveAttributes: function ( attributes ) { + static interleaveAttributes( attributes ) { // Interleaves the provided attributes into an InterleavedBuffer and returns // a set of InterleavedBufferAttributes for each attribute - var TypedArray; - var arrayLength = 0; - var stride = 0; + let TypedArray; + let arrayLength = 0; + let stride = 0; // calculate the the length and type of the interleavedBuffer - for ( var i = 0, l = attributes.length; i < l; ++ i ) { + for ( let i = 0, l = attributes.length; i < l; ++ i ) { - var attribute = attributes[ i ]; + const attribute = attributes[ i ]; if ( TypedArray === undefined ) TypedArray = attribute.array.constructor; if ( TypedArray !== attribute.array.constructor ) { @@ -316,27 +316,27 @@ var BufferGeometryUtils = { } // Create the set of buffer attributes - var interleavedBuffer = new InterleavedBuffer( new TypedArray( arrayLength ), stride ); - var offset = 0; - var res = []; - var getters = [ 'getX', 'getY', 'getZ', 'getW' ]; - var setters = [ 'setX', 'setY', 'setZ', 'setW' ]; - - for ( var j = 0, l = attributes.length; j < l; j ++ ) { - - var attribute = attributes[ j ]; - var itemSize = attribute.itemSize; - var count = attribute.count; - var iba = new InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, attribute.normalized ); + const interleavedBuffer = new InterleavedBuffer( new TypedArray( arrayLength ), stride ); + let offset = 0; + const res = []; + const getters = [ 'getX', 'getY', 'getZ', 'getW' ]; + const setters = [ 'setX', 'setY', 'setZ', 'setW' ]; + + for ( let j = 0, l = attributes.length; j < l; j ++ ) { + + const attribute = attributes[ j ]; + const itemSize = attribute.itemSize; + const count = attribute.count; + const iba = new InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, attribute.normalized ); res.push( iba ); offset += itemSize; // Move the data for each attribute into the new interleavedBuffer // at the appropriate offset - for ( var c = 0; c < count; c ++ ) { + for ( let c = 0; c < count; c ++ ) { - for ( var k = 0; k < itemSize; k ++ ) { + for ( let k = 0; k < itemSize; k ++ ) { iba[ setters[ k ] ]( c, attribute[ getters[ k ] ]( c ) ); @@ -348,65 +348,65 @@ var BufferGeometryUtils = { return res; - }, + } /** * @param {Array} geometry * @return {number} */ - estimateBytesUsed: function ( geometry ) { + static estimateBytesUsed( geometry ) { // Return the estimated memory used by this geometry in bytes // Calculate using itemSize, count, and BYTES_PER_ELEMENT to account // for InterleavedBufferAttributes. - var mem = 0; - for ( var name in geometry.attributes ) { + let mem = 0; + for ( const name in geometry.attributes ) { - var attr = geometry.getAttribute( name ); + const attr = geometry.getAttribute( name ); mem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT; } - var indices = geometry.getIndex(); + const indices = geometry.getIndex(); mem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0; return mem; - }, + } /** * @param {BufferGeometry} geometry * @param {number} tolerance * @return {BufferGeometry>} */ - mergeVertices: function ( geometry, tolerance = 1e-4 ) { + static mergeVertices( geometry, tolerance = 1e-4 ) { tolerance = Math.max( tolerance, Number.EPSILON ); // Generate an index buffer if the geometry doesn't have one, or optimize it // if it's already available. - var hashToIndex = {}; - var indices = geometry.getIndex(); - var positions = geometry.getAttribute( 'position' ); - var vertexCount = indices ? indices.count : positions.count; + const hashToIndex = {}; + const indices = geometry.getIndex(); + const positions = geometry.getAttribute( 'position' ); + const vertexCount = indices ? indices.count : positions.count; // next value for triangle indices - var nextIndex = 0; + let nextIndex = 0; // attributes and new attribute arrays - var attributeNames = Object.keys( geometry.attributes ); - var attrArrays = {}; - var morphAttrsArrays = {}; - var newIndices = []; - var getters = [ 'getX', 'getY', 'getZ', 'getW' ]; + const attributeNames = Object.keys( geometry.attributes ); + const attrArrays = {}; + const morphAttrsArrays = {}; + const newIndices = []; + const getters = [ 'getX', 'getY', 'getZ', 'getW' ]; // initialize the arrays - for ( var i = 0, l = attributeNames.length; i < l; i ++ ) { + for ( let i = 0, l = attributeNames.length; i < l; i ++ ) { - var name = attributeNames[ i ]; + const name = attributeNames[ i ]; attrArrays[ name ] = []; - var morphAttr = geometry.morphAttributes[ name ]; + const morphAttr = geometry.morphAttributes[ name ]; if ( morphAttr ) { morphAttrsArrays[ name ] = new Array( morphAttr.length ).fill().map( () => [] ); @@ -416,21 +416,21 @@ var BufferGeometryUtils = { } // convert the error tolerance to an amount of decimal places to truncate to - var decimalShift = Math.log10( 1 / tolerance ); - var shiftMultiplier = Math.pow( 10, decimalShift ); - for ( var i = 0; i < vertexCount; i ++ ) { + const decimalShift = Math.log10( 1 / tolerance ); + const shiftMultiplier = Math.pow( 10, decimalShift ); + for ( let i = 0; i < vertexCount; i ++ ) { - var index = indices ? indices.getX( i ) : i; + const index = indices ? indices.getX( i ) : i; // Generate a hash for the vertex attributes at the current index 'i' - var hash = ''; - for ( var j = 0, l = attributeNames.length; j < l; j ++ ) { + let hash = ''; + for ( let j = 0, l = attributeNames.length; j < l; j ++ ) { - var name = attributeNames[ j ]; - var attribute = geometry.getAttribute( name ); - var itemSize = attribute.itemSize; + const name = attributeNames[ j ]; + const attribute = geometry.getAttribute( name ); + const itemSize = attribute.itemSize; - for ( var k = 0; k < itemSize; k ++ ) { + for ( let k = 0; k < itemSize; k ++ ) { // double tilde truncates the decimal value hash += `${ ~ ~ ( attribute[ getters[ k ] ]( index ) * shiftMultiplier ) },`; @@ -448,23 +448,23 @@ var BufferGeometryUtils = { } else { // copy data to the new index in the attribute arrays - for ( var j = 0, l = attributeNames.length; j < l; j ++ ) { + for ( let j = 0, l = attributeNames.length; j < l; j ++ ) { - var name = attributeNames[ j ]; - var attribute = geometry.getAttribute( name ); - var morphAttr = geometry.morphAttributes[ name ]; - var itemSize = attribute.itemSize; - var newarray = attrArrays[ name ]; - var newMorphArrays = morphAttrsArrays[ name ]; + const name = attributeNames[ j ]; + const attribute = geometry.getAttribute( name ); + const morphAttr = geometry.morphAttributes[ name ]; + const itemSize = attribute.itemSize; + const newarray = attrArrays[ name ]; + const newMorphArrays = morphAttrsArrays[ name ]; - for ( var k = 0; k < itemSize; k ++ ) { + for ( let k = 0; k < itemSize; k ++ ) { - var getterFunc = getters[ k ]; + const getterFunc = getters[ k ]; newarray.push( attribute[ getterFunc ]( index ) ); if ( morphAttr ) { - for ( var m = 0, ml = morphAttr.length; m < ml; m ++ ) { + for ( let m = 0, ml = morphAttr.length; m < ml; m ++ ) { newMorphArrays[ m ].push( morphAttr[ m ][ getterFunc ]( index ) ); @@ -487,25 +487,25 @@ var BufferGeometryUtils = { // Generate typed arrays from new attribute arrays and update // the attributeBuffers const result = geometry.clone(); - for ( var i = 0, l = attributeNames.length; i < l; i ++ ) { + for ( let i = 0, l = attributeNames.length; i < l; i ++ ) { - var name = attributeNames[ i ]; - var oldAttribute = geometry.getAttribute( name ); + const name = attributeNames[ i ]; + const oldAttribute = geometry.getAttribute( name ); - var buffer = new oldAttribute.array.constructor( attrArrays[ name ] ); - var attribute = new BufferAttribute( buffer, oldAttribute.itemSize, oldAttribute.normalized ); + const buffer = new oldAttribute.array.constructor( attrArrays[ name ] ); + const attribute = new BufferAttribute( buffer, oldAttribute.itemSize, oldAttribute.normalized ); result.setAttribute( name, attribute ); // Update the attribute arrays if ( name in morphAttrsArrays ) { - for ( var j = 0; j < morphAttrsArrays[ name ].length; j ++ ) { + for ( let j = 0; j < morphAttrsArrays[ name ].length; j ++ ) { - var oldMorphAttribute = geometry.morphAttributes[ name ][ j ]; + const oldMorphAttribute = geometry.morphAttributes[ name ][ j ]; - var buffer = new oldMorphAttribute.array.constructor( morphAttrsArrays[ name ][ j ] ); - var morphAttribute = new BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized ); + const buffer = new oldMorphAttribute.array.constructor( morphAttrsArrays[ name ][ j ] ); + const morphAttribute = new BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized ); result.morphAttributes[ name ][ j ] = morphAttribute; } @@ -520,14 +520,14 @@ var BufferGeometryUtils = { return result; - }, + } /** * @param {BufferGeometry} geometry * @param {number} drawMode * @return {BufferGeometry>} */ - toTrianglesDrawMode: function ( geometry, drawMode ) { + static toTrianglesDrawMode( geometry, drawMode ) { if ( drawMode === TrianglesDrawMode ) { @@ -538,19 +538,19 @@ var BufferGeometryUtils = { if ( drawMode === TriangleFanDrawMode || drawMode === TriangleStripDrawMode ) { - var index = geometry.getIndex(); + let index = geometry.getIndex(); // generate index if not present if ( index === null ) { - var indices = []; + const indices = []; - var position = geometry.getAttribute( 'position' ); + const position = geometry.getAttribute( 'position' ); if ( position !== undefined ) { - for ( var i = 0; i < position.count; i ++ ) { + for ( let i = 0; i < position.count; i ++ ) { indices.push( i ); @@ -570,14 +570,14 @@ var BufferGeometryUtils = { // - var numberOfTriangles = index.count - 2; - var newIndices = []; + const numberOfTriangles = index.count - 2; + const newIndices = []; if ( drawMode === TriangleFanDrawMode ) { // gl.TRIANGLE_FAN - for ( var i = 1; i <= numberOfTriangles; i ++ ) { + for ( let i = 1; i <= numberOfTriangles; i ++ ) { newIndices.push( index.getX( 0 ) ); newIndices.push( index.getX( i ) ); @@ -589,7 +589,7 @@ var BufferGeometryUtils = { // gl.TRIANGLE_STRIP - for ( var i = 0; i < numberOfTriangles; i ++ ) { + for ( let i = 0; i < numberOfTriangles; i ++ ) { if ( i % 2 === 0 ) { @@ -617,7 +617,7 @@ var BufferGeometryUtils = { // build final geometry - var newGeometry = geometry.clone(); + const newGeometry = geometry.clone(); newGeometry.setIndex( newIndices ); newGeometry.clearGroups(); @@ -630,7 +630,7 @@ var BufferGeometryUtils = { } - }, + } /** * Calculates the morphed attributes of a morphed/skinned BufferGeometry. @@ -638,7 +638,7 @@ var BufferGeometryUtils = { * @param {Mesh | Line | Points} object An instance of Mesh, Line or Points. * @return {Object} An Object with original position/normal attributes and morphed ones. */ - computeMorphedAttributes: function ( object ) { + static computeMorphedAttributes( object ) { if ( object.geometry.isBufferGeometry !== true ) { @@ -647,17 +647,17 @@ var BufferGeometryUtils = { } - var _vA = new Vector3(); - var _vB = new Vector3(); - var _vC = new Vector3(); + const _vA = new Vector3(); + const _vB = new Vector3(); + const _vC = new Vector3(); - var _tempA = new Vector3(); - var _tempB = new Vector3(); - var _tempC = new Vector3(); + const _tempA = new Vector3(); + const _tempB = new Vector3(); + const _tempC = new Vector3(); - var _morphA = new Vector3(); - var _morphB = new Vector3(); - var _morphC = new Vector3(); + const _morphA = new Vector3(); + const _morphB = new Vector3(); + const _morphC = new Vector3(); function _calculateMorphedAttributeData( object, @@ -675,7 +675,7 @@ var BufferGeometryUtils = { _vB.fromBufferAttribute( attribute, b ); _vC.fromBufferAttribute( attribute, c ); - var morphInfluences = object.morphTargetInfluences; + const morphInfluences = object.morphTargetInfluences; if ( material.morphTargets && morphAttribute && morphInfluences ) { @@ -683,10 +683,10 @@ var BufferGeometryUtils = { _morphB.set( 0, 0, 0 ); _morphC.set( 0, 0, 0 ); - for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) { + for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { - var influence = morphInfluences[ i ]; - var morph = morphAttribute[ i ]; + const influence = morphInfluences[ i ]; + const morph = morphAttribute[ i ]; if ( influence === 0 ) continue; @@ -736,25 +736,25 @@ var BufferGeometryUtils = { } - var geometry = object.geometry; - var material = object.material; + const geometry = object.geometry; + const material = object.material; - var a, b, c; - var index = geometry.index; - var positionAttribute = geometry.attributes.position; - var morphPosition = geometry.morphAttributes.position; - var morphTargetsRelative = geometry.morphTargetsRelative; - var normalAttribute = geometry.attributes.normal; - var morphNormal = geometry.morphAttributes.position; + let a, b, c; + const index = geometry.index; + const positionAttribute = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; + const normalAttribute = geometry.attributes.normal; + const morphNormal = geometry.morphAttributes.position; - var groups = geometry.groups; - var drawRange = geometry.drawRange; - var i, j, il, jl; - var group, groupMaterial; - var start, end; + const groups = geometry.groups; + const drawRange = geometry.drawRange; + let i, j, il, jl; + let group, groupMaterial; + let start, end; - var modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize ); - var modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize ); + const modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize ); + const modifiedNormal = new Float32Array( normalAttribute.count * normalAttribute.itemSize ); if ( index !== null ) { @@ -916,8 +916,8 @@ var BufferGeometryUtils = { } - var morphedPositionAttribute = new Float32BufferAttribute( modifiedPosition, 3 ); - var morphedNormalAttribute = new Float32BufferAttribute( modifiedNormal, 3 ); + const morphedPositionAttribute = new Float32BufferAttribute( modifiedPosition, 3 ); + const morphedNormalAttribute = new Float32BufferAttribute( modifiedNormal, 3 ); return { @@ -930,6 +930,6 @@ var BufferGeometryUtils = { } -}; +} export { BufferGeometryUtils }; diff --git a/examples/jsm/utils/GeometryCompressionUtils.js b/examples/jsm/utils/GeometryCompressionUtils.js index 4941b38d69febb..0004ac71aa1b33 100644 --- a/examples/jsm/utils/GeometryCompressionUtils.js +++ b/examples/jsm/utils/GeometryCompressionUtils.js @@ -16,7 +16,7 @@ import { Vector3 } from '../../../build/three.module.js'; -var GeometryCompressionUtils = { +class GeometryCompressionUtils { /** * Make the input mesh.geometry's normal attribute encoded and compressed by 3 different methods. @@ -26,7 +26,7 @@ var GeometryCompressionUtils = { * @param {String} encodeMethod "DEFAULT" || "OCT1Byte" || "OCT2Byte" || "ANGLES" * */ - compressNormals: function ( mesh, encodeMethod ) { + static compressNormals( mesh, encodeMethod ) { if ( ! mesh.geometry ) { @@ -61,7 +61,7 @@ var GeometryCompressionUtils = { for ( let idx = 0; idx < array.length; idx += 3 ) { - const encoded = this.EncodingFuncs.defaultEncode( array[ idx ], array[ idx + 1 ], array[ idx + 2 ], 1 ); + const encoded = EncodingFuncs.defaultEncode( array[ idx ], array[ idx + 1 ], array[ idx + 2 ], 1 ); result[ idx + 0 ] = encoded[ 0 ]; result[ idx + 1 ] = encoded[ 1 ]; @@ -84,7 +84,7 @@ var GeometryCompressionUtils = { for ( let idx = 0; idx < array.length; idx += 3 ) { - const encoded = this.EncodingFuncs.octEncodeBest( array[ idx ], array[ idx + 1 ], array[ idx + 2 ], 1 ); + const encoded = EncodingFuncs.octEncodeBest( array[ idx ], array[ idx + 1 ], array[ idx + 2 ], 1 ); result[ idx / 3 * 2 + 0 ] = encoded[ 0 ]; result[ idx / 3 * 2 + 1 ] = encoded[ 1 ]; @@ -100,7 +100,7 @@ var GeometryCompressionUtils = { for ( let idx = 0; idx < array.length; idx += 3 ) { - const encoded = this.EncodingFuncs.octEncodeBest( array[ idx ], array[ idx + 1 ], array[ idx + 2 ], 2 ); + const encoded = EncodingFuncs.octEncodeBest( array[ idx ], array[ idx + 1 ], array[ idx + 2 ], 2 ); result[ idx / 3 * 2 + 0 ] = encoded[ 0 ]; result[ idx / 3 * 2 + 1 ] = encoded[ 1 ]; @@ -116,7 +116,7 @@ var GeometryCompressionUtils = { for ( let idx = 0; idx < array.length; idx += 3 ) { - const encoded = this.EncodingFuncs.anglesEncode( array[ idx ], array[ idx + 1 ], array[ idx + 2 ] ); + const encoded = EncodingFuncs.anglesEncode( array[ idx ], array[ idx + 1 ], array[ idx + 2 ] ); result[ idx / 3 * 2 + 0 ] = encoded[ 0 ]; result[ idx / 3 * 2 + 1 ] = encoded[ 1 ]; @@ -167,7 +167,7 @@ var GeometryCompressionUtils = { } - }, + } /** @@ -177,7 +177,7 @@ var GeometryCompressionUtils = { * @param {THREE.Mesh} mesh * */ - compressPositions: function ( mesh ) { + static compressPositions( mesh ) { if ( ! mesh.geometry ) { @@ -204,7 +204,7 @@ var GeometryCompressionUtils = { const array = position.array; const encodingBytes = 2; - const result = this.EncodingFuncs.quantizedEncode( array, encodingBytes ); + const result = EncodingFuncs.quantizedEncode( array, encodingBytes ); const quantized = result.quantized; const decodeMat = result.decodeMat; @@ -230,7 +230,7 @@ var GeometryCompressionUtils = { mesh.material.uniforms.quantizeMatPos.value = decodeMat; mesh.material.uniforms.quantizeMatPos.needsUpdate = true; - }, + } /** * Make the input mesh.geometry's uv attribute encoded and compressed. @@ -239,7 +239,7 @@ var GeometryCompressionUtils = { * @param {THREE.Mesh} mesh * */ - compressUvs: function ( mesh ) { + static compressUvs( mesh ) { if ( ! mesh.geometry ) { @@ -277,7 +277,7 @@ var GeometryCompressionUtils = { for ( let i = 0; i < array.length; i += 2 ) { - const encoded = this.EncodingFuncs.defaultEncode( array[ i ], array[ i + 1 ], 0, 2 ); + const encoded = EncodingFuncs.defaultEncode( array[ i ], array[ i + 1 ], 0, 2 ); result[ i ] = encoded[ 0 ]; result[ i + 1 ] = encoded[ 1 ]; @@ -300,7 +300,7 @@ var GeometryCompressionUtils = { } else { // use quantized encoding method - result = this.EncodingFuncs.quantizedEncodeUV( array, 2 ); + result = EncodingFuncs.quantizedEncodeUV( array, 2 ); mesh.geometry.setAttribute( 'uv', new BufferAttribute( result.quantized, 2 ) ); mesh.geometry.attributes.uv.isPacked = true; @@ -320,348 +320,347 @@ var GeometryCompressionUtils = { } - }, + } - EncodingFuncs: { +} - defaultEncode: function ( x, y, z, bytes ) { +class EncodingFuncs { - if ( bytes == 1 ) { + static defaultEncode( x, y, z, bytes ) { - const tmpx = Math.round( ( x + 1 ) * 0.5 * 255 ); - const tmpy = Math.round( ( y + 1 ) * 0.5 * 255 ); - const tmpz = Math.round( ( z + 1 ) * 0.5 * 255 ); - return new Uint8Array( [ tmpx, tmpy, tmpz ] ); + if ( bytes == 1 ) { - } else if ( bytes == 2 ) { + const tmpx = Math.round( ( x + 1 ) * 0.5 * 255 ); + const tmpy = Math.round( ( y + 1 ) * 0.5 * 255 ); + const tmpz = Math.round( ( z + 1 ) * 0.5 * 255 ); + return new Uint8Array( [ tmpx, tmpy, tmpz ] ); - const tmpx = Math.round( ( x + 1 ) * 0.5 * 65535 ); - const tmpy = Math.round( ( y + 1 ) * 0.5 * 65535 ); - const tmpz = Math.round( ( z + 1 ) * 0.5 * 65535 ); - return new Uint16Array( [ tmpx, tmpy, tmpz ] ); + } else if ( bytes == 2 ) { - } else { + const tmpx = Math.round( ( x + 1 ) * 0.5 * 65535 ); + const tmpy = Math.round( ( y + 1 ) * 0.5 * 65535 ); + const tmpz = Math.round( ( z + 1 ) * 0.5 * 65535 ); + return new Uint16Array( [ tmpx, tmpy, tmpz ] ); - console.error( 'number of bytes must be 1 or 2' ); + } else { - } + console.error( 'number of bytes must be 1 or 2' ); - }, + } - defaultDecode: function ( array, bytes ) { + } - if ( bytes == 1 ) { + static defaultDecode( array, bytes ) { - return [ - ( ( array[ 0 ] / 255 ) * 2.0 ) - 1.0, - ( ( array[ 1 ] / 255 ) * 2.0 ) - 1.0, - ( ( array[ 2 ] / 255 ) * 2.0 ) - 1.0, - ]; + if ( bytes == 1 ) { - } else if ( bytes == 2 ) { + return [ + ( ( array[ 0 ] / 255 ) * 2.0 ) - 1.0, + ( ( array[ 1 ] / 255 ) * 2.0 ) - 1.0, + ( ( array[ 2 ] / 255 ) * 2.0 ) - 1.0, + ]; - return [ - ( ( array[ 0 ] / 65535 ) * 2.0 ) - 1.0, - ( ( array[ 1 ] / 65535 ) * 2.0 ) - 1.0, - ( ( array[ 2 ] / 65535 ) * 2.0 ) - 1.0, - ]; + } else if ( bytes == 2 ) { - } else { + return [ + ( ( array[ 0 ] / 65535 ) * 2.0 ) - 1.0, + ( ( array[ 1 ] / 65535 ) * 2.0 ) - 1.0, + ( ( array[ 2 ] / 65535 ) * 2.0 ) - 1.0, + ]; - console.error( 'number of bytes must be 1 or 2' ); + } else { - } + console.error( 'number of bytes must be 1 or 2' ); - }, + } - // for `Angles` encoding - anglesEncode: function ( x, y, z ) { + } - const normal0 = parseInt( 0.5 * ( 1.0 + Math.atan2( y, x ) / Math.PI ) * 65535 ); - const normal1 = parseInt( 0.5 * ( 1.0 + z ) * 65535 ); - return new Uint16Array( [ normal0, normal1 ] ); + // for `Angles` encoding + static anglesEncode( x, y, z ) { - }, + const normal0 = parseInt( 0.5 * ( 1.0 + Math.atan2( y, x ) / Math.PI ) * 65535 ); + const normal1 = parseInt( 0.5 * ( 1.0 + z ) * 65535 ); + return new Uint16Array( [ normal0, normal1 ] ); - // for `Octahedron` encoding - octEncodeBest: function ( x, y, z, bytes ) { + } - var oct, dec, best, currentCos, bestCos; + // for `Octahedron` encoding + static octEncodeBest( x, y, z, bytes ) { - // Test various combinations of ceil and floor - // to minimize rounding errors - best = oct = octEncodeVec3( x, y, z, 'floor', 'floor' ); - dec = octDecodeVec2( oct ); - bestCos = dot( x, y, z, dec ); + let oct, dec, best, currentCos, bestCos; - oct = octEncodeVec3( x, y, z, 'ceil', 'floor' ); - dec = octDecodeVec2( oct ); - currentCos = dot( x, y, z, dec ); + // Test various combinations of ceil and floor + // to minimize rounding errors + best = oct = octEncodeVec3( x, y, z, 'floor', 'floor' ); + dec = octDecodeVec2( oct ); + bestCos = dot( x, y, z, dec ); - if ( currentCos > bestCos ) { + oct = octEncodeVec3( x, y, z, 'ceil', 'floor' ); + dec = octDecodeVec2( oct ); + currentCos = dot( x, y, z, dec ); - best = oct; - bestCos = currentCos; + if ( currentCos > bestCos ) { - } + best = oct; + bestCos = currentCos; - oct = octEncodeVec3( x, y, z, 'floor', 'ceil' ); - dec = octDecodeVec2( oct ); - currentCos = dot( x, y, z, dec ); + } - if ( currentCos > bestCos ) { + oct = octEncodeVec3( x, y, z, 'floor', 'ceil' ); + dec = octDecodeVec2( oct ); + currentCos = dot( x, y, z, dec ); - best = oct; - bestCos = currentCos; + if ( currentCos > bestCos ) { - } + best = oct; + bestCos = currentCos; - oct = octEncodeVec3( x, y, z, 'ceil', 'ceil' ); - dec = octDecodeVec2( oct ); - currentCos = dot( x, y, z, dec ); + } - if ( currentCos > bestCos ) { + oct = octEncodeVec3( x, y, z, 'ceil', 'ceil' ); + dec = octDecodeVec2( oct ); + currentCos = dot( x, y, z, dec ); - best = oct; + if ( currentCos > bestCos ) { - } + best = oct; - return best; + } - function octEncodeVec3( x0, y0, z0, xfunc, yfunc ) { + return best; - var x = x0 / ( Math.abs( x0 ) + Math.abs( y0 ) + Math.abs( z0 ) ); - var y = y0 / ( Math.abs( x0 ) + Math.abs( y0 ) + Math.abs( z0 ) ); + function octEncodeVec3( x0, y0, z0, xfunc, yfunc ) { - if ( z < 0 ) { + let x = x0 / ( Math.abs( x0 ) + Math.abs( y0 ) + Math.abs( z0 ) ); + let y = y0 / ( Math.abs( x0 ) + Math.abs( y0 ) + Math.abs( z0 ) ); - var tempx = ( 1 - Math.abs( y ) ) * ( x >= 0 ? 1 : - 1 ); - var tempy = ( 1 - Math.abs( x ) ) * ( y >= 0 ? 1 : - 1 ); + if ( z < 0 ) { - x = tempx; - y = tempy; + const tempx = ( 1 - Math.abs( y ) ) * ( x >= 0 ? 1 : - 1 ); + const tempy = ( 1 - Math.abs( x ) ) * ( y >= 0 ? 1 : - 1 ); - var diff = 1 - Math.abs( x ) - Math.abs( y ); - if ( diff > 0 ) { + x = tempx; + y = tempy; - diff += 0.001; - x += x > 0 ? diff / 2 : - diff / 2; - y += y > 0 ? diff / 2 : - diff / 2; + let diff = 1 - Math.abs( x ) - Math.abs( y ); + if ( diff > 0 ) { - } + diff += 0.001; + x += x > 0 ? diff / 2 : - diff / 2; + y += y > 0 ? diff / 2 : - diff / 2; } - if ( bytes == 1 ) { - - return new Int8Array( [ - Math[ xfunc ]( x * 127.5 + ( x < 0 ? 1 : 0 ) ), - Math[ yfunc ]( y * 127.5 + ( y < 0 ? 1 : 0 ) ) - ] ); + } - } + if ( bytes == 1 ) { - if ( bytes == 2 ) { + return new Int8Array( [ + Math[ xfunc ]( x * 127.5 + ( x < 0 ? 1 : 0 ) ), + Math[ yfunc ]( y * 127.5 + ( y < 0 ? 1 : 0 ) ) + ] ); - return new Int16Array( [ - Math[ xfunc ]( x * 32767.5 + ( x < 0 ? 1 : 0 ) ), - Math[ yfunc ]( y * 32767.5 + ( y < 0 ? 1 : 0 ) ) - ] ); + } - } + if ( bytes == 2 ) { + return new Int16Array( [ + Math[ xfunc ]( x * 32767.5 + ( x < 0 ? 1 : 0 ) ), + Math[ yfunc ]( y * 32767.5 + ( y < 0 ? 1 : 0 ) ) + ] ); } - function octDecodeVec2( oct ) { - - var x = oct[ 0 ]; - var y = oct[ 1 ]; - if ( bytes == 1 ) { + } - x /= x < 0 ? 127 : 128; - y /= y < 0 ? 127 : 128; + function octDecodeVec2( oct ) { - } else if ( bytes == 2 ) { + let x = oct[ 0 ]; + let y = oct[ 1 ]; - x /= x < 0 ? 32767 : 32768; - y /= y < 0 ? 32767 : 32768; + if ( bytes == 1 ) { - } + x /= x < 0 ? 127 : 128; + y /= y < 0 ? 127 : 128; + } else if ( bytes == 2 ) { - var z = 1 - Math.abs( x ) - Math.abs( y ); + x /= x < 0 ? 32767 : 32768; + y /= y < 0 ? 32767 : 32768; - if ( z < 0 ) { + } - var tmpx = x; - x = ( 1 - Math.abs( y ) ) * ( x >= 0 ? 1 : - 1 ); - y = ( 1 - Math.abs( tmpx ) ) * ( y >= 0 ? 1 : - 1 ); - } + const z = 1 - Math.abs( x ) - Math.abs( y ); - var length = Math.sqrt( x * x + y * y + z * z ); + if ( z < 0 ) { - return [ - x / length, - y / length, - z / length - ]; + const tmpx = x; + x = ( 1 - Math.abs( y ) ) * ( x >= 0 ? 1 : - 1 ); + y = ( 1 - Math.abs( tmpx ) ) * ( y >= 0 ? 1 : - 1 ); } - function dot( x, y, z, vec3 ) { + const length = Math.sqrt( x * x + y * y + z * z ); - return x * vec3[ 0 ] + y * vec3[ 1 ] + z * vec3[ 2 ]; + return [ + x / length, + y / length, + z / length + ]; - } + } - }, + function dot( x, y, z, vec3 ) { - quantizedEncode: function ( array, bytes ) { + return x * vec3[ 0 ] + y * vec3[ 1 ] + z * vec3[ 2 ]; - let quantized, segments; + } - if ( bytes == 1 ) { + } - quantized = new Uint8Array( array.length ); - segments = 255; + static quantizedEncode( array, bytes ) { - } else if ( bytes == 2 ) { + let quantized, segments; - quantized = new Uint16Array( array.length ); - segments = 65535; + if ( bytes == 1 ) { - } else { + quantized = new Uint8Array( array.length ); + segments = 255; - console.error( 'number of bytes error! ' ); + } else if ( bytes == 2 ) { - } + quantized = new Uint16Array( array.length ); + segments = 65535; - const decodeMat = new Matrix4(); + } else { - const min = new Float32Array( 3 ); - const max = new Float32Array( 3 ); + console.error( 'number of bytes error! ' ); - min[ 0 ] = min[ 1 ] = min[ 2 ] = Number.MAX_VALUE; - max[ 0 ] = max[ 1 ] = max[ 2 ] = - Number.MAX_VALUE; + } - for ( let i = 0; i < array.length; i += 3 ) { + const decodeMat = new Matrix4(); - min[ 0 ] = Math.min( min[ 0 ], array[ i + 0 ] ); - min[ 1 ] = Math.min( min[ 1 ], array[ i + 1 ] ); - min[ 2 ] = Math.min( min[ 2 ], array[ i + 2 ] ); - max[ 0 ] = Math.max( max[ 0 ], array[ i + 0 ] ); - max[ 1 ] = Math.max( max[ 1 ], array[ i + 1 ] ); - max[ 2 ] = Math.max( max[ 2 ], array[ i + 2 ] ); + const min = new Float32Array( 3 ); + const max = new Float32Array( 3 ); - } + min[ 0 ] = min[ 1 ] = min[ 2 ] = Number.MAX_VALUE; + max[ 0 ] = max[ 1 ] = max[ 2 ] = - Number.MAX_VALUE; - decodeMat.scale( new Vector3( - ( max[ 0 ] - min[ 0 ] ) / segments, - ( max[ 1 ] - min[ 1 ] ) / segments, - ( max[ 2 ] - min[ 2 ] ) / segments - ) ); + for ( let i = 0; i < array.length; i += 3 ) { - decodeMat.elements[ 12 ] = min[ 0 ]; - decodeMat.elements[ 13 ] = min[ 1 ]; - decodeMat.elements[ 14 ] = min[ 2 ]; + min[ 0 ] = Math.min( min[ 0 ], array[ i + 0 ] ); + min[ 1 ] = Math.min( min[ 1 ], array[ i + 1 ] ); + min[ 2 ] = Math.min( min[ 2 ], array[ i + 2 ] ); + max[ 0 ] = Math.max( max[ 0 ], array[ i + 0 ] ); + max[ 1 ] = Math.max( max[ 1 ], array[ i + 1 ] ); + max[ 2 ] = Math.max( max[ 2 ], array[ i + 2 ] ); - decodeMat.transpose(); + } + decodeMat.scale( new Vector3( + ( max[ 0 ] - min[ 0 ] ) / segments, + ( max[ 1 ] - min[ 1 ] ) / segments, + ( max[ 2 ] - min[ 2 ] ) / segments + ) ); - const multiplier = new Float32Array( [ - max[ 0 ] !== min[ 0 ] ? segments / ( max[ 0 ] - min[ 0 ] ) : 0, - max[ 1 ] !== min[ 1 ] ? segments / ( max[ 1 ] - min[ 1 ] ) : 0, - max[ 2 ] !== min[ 2 ] ? segments / ( max[ 2 ] - min[ 2 ] ) : 0 - ] ); + decodeMat.elements[ 12 ] = min[ 0 ]; + decodeMat.elements[ 13 ] = min[ 1 ]; + decodeMat.elements[ 14 ] = min[ 2 ]; - for ( let i = 0; i < array.length; i += 3 ) { + decodeMat.transpose(); - quantized[ i + 0 ] = Math.floor( ( array[ i + 0 ] - min[ 0 ] ) * multiplier[ 0 ] ); - quantized[ i + 1 ] = Math.floor( ( array[ i + 1 ] - min[ 1 ] ) * multiplier[ 1 ] ); - quantized[ i + 2 ] = Math.floor( ( array[ i + 2 ] - min[ 2 ] ) * multiplier[ 2 ] ); - } + const multiplier = new Float32Array( [ + max[ 0 ] !== min[ 0 ] ? segments / ( max[ 0 ] - min[ 0 ] ) : 0, + max[ 1 ] !== min[ 1 ] ? segments / ( max[ 1 ] - min[ 1 ] ) : 0, + max[ 2 ] !== min[ 2 ] ? segments / ( max[ 2 ] - min[ 2 ] ) : 0 + ] ); - return { - quantized: quantized, - decodeMat: decodeMat - }; + for ( let i = 0; i < array.length; i += 3 ) { - }, + quantized[ i + 0 ] = Math.floor( ( array[ i + 0 ] - min[ 0 ] ) * multiplier[ 0 ] ); + quantized[ i + 1 ] = Math.floor( ( array[ i + 1 ] - min[ 1 ] ) * multiplier[ 1 ] ); + quantized[ i + 2 ] = Math.floor( ( array[ i + 2 ] - min[ 2 ] ) * multiplier[ 2 ] ); + } - quantizedEncodeUV: function ( array, bytes ) { + return { + quantized: quantized, + decodeMat: decodeMat + }; - let quantized, segments; + } - if ( bytes == 1 ) { + static quantizedEncodeUV( array, bytes ) { - quantized = new Uint8Array( array.length ); - segments = 255; + let quantized, segments; - } else if ( bytes == 2 ) { + if ( bytes == 1 ) { - quantized = new Uint16Array( array.length ); - segments = 65535; + quantized = new Uint8Array( array.length ); + segments = 255; - } else { + } else if ( bytes == 2 ) { - console.error( 'number of bytes error! ' ); + quantized = new Uint16Array( array.length ); + segments = 65535; - } + } else { - const decodeMat = new Matrix3(); + console.error( 'number of bytes error! ' ); - const min = new Float32Array( 2 ); - const max = new Float32Array( 2 ); + } - min[ 0 ] = min[ 1 ] = Number.MAX_VALUE; - max[ 0 ] = max[ 1 ] = - Number.MAX_VALUE; + const decodeMat = new Matrix3(); - for ( let i = 0; i < array.length; i += 2 ) { + const min = new Float32Array( 2 ); + const max = new Float32Array( 2 ); - min[ 0 ] = Math.min( min[ 0 ], array[ i + 0 ] ); - min[ 1 ] = Math.min( min[ 1 ], array[ i + 1 ] ); - max[ 0 ] = Math.max( max[ 0 ], array[ i + 0 ] ); - max[ 1 ] = Math.max( max[ 1 ], array[ i + 1 ] ); + min[ 0 ] = min[ 1 ] = Number.MAX_VALUE; + max[ 0 ] = max[ 1 ] = - Number.MAX_VALUE; - } + for ( let i = 0; i < array.length; i += 2 ) { - decodeMat.scale( - ( max[ 0 ] - min[ 0 ] ) / segments, - ( max[ 1 ] - min[ 1 ] ) / segments - ); + min[ 0 ] = Math.min( min[ 0 ], array[ i + 0 ] ); + min[ 1 ] = Math.min( min[ 1 ], array[ i + 1 ] ); + max[ 0 ] = Math.max( max[ 0 ], array[ i + 0 ] ); + max[ 1 ] = Math.max( max[ 1 ], array[ i + 1 ] ); - decodeMat.elements[ 6 ] = min[ 0 ]; - decodeMat.elements[ 7 ] = min[ 1 ]; + } - decodeMat.transpose(); + decodeMat.scale( + ( max[ 0 ] - min[ 0 ] ) / segments, + ( max[ 1 ] - min[ 1 ] ) / segments + ); - const multiplier = new Float32Array( [ - max[ 0 ] !== min[ 0 ] ? segments / ( max[ 0 ] - min[ 0 ] ) : 0, - max[ 1 ] !== min[ 1 ] ? segments / ( max[ 1 ] - min[ 1 ] ) : 0 - ] ); + decodeMat.elements[ 6 ] = min[ 0 ]; + decodeMat.elements[ 7 ] = min[ 1 ]; - for ( let i = 0; i < array.length; i += 2 ) { + decodeMat.transpose(); - quantized[ i + 0 ] = Math.floor( ( array[ i + 0 ] - min[ 0 ] ) * multiplier[ 0 ] ); - quantized[ i + 1 ] = Math.floor( ( array[ i + 1 ] - min[ 1 ] ) * multiplier[ 1 ] ); + const multiplier = new Float32Array( [ + max[ 0 ] !== min[ 0 ] ? segments / ( max[ 0 ] - min[ 0 ] ) : 0, + max[ 1 ] !== min[ 1 ] ? segments / ( max[ 1 ] - min[ 1 ] ) : 0 + ] ); - } + for ( let i = 0; i < array.length; i += 2 ) { - return { - quantized: quantized, - decodeMat: decodeMat - }; + quantized[ i + 0 ] = Math.floor( ( array[ i + 0 ] - min[ 0 ] ) * multiplier[ 0 ] ); + quantized[ i + 1 ] = Math.floor( ( array[ i + 1 ] - min[ 1 ] ) * multiplier[ 1 ] ); } + return { + quantized: quantized, + decodeMat: decodeMat + }; + } -}; +} diff --git a/examples/jsm/utils/GeometryUtils.js b/examples/jsm/utils/GeometryUtils.js index a3915e7a5e5ac5..62de58f0add9c2 100644 --- a/examples/jsm/utils/GeometryUtils.js +++ b/examples/jsm/utils/GeometryUtils.js @@ -2,7 +2,7 @@ import { Vector3 } from '../../../build/three.module.js'; -var GeometryUtils = { +class GeometryUtils { /** * Generates 2D-Coordinates in a very fast way. @@ -18,27 +18,18 @@ var GeometryUtils = { * @param v2 Corner index +X, +Z. * @param v3 Corner index +X, -Z. */ - hilbert2D: function ( center, size, iterations, v0, v1, v2, v3 ) { + static hilbert2D( center = new Vector3( 0, 0, 0 ), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3 ) { - // Default Vars - var center = center !== undefined ? center : new Vector3( 0, 0, 0 ), - size = size !== undefined ? size : 10, - half = size / 2, - iterations = iterations !== undefined ? iterations : 1, - v0 = v0 !== undefined ? v0 : 0, - v1 = v1 !== undefined ? v1 : 1, - v2 = v2 !== undefined ? v2 : 2, - v3 = v3 !== undefined ? v3 : 3 - ; - - var vec_s = [ + const half = size / 2; + + const vec_s = [ new Vector3( center.x - half, center.y, center.z - half ), new Vector3( center.x - half, center.y, center.z + half ), new Vector3( center.x + half, center.y, center.z + half ), new Vector3( center.x + half, center.y, center.z - half ) ]; - var vec = [ + const vec = [ vec_s[ v0 ], vec_s[ v1 ], vec_s[ v2 ], @@ -48,7 +39,7 @@ var GeometryUtils = { // Recurse iterations if ( 0 <= -- iterations ) { - var tmp = []; + const tmp = []; Array.prototype.push.apply( tmp, GeometryUtils.hilbert2D( vec[ 0 ], half, iterations, v0, v3, v2, v1 ) ); Array.prototype.push.apply( tmp, GeometryUtils.hilbert2D( vec[ 1 ], half, iterations, v0, v1, v2, v3 ) ); @@ -63,7 +54,7 @@ var GeometryUtils = { // Return complete Hilbert Curve. return vec; - }, + } /** * Generates 3D-Coordinates in a very fast way. @@ -83,24 +74,12 @@ var GeometryUtils = { * @param v6 Corner index +X, +Y, +Z. * @param v7 Corner index +X, +Y, -Z. */ - hilbert3D: function ( center, size, iterations, v0, v1, v2, v3, v4, v5, v6, v7 ) { + static hilbert3D( center = new Vector3( 0, 0, 0 ), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7 ) { // Default Vars - var center = center !== undefined ? center : new Vector3( 0, 0, 0 ), - size = size !== undefined ? size : 10, - half = size / 2, - iterations = iterations !== undefined ? iterations : 1, - v0 = v0 !== undefined ? v0 : 0, - v1 = v1 !== undefined ? v1 : 1, - v2 = v2 !== undefined ? v2 : 2, - v3 = v3 !== undefined ? v3 : 3, - v4 = v4 !== undefined ? v4 : 4, - v5 = v5 !== undefined ? v5 : 5, - v6 = v6 !== undefined ? v6 : 6, - v7 = v7 !== undefined ? v7 : 7 - ; - - var vec_s = [ + const half = size / 2; + + const vec_s = [ new Vector3( center.x - half, center.y + half, center.z - half ), new Vector3( center.x - half, center.y + half, center.z + half ), new Vector3( center.x - half, center.y - half, center.z + half ), @@ -111,7 +90,7 @@ var GeometryUtils = { new Vector3( center.x + half, center.y + half, center.z - half ) ]; - var vec = [ + const vec = [ vec_s[ v0 ], vec_s[ v1 ], vec_s[ v2 ], @@ -125,7 +104,7 @@ var GeometryUtils = { // Recurse iterations if ( -- iterations >= 0 ) { - var tmp = []; + const tmp = []; Array.prototype.push.apply( tmp, GeometryUtils.hilbert3D( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) ); Array.prototype.push.apply( tmp, GeometryUtils.hilbert3D( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) ); @@ -144,7 +123,7 @@ var GeometryUtils = { // Return complete Hilbert Curve. return vec; - }, + } /** * Generates a Gosper curve (lying in the XY plane) @@ -153,22 +132,20 @@ var GeometryUtils = { * * @param size The size of a single gosper island. */ - gosper: function ( size ) { - - size = ( size !== undefined ) ? size : 1; + static gosper( size = 1 ) { function fractalize( config ) { - var output; - var input = config.axiom; + let output; + let input = config.axiom; - for ( var i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i ++ : i -- ) { + for ( let i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i ++ : i -- ) { output = ''; - for ( var j = 0, jl = input.length; j < jl; j ++ ) { + for ( let j = 0, jl = input.length; j < jl; j ++ ) { - var char = input[ j ]; + const char = input[ j ]; if ( char in config.rules ) { @@ -192,14 +169,14 @@ var GeometryUtils = { function toPoints( config ) { - var currX = 0, currY = 0; - var angle = 0; - var path = [ 0, 0, 0 ]; - var fractal = config.fractal; + let currX = 0, currY = 0; + let angle = 0; + const path = [ 0, 0, 0 ]; + const fractal = config.fractal; - for ( var i = 0, l = fractal.length; i < l; i ++ ) { + for ( let i = 0, l = fractal.length; i < l; i ++ ) { - var char = fractal[ i ]; + const char = fractal[ i ]; if ( char === '+' ) { @@ -225,7 +202,7 @@ var GeometryUtils = { // - var gosper = fractalize( { + const gosper = fractalize( { axiom: 'A', steps: 4, rules: { @@ -234,7 +211,7 @@ var GeometryUtils = { } } ); - var points = toPoints( { + const points = toPoints( { fractal: gosper, size: size, angle: Math.PI / 3 // 60 degrees @@ -244,6 +221,6 @@ var GeometryUtils = { } -}; +} export { GeometryUtils }; diff --git a/examples/jsm/utils/RoughnessMipmapper.js b/examples/jsm/utils/RoughnessMipmapper.js index 43ccb8f64911b1..93c591a9cb6c93 100644 --- a/examples/jsm/utils/RoughnessMipmapper.js +++ b/examples/jsm/utils/RoughnessMipmapper.js @@ -17,47 +17,44 @@ import { WebGLRenderTarget } from '../../../build/three.module.js'; -var _mipmapMaterial = _getMipmapMaterial(); +const _mipmapMaterial = _getMipmapMaterial(); -var _mesh = new Mesh( new PlaneGeometry( 2, 2 ), _mipmapMaterial ); +const _mesh = new Mesh( new PlaneGeometry( 2, 2 ), _mipmapMaterial ); -var _flatCamera = new OrthographicCamera( 0, 1, 0, 1, 0, 1 ); +const _flatCamera = new OrthographicCamera( 0, 1, 0, 1, 0, 1 ); -var _tempTarget = null; +let _tempTarget = null; -var _renderer = null; +let _renderer = null; -function RoughnessMipmapper( renderer ) { +class RoughnessMipmapper { - _renderer = renderer; + constructor( renderer ) { - _renderer.compile( _mesh, _flatCamera ); + _renderer = renderer; -} - -RoughnessMipmapper.prototype = { + _renderer.compile( _mesh, _flatCamera ); - constructor: RoughnessMipmapper, + } - generateMipmaps: function ( material ) { + generateMipmaps( material ) { if ( 'roughnessMap' in material === false ) return; - var { roughnessMap, normalMap } = material; + const { roughnessMap, normalMap } = material; if ( roughnessMap === null || normalMap === null || ! roughnessMap.generateMipmaps || material.userData.roughnessUpdated ) return; material.userData.roughnessUpdated = true; - var width = Math.max( roughnessMap.image.width, normalMap.image.width ); - - var height = Math.max( roughnessMap.image.height, normalMap.image.height ); + 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; - var oldTarget = _renderer.getRenderTarget(); + const oldTarget = _renderer.getRenderTarget(); - var autoClear = _renderer.autoClear; + const autoClear = _renderer.autoClear; _renderer.autoClear = false; @@ -73,7 +70,7 @@ RoughnessMipmapper.prototype = { if ( width !== roughnessMap.image.width || height !== roughnessMap.image.height ) { - var params = { + const params = { wrapS: roughnessMap.wrapS, wrapT: roughnessMap.wrapT, magFilter: roughnessMap.magFilter, @@ -81,7 +78,7 @@ RoughnessMipmapper.prototype = { depthBuffer: false }; - var newRoughnessTarget = new WebGLRenderTarget( width, height, params ); + const newRoughnessTarget = new WebGLRenderTarget( width, height, params ); newRoughnessTarget.texture.generateMipmaps = true; @@ -111,11 +108,11 @@ RoughnessMipmapper.prototype = { _mipmapMaterial.uniforms.normalMap.value = normalMap; - var position = new Vector2( 0, 0 ); + const position = new Vector2( 0, 0 ); - var texelSize = _mipmapMaterial.uniforms.texelSize.value; + const texelSize = _mipmapMaterial.uniforms.texelSize.value; - for ( var mip = 0; width >= 1 && height >= 1; ++ mip, width /= 2, height /= 2 ) { + 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 @@ -145,9 +142,9 @@ RoughnessMipmapper.prototype = { _renderer.autoClear = autoClear; - }, + } - dispose: function () { + dispose() { _mipmapMaterial.dispose(); @@ -157,11 +154,11 @@ RoughnessMipmapper.prototype = { } -}; +} function _getMipmapMaterial() { - var shaderMaterial = new RawShaderMaterial( { + const shaderMaterial = new RawShaderMaterial( { uniforms: { roughnessMap: { value: null }, diff --git a/examples/jsm/utils/SceneUtils.js b/examples/jsm/utils/SceneUtils.js index e1306093d738b1..1be92e8d251189 100644 --- a/examples/jsm/utils/SceneUtils.js +++ b/examples/jsm/utils/SceneUtils.js @@ -3,19 +3,19 @@ import { Mesh } from '../../../build/three.module.js'; -var SceneUtils = { +class SceneUtils { - createMeshesFromInstancedMesh: function ( instancedMesh ) { + static createMeshesFromInstancedMesh( instancedMesh ) { - var group = new Group(); + const group = new Group(); - var count = instancedMesh.count; - var geometry = instancedMesh.geometry; - var material = instancedMesh.material; + const count = instancedMesh.count; + const geometry = instancedMesh.geometry; + const material = instancedMesh.material; - for ( var i = 0; i < count; i ++ ) { + for ( let i = 0; i < count; i ++ ) { - var mesh = new Mesh( geometry, material ); + const mesh = new Mesh( geometry, material ); instancedMesh.getMatrixAt( i, mesh.matrix ); mesh.matrix.decompose( mesh.position, mesh.quaternion, mesh.scale ); @@ -29,13 +29,13 @@ var SceneUtils = { return group; - }, + } - createMultiMaterialObject: function ( geometry, materials ) { + static createMultiMaterialObject( geometry, materials ) { - var group = new Group(); + const group = new Group(); - for ( var i = 0, l = materials.length; i < l; i ++ ) { + for ( let i = 0, l = materials.length; i < l; i ++ ) { group.add( new Mesh( geometry, materials[ i ] ) ); @@ -43,17 +43,17 @@ var SceneUtils = { return group; - }, + } - detach: function ( child, parent, scene ) { + static detach( child, parent, scene ) { console.warn( 'THREE.SceneUtils: detach() has been deprecated. Use scene.attach( child ) instead.' ); scene.attach( child ); - }, + } - attach: function ( child, scene, parent ) { + static attach( child, scene, parent ) { console.warn( 'THREE.SceneUtils: attach() has been deprecated. Use parent.attach( child ) instead.' ); @@ -61,6 +61,6 @@ var SceneUtils = { } -}; +} export { SceneUtils }; diff --git a/examples/jsm/utils/ShadowMapViewer.js b/examples/jsm/utils/ShadowMapViewer.js index 4bdb6b98d66cf0..eee495a60f4c84 100644 --- a/examples/jsm/utils/ShadowMapViewer.js +++ b/examples/jsm/utils/ShadowMapViewer.js @@ -21,12 +21,12 @@ import { UnpackDepthRGBAShader } from '../shaders/UnpackDepthRGBAShader.js'; * 1) Import ShadowMapViewer into your app. * * 2) Create a shadow casting light and name it optionally: - * var light = new DirectionalLight( 0xffffff, 1 ); + * let light = new DirectionalLight( 0xffffff, 1 ); * light.castShadow = true; * light.name = 'Sun'; * * 3) Create a shadow map viewer for that light and set its size and position optionally: - * var shadowMapViewer = new ShadowMapViewer( light ); + * let shadowMapViewer = new ShadowMapViewer( light ); * shadowMapViewer.size.set( 128, 128 ); //width, height default: 256, 256 * shadowMapViewer.position.set( 10, 10 ); //x, y in pixel default: 0, 0 (top left corner) * @@ -39,169 +39,172 @@ import { UnpackDepthRGBAShader } from '../shaders/UnpackDepthRGBAShader.js'; * 6) If you set the position or size members directly, you need to call shadowMapViewer.update(); */ -var ShadowMapViewer = function ( light ) { +class ShadowMapViewer { - //- Internals - var scope = this; - var doRenderLabel = ( light.name !== undefined && light.name !== '' ); - var userAutoClearSetting; + constructor( light ) { - //Holds the initial position and dimension of the HUD - var frame = { - x: 10, - y: 10, - width: 256, - height: 256 - }; + //- Internals + const scope = this; + const doRenderLabel = ( light.name !== undefined && light.name !== '' ); + let userAutoClearSetting; - var camera = new OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 10 ); - camera.position.set( 0, 0, 2 ); - var scene = new Scene(); + //Holds the initial position and dimension of the HUD + const frame = { + x: 10, + y: 10, + width: 256, + height: 256 + }; - //HUD for shadow map - var shader = UnpackDepthRGBAShader; + const camera = new OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 10 ); + camera.position.set( 0, 0, 2 ); + const scene = new Scene(); - var uniforms = UniformsUtils.clone( shader.uniforms ); - var material = new ShaderMaterial( { - uniforms: uniforms, - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader - } ); - var plane = new PlaneGeometry( frame.width, frame.height ); - var mesh = new Mesh( plane, material ); + //HUD for shadow map + const shader = UnpackDepthRGBAShader; - scene.add( mesh ); + const uniforms = UniformsUtils.clone( shader.uniforms ); + const material = new ShaderMaterial( { + uniforms: uniforms, + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader + } ); + const plane = new PlaneGeometry( frame.width, frame.height ); + const mesh = new Mesh( plane, material ); + scene.add( mesh ); - //Label for light's name - var labelCanvas, labelMesh; - if ( doRenderLabel ) { + //Label for light's name + let labelCanvas, labelMesh; - labelCanvas = document.createElement( 'canvas' ); + if ( doRenderLabel ) { - var context = labelCanvas.getContext( '2d' ); - context.font = 'Bold 20px Arial'; + labelCanvas = document.createElement( 'canvas' ); - var labelWidth = context.measureText( light.name ).width; - labelCanvas.width = labelWidth; - labelCanvas.height = 25; //25 to account for g, p, etc. + const context = labelCanvas.getContext( '2d' ); + context.font = 'Bold 20px Arial'; - context.font = 'Bold 20px Arial'; - context.fillStyle = 'rgba( 255, 0, 0, 1 )'; - context.fillText( light.name, 0, 20 ); + const labelWidth = context.measureText( light.name ).width; + labelCanvas.width = labelWidth; + labelCanvas.height = 25; //25 to account for g, p, etc. - var labelTexture = new Texture( labelCanvas ); - labelTexture.magFilter = LinearFilter; - labelTexture.minFilter = LinearFilter; - labelTexture.needsUpdate = true; + context.font = 'Bold 20px Arial'; + context.fillStyle = 'rgba( 255, 0, 0, 1 )'; + context.fillText( light.name, 0, 20 ); - var labelMaterial = new MeshBasicMaterial( { map: labelTexture, side: DoubleSide } ); - labelMaterial.transparent = true; + const labelTexture = new Texture( labelCanvas ); + labelTexture.magFilter = LinearFilter; + labelTexture.minFilter = LinearFilter; + labelTexture.needsUpdate = true; - var labelPlane = new PlaneGeometry( labelCanvas.width, labelCanvas.height ); - labelMesh = new Mesh( labelPlane, labelMaterial ); + const labelMaterial = new MeshBasicMaterial( { map: labelTexture, side: DoubleSide } ); + labelMaterial.transparent = true; - scene.add( labelMesh ); + const labelPlane = new PlaneGeometry( labelCanvas.width, labelCanvas.height ); + labelMesh = new Mesh( labelPlane, labelMaterial ); - } + scene.add( labelMesh ); + } - function resetPosition() { - scope.position.set( scope.position.x, scope.position.y ); + function resetPosition() { - } + scope.position.set( scope.position.x, scope.position.y ); - //- API - // Set to false to disable displaying this shadow map - this.enabled = true; + } - // Set the size of the displayed shadow map on the HUD - this.size = { - width: frame.width, - height: frame.height, - set: function ( width, height ) { + //- API + // Set to false to disable displaying this shadow map + this.enabled = true; - this.width = width; - this.height = height; + // Set the size of the displayed shadow map on the HUD + this.size = { + width: frame.width, + height: frame.height, + set: function ( width, height ) { - mesh.scale.set( this.width / frame.width, this.height / frame.height, 1 ); + this.width = width; + this.height = height; - //Reset the position as it is off when we scale stuff - resetPosition(); + mesh.scale.set( this.width / frame.width, this.height / frame.height, 1 ); - } - }; + //Reset the position as it is off when we scale stuff + resetPosition(); - // Set the position of the displayed shadow map on the HUD - this.position = { - x: frame.x, - y: frame.y, - set: function ( x, y ) { + } + }; - this.x = x; - this.y = y; + // Set the position of the displayed shadow map on the HUD + this.position = { + x: frame.x, + y: frame.y, + set: function ( x, y ) { - var width = scope.size.width; - var height = scope.size.height; + this.x = x; + this.y = y; - mesh.position.set( - window.innerWidth / 2 + width / 2 + this.x, window.innerHeight / 2 - height / 2 - this.y, 0 ); + const width = scope.size.width; + const height = scope.size.height; - if ( doRenderLabel ) labelMesh.position.set( mesh.position.x, mesh.position.y - scope.size.height / 2 + labelCanvas.height / 2, 0 ); + mesh.position.set( - window.innerWidth / 2 + width / 2 + this.x, window.innerHeight / 2 - height / 2 - this.y, 0 ); - } - }; + if ( doRenderLabel ) labelMesh.position.set( mesh.position.x, mesh.position.y - scope.size.height / 2 + labelCanvas.height / 2, 0 ); - this.render = function ( renderer ) { + } + }; - if ( this.enabled ) { + this.render = function ( renderer ) { - //Because a light's .shadowMap is only initialised after the first render pass - //we have to make sure the correct map is sent into the shader, otherwise we - //always end up with the scene's first added shadow casting light's shadowMap - //in the shader - //See: https://github.com/mrdoob/three.js/issues/5932 - uniforms.tDiffuse.value = light.shadow.map.texture; + if ( this.enabled ) { - userAutoClearSetting = renderer.autoClear; - renderer.autoClear = false; // To allow render overlay - renderer.clearDepth(); - renderer.render( scene, camera ); - renderer.autoClear = userAutoClearSetting; //Restore user's setting + //Because a light's .shadowMap is only initialised after the first render pass + //we have to make sure the correct map is sent into the shader, otherwise we + //always end up with the scene's first added shadow casting light's shadowMap + //in the shader + //See: https://github.com/mrdoob/three.js/issues/5932 + uniforms.tDiffuse.value = light.shadow.map.texture; - } + userAutoClearSetting = renderer.autoClear; + renderer.autoClear = false; // To allow render overlay + renderer.clearDepth(); + renderer.render( scene, camera ); + renderer.autoClear = userAutoClearSetting; //Restore user's setting - }; + } - this.updateForWindowResize = function () { + }; - if ( this.enabled ) { + this.updateForWindowResize = function () { - camera.left = window.innerWidth / - 2; - camera.right = window.innerWidth / 2; - camera.top = window.innerHeight / 2; - camera.bottom = window.innerHeight / - 2; - camera.updateProjectionMatrix(); + if ( this.enabled ) { - this.update(); + camera.left = window.innerWidth / - 2; + camera.right = window.innerWidth / 2; + camera.top = window.innerHeight / 2; + camera.bottom = window.innerHeight / - 2; + camera.updateProjectionMatrix(); - } + this.update(); + + } - }; + }; - this.update = function () { + this.update = function () { - this.position.set( this.position.x, this.position.y ); - this.size.set( this.size.width, this.size.height ); + this.position.set( this.position.x, this.position.y ); + this.size.set( this.size.width, this.size.height ); - }; + }; - //Force an update to set position/size - this.update(); + //Force an update to set position/size + this.update(); + + } -}; +} -ShadowMapViewer.prototype.constructor = ShadowMapViewer; export { ShadowMapViewer }; diff --git a/examples/jsm/utils/SkeletonUtils.js b/examples/jsm/utils/SkeletonUtils.js index 3e036684a47380..255db96c2c0dce 100644 --- a/examples/jsm/utils/SkeletonUtils.js +++ b/examples/jsm/utils/SkeletonUtils.js @@ -11,202 +11,197 @@ import { VectorKeyframeTrack } from '../../../build/three.module.js'; -var SkeletonUtils = { +class SkeletonUtils { - retarget: function () { + static retarget( target, source, options = {} ) { - var pos = new Vector3(), + const pos = new Vector3(), quat = new Quaternion(), scale = new Vector3(), bindBoneMatrix = new Matrix4(), relativeMatrix = new Matrix4(), globalMatrix = new Matrix4(); - return function ( target, source, options ) { + options.preserveMatrix = options.preserveMatrix !== undefined ? options.preserveMatrix : true; + options.preservePosition = options.preservePosition !== undefined ? options.preservePosition : true; + options.preserveHipPosition = options.preserveHipPosition !== undefined ? options.preserveHipPosition : false; + options.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false; + options.hip = options.hip !== undefined ? options.hip : 'hip'; + options.names = options.names || {}; - options = options || {}; - options.preserveMatrix = options.preserveMatrix !== undefined ? options.preserveMatrix : true; - options.preservePosition = options.preservePosition !== undefined ? options.preservePosition : true; - options.preserveHipPosition = options.preserveHipPosition !== undefined ? options.preserveHipPosition : false; - options.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false; - options.hip = options.hip !== undefined ? options.hip : 'hip'; - options.names = options.names || {}; + const sourceBones = source.isObject3D ? source.skeleton.bones : this.getBones( source ), + bones = target.isObject3D ? target.skeleton.bones : this.getBones( target ); - var sourceBones = source.isObject3D ? source.skeleton.bones : this.getBones( source ), - bones = target.isObject3D ? target.skeleton.bones : this.getBones( target ), - bindBones, - bone, name, boneTo, - bonesPosition, i; + let bindBones, + bone, name, boneTo, + bonesPosition; - // reset bones + // reset bones - if ( target.isObject3D ) { + if ( target.isObject3D ) { - target.skeleton.pose(); + target.skeleton.pose(); - } else { + } else { - options.useTargetMatrix = true; - options.preserveMatrix = false; + options.useTargetMatrix = true; + options.preserveMatrix = false; - } + } - if ( options.preservePosition ) { + if ( options.preservePosition ) { - bonesPosition = []; + bonesPosition = []; - for ( i = 0; i < bones.length; i ++ ) { + for ( let i = 0; i < bones.length; i ++ ) { - bonesPosition.push( bones[ i ].position.clone() ); - - } + bonesPosition.push( bones[ i ].position.clone() ); } - if ( options.preserveMatrix ) { + } - // reset matrix + if ( options.preserveMatrix ) { - target.updateMatrixWorld(); + // reset matrix - target.matrixWorld.identity(); + target.updateMatrixWorld(); - // reset children matrix + target.matrixWorld.identity(); - for ( i = 0; i < target.children.length; ++ i ) { + // reset children matrix - target.children[ i ].updateMatrixWorld( true ); + for ( let i = 0; i < target.children.length; ++ i ) { - } + target.children[ i ].updateMatrixWorld( true ); } - if ( options.offsets ) { - - bindBones = []; + } - for ( i = 0; i < bones.length; ++ i ) { + if ( options.offsets ) { - bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; + bindBones = []; - if ( options.offsets && options.offsets[ name ] ) { + for ( let i = 0; i < bones.length; ++ i ) { - bone.matrix.multiply( options.offsets[ name ] ); + bone = bones[ i ]; + name = options.names[ bone.name ] || bone.name; - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); + if ( options.offsets && options.offsets[ name ] ) { - bone.updateMatrixWorld(); + bone.matrix.multiply( options.offsets[ name ] ); - } + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); - bindBones.push( bone.matrixWorld.clone() ); + bone.updateMatrixWorld(); } - } + bindBones.push( bone.matrixWorld.clone() ); - for ( i = 0; i < bones.length; ++ i ) { + } - bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; + } - boneTo = this.getBoneByName( name, sourceBones ); + for ( let i = 0; i < bones.length; ++ i ) { - globalMatrix.copy( bone.matrixWorld ); + bone = bones[ i ]; + name = options.names[ bone.name ] || bone.name; - if ( boneTo ) { + boneTo = this.getBoneByName( name, sourceBones ); - boneTo.updateMatrixWorld(); + globalMatrix.copy( bone.matrixWorld ); - if ( options.useTargetMatrix ) { + if ( boneTo ) { - relativeMatrix.copy( boneTo.matrixWorld ); + boneTo.updateMatrixWorld(); - } else { + if ( options.useTargetMatrix ) { - relativeMatrix.copy( target.matrixWorld ).invert(); - relativeMatrix.multiply( boneTo.matrixWorld ); + relativeMatrix.copy( boneTo.matrixWorld ); - } + } else { - // ignore scale to extract rotation + relativeMatrix.copy( target.matrixWorld ).invert(); + relativeMatrix.multiply( boneTo.matrixWorld ); - scale.setFromMatrixScale( relativeMatrix ); - relativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) ); + } - // apply to global matrix + // ignore scale to extract rotation - globalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) ); + scale.setFromMatrixScale( relativeMatrix ); + relativeMatrix.scale( scale.set( 1 / scale.x, 1 / scale.y, 1 / scale.z ) ); - if ( target.isObject3D ) { + // apply to global matrix - var boneIndex = bones.indexOf( bone ), - wBindMatrix = bindBones ? bindBones[ boneIndex ] : bindBoneMatrix.copy( target.skeleton.boneInverses[ boneIndex ] ).invert(); + globalMatrix.makeRotationFromQuaternion( quat.setFromRotationMatrix( relativeMatrix ) ); - globalMatrix.multiply( wBindMatrix ); + if ( target.isObject3D ) { - } + const boneIndex = bones.indexOf( bone ), + wBindMatrix = bindBones ? bindBones[ boneIndex ] : bindBoneMatrix.copy( target.skeleton.boneInverses[ boneIndex ] ).invert(); - globalMatrix.copyPosition( relativeMatrix ); + globalMatrix.multiply( wBindMatrix ); } - if ( bone.parent && bone.parent.isBone ) { - - bone.matrix.copy( bone.parent.matrixWorld ).invert(); - bone.matrix.multiply( globalMatrix ); + globalMatrix.copyPosition( relativeMatrix ); - } else { + } - bone.matrix.copy( globalMatrix ); + if ( bone.parent && bone.parent.isBone ) { - } + bone.matrix.copy( bone.parent.matrixWorld ).invert(); + bone.matrix.multiply( globalMatrix ); - if ( options.preserveHipPosition && name === options.hip ) { + } else { - bone.matrix.setPosition( pos.set( 0, bone.position.y, 0 ) ); + bone.matrix.copy( globalMatrix ); - } + } - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); + if ( options.preserveHipPosition && name === options.hip ) { - bone.updateMatrixWorld(); + bone.matrix.setPosition( pos.set( 0, bone.position.y, 0 ) ); } - if ( options.preservePosition ) { + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); - for ( i = 0; i < bones.length; ++ i ) { + bone.updateMatrixWorld(); - bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; + } - if ( name !== options.hip ) { + if ( options.preservePosition ) { - bone.position.copy( bonesPosition[ i ] ); + for ( let i = 0; i < bones.length; ++ i ) { - } + bone = bones[ i ]; + name = options.names[ bone.name ] || bone.name; + + if ( name !== options.hip ) { + + bone.position.copy( bonesPosition[ i ] ); } } - if ( options.preserveMatrix ) { + } - // restore matrix + if ( options.preserveMatrix ) { - target.updateMatrixWorld( true ); + // restore matrix - } + target.updateMatrixWorld( true ); - }; + } - }(), + } - retargetClip: function ( target, source, clip, options ) { + static retargetClip( target, source, clip, options = {} ) { - options = options || {}; options.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false; options.fps = options.fps !== undefined ? options.fps : 30; options.names = options.names || []; @@ -217,28 +212,28 @@ var SkeletonUtils = { } - var numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ), + const numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ), delta = 1 / options.fps, convertedTracks = [], mixer = new AnimationMixer( source ), bones = this.getBones( target.skeleton ), - boneDatas = [], - positionOffset, + boneDatas = []; + let positionOffset, bone, boneTo, boneData, - name, i, j; + name; mixer.clipAction( clip ).play(); mixer.update( 0 ); source.updateMatrixWorld(); - for ( i = 0; i < numFrames; ++ i ) { + for ( let i = 0; i < numFrames; ++ i ) { - var time = i * delta; + const time = i * delta; this.retarget( target, source, options ); - for ( j = 0; j < bones.length; ++ j ) { + for ( let j = 0; j < bones.length; ++ j ) { name = options.names[ bones[ j ].name ] || bones[ j ].name; @@ -301,7 +296,7 @@ var SkeletonUtils = { } - for ( i = 0; i < boneDatas.length; ++ i ) { + for ( let i = 0; i < boneDatas.length; ++ i ) { boneData = boneDatas[ i ]; @@ -331,114 +326,110 @@ var SkeletonUtils = { return new AnimationClip( clip.name, - 1, convertedTracks ); - }, + } - getHelperFromSkeleton: function ( skeleton ) { + static getHelperFromSkeleton( skeleton ) { - var source = new SkeletonHelper( skeleton.bones[ 0 ] ); + const source = new SkeletonHelper( skeleton.bones[ 0 ] ); source.skeleton = skeleton; return source; - }, + } - getSkeletonOffsets: function () { + static getSkeletonOffsets( target, source, options = {} ) { - var targetParentPos = new Vector3(), + const targetParentPos = new Vector3(), targetPos = new Vector3(), sourceParentPos = new Vector3(), sourcePos = new Vector3(), targetDir = new Vector2(), sourceDir = new Vector2(); - return function ( target, source, options ) { - - options = options || {}; - options.hip = options.hip !== undefined ? options.hip : 'hip'; - options.names = options.names || {}; + options.hip = options.hip !== undefined ? options.hip : 'hip'; + options.names = options.names || {}; - if ( ! source.isObject3D ) { + if ( ! source.isObject3D ) { - source = this.getHelperFromSkeleton( source ); + source = this.getHelperFromSkeleton( source ); - } + } - var nameKeys = Object.keys( options.names ), - nameValues = Object.values( options.names ), - sourceBones = source.isObject3D ? source.skeleton.bones : this.getBones( source ), - bones = target.isObject3D ? target.skeleton.bones : this.getBones( target ), - offsets = [], - bone, boneTo, - name, i; + const nameKeys = Object.keys( options.names ), + nameValues = Object.values( options.names ), + sourceBones = source.isObject3D ? source.skeleton.bones : this.getBones( source ), + bones = target.isObject3D ? target.skeleton.bones : this.getBones( target ), + offsets = []; - target.skeleton.pose(); + let bone, boneTo, + name, i; - for ( i = 0; i < bones.length; ++ i ) { + target.skeleton.pose(); - bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; + for ( i = 0; i < bones.length; ++ i ) { - boneTo = this.getBoneByName( name, sourceBones ); + bone = bones[ i ]; + name = options.names[ bone.name ] || bone.name; - if ( boneTo && name !== options.hip ) { + boneTo = this.getBoneByName( name, sourceBones ); - var boneParent = this.getNearestBone( bone.parent, nameKeys ), - boneToParent = this.getNearestBone( boneTo.parent, nameValues ); + if ( boneTo && name !== options.hip ) { - boneParent.updateMatrixWorld(); - boneToParent.updateMatrixWorld(); + const boneParent = this.getNearestBone( bone.parent, nameKeys ), + boneToParent = this.getNearestBone( boneTo.parent, nameValues ); - targetParentPos.setFromMatrixPosition( boneParent.matrixWorld ); - targetPos.setFromMatrixPosition( bone.matrixWorld ); + boneParent.updateMatrixWorld(); + boneToParent.updateMatrixWorld(); - sourceParentPos.setFromMatrixPosition( boneToParent.matrixWorld ); - sourcePos.setFromMatrixPosition( boneTo.matrixWorld ); + targetParentPos.setFromMatrixPosition( boneParent.matrixWorld ); + targetPos.setFromMatrixPosition( bone.matrixWorld ); - targetDir.subVectors( - new Vector2( targetPos.x, targetPos.y ), - new Vector2( targetParentPos.x, targetParentPos.y ) - ).normalize(); + sourceParentPos.setFromMatrixPosition( boneToParent.matrixWorld ); + sourcePos.setFromMatrixPosition( boneTo.matrixWorld ); - sourceDir.subVectors( - new Vector2( sourcePos.x, sourcePos.y ), - new Vector2( sourceParentPos.x, sourceParentPos.y ) - ).normalize(); + targetDir.subVectors( + new Vector2( targetPos.x, targetPos.y ), + new Vector2( targetParentPos.x, targetParentPos.y ) + ).normalize(); - var laterialAngle = targetDir.angle() - sourceDir.angle(); + sourceDir.subVectors( + new Vector2( sourcePos.x, sourcePos.y ), + new Vector2( sourceParentPos.x, sourceParentPos.y ) + ).normalize(); - var offset = new Matrix4().makeRotationFromEuler( - new Euler( - 0, - 0, - laterialAngle - ) - ); + const laterialAngle = targetDir.angle() - sourceDir.angle(); - bone.matrix.multiply( offset ); + const offset = new Matrix4().makeRotationFromEuler( + new Euler( + 0, + 0, + laterialAngle + ) + ); - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); + bone.matrix.multiply( offset ); - bone.updateMatrixWorld(); + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); - offsets[ name ] = offset; + bone.updateMatrixWorld(); - } + offsets[ name ] = offset; } - return offsets; + } - }; + return offsets; - }(), + } - renameBones: function ( skeleton, names ) { + static renameBones( skeleton, names ) { - var bones = this.getBones( skeleton ); + const bones = this.getBones( skeleton ); - for ( var i = 0; i < bones.length; ++ i ) { + for ( let i = 0; i < bones.length; ++ i ) { - var bone = bones[ i ]; + const bone = bones[ i ]; if ( names[ bone.name ] ) { @@ -450,17 +441,17 @@ var SkeletonUtils = { return this; - }, + } - getBones: function ( skeleton ) { + static getBones( skeleton ) { return Array.isArray( skeleton ) ? skeleton : skeleton.bones; - }, + } - getBoneByName: function ( name, skeleton ) { + static getBoneByName( name, skeleton ) { - for ( var i = 0, bones = this.getBones( skeleton ); i < bones.length; i ++ ) { + for ( let i = 0, bones = this.getBones( skeleton ); i < bones.length; i ++ ) { if ( name === bones[ i ].name ) @@ -468,9 +459,9 @@ var SkeletonUtils = { } - }, + } - getNearestBone: function ( bone, names ) { + static getNearestBone( bone, names ) { while ( bone.isBone ) { @@ -484,18 +475,18 @@ var SkeletonUtils = { } - }, + } - findBoneTrackData: function ( name, tracks ) { + static findBoneTrackData( name, tracks ) { - var regexp = /\[(.*)\]\.(.*)/, + const regexp = /\[(.*)\]\.(.*)/, result = { name: name }; - for ( var i = 0; i < tracks.length; ++ i ) { + for ( let i = 0; i < tracks.length; ++ i ) { // 1 is track name // 2 is track type - var trackData = regexp.exec( tracks[ i ].name ); + const trackData = regexp.exec( tracks[ i ].name ); if ( trackData && name === trackData[ 1 ] ) { @@ -507,19 +498,19 @@ var SkeletonUtils = { return result; - }, + } - getEqualsBonesNames: function ( skeleton, targetSkeleton ) { + static getEqualsBonesNames( skeleton, targetSkeleton ) { - var sourceBones = this.getBones( skeleton ), + const sourceBones = this.getBones( skeleton ), targetBones = this.getBones( targetSkeleton ), bones = []; - search : for ( var i = 0; i < sourceBones.length; i ++ ) { + search : for ( let i = 0; i < sourceBones.length; i ++ ) { - var boneName = sourceBones[ i ].name; + const boneName = sourceBones[ i ].name; - for ( var j = 0; j < targetBones.length; j ++ ) { + for ( let j = 0; j < targetBones.length; j ++ ) { if ( boneName === targetBones[ j ].name ) { @@ -535,14 +526,14 @@ var SkeletonUtils = { return bones; - }, + } - clone: function ( source ) { + static clone( source ) { - var sourceLookup = new Map(); - var cloneLookup = new Map(); + const sourceLookup = new Map(); + const cloneLookup = new Map(); - var clone = source.clone(); + const clone = source.clone(); parallelTraverse( source, clone, function ( sourceNode, clonedNode ) { @@ -555,9 +546,9 @@ var SkeletonUtils = { if ( ! node.isSkinnedMesh ) return; - var clonedMesh = node; - var sourceMesh = sourceLookup.get( node ); - var sourceBones = sourceMesh.skeleton.bones; + const clonedMesh = node; + const sourceMesh = sourceLookup.get( node ); + const sourceBones = sourceMesh.skeleton.bones; clonedMesh.skeleton = sourceMesh.skeleton.clone(); clonedMesh.bindMatrix.copy( sourceMesh.bindMatrix ); @@ -576,14 +567,14 @@ var SkeletonUtils = { } -}; +} function parallelTraverse( a, b, callback ) { callback( a, b ); - for ( var i = 0; i < a.children.length; i ++ ) { + for ( let i = 0; i < a.children.length; i ++ ) { parallelTraverse( a.children[ i ], b.children[ i ], callback ); diff --git a/examples/jsm/utils/UVsDebug.js b/examples/jsm/utils/UVsDebug.js index d5b4ad0b8c1d11..48789f8cd91847 100644 --- a/examples/jsm/utils/UVsDebug.js +++ b/examples/jsm/utils/UVsDebug.js @@ -10,29 +10,29 @@ import { * */ -var UVsDebug = function ( geometry, size ) { +function UVsDebug( geometry, size = 1024 ) { // handles wrapping of uv.x > 1 only - var abc = 'abc'; - var a = new Vector2(); - var b = new Vector2(); + const abc = 'abc'; + const a = new Vector2(); + const b = new Vector2(); - var uvs = [ + const uvs = [ new Vector2(), new Vector2(), new Vector2() ]; - var face = []; + const face = []; - var canvas = document.createElement( 'canvas' ); - var width = size || 1024; // power of 2 required for wrapping - var height = size || 1024; + const canvas = document.createElement( 'canvas' ); + const width = size; // power of 2 required for wrapping + const height = size; canvas.width = width; canvas.height = height; - var ctx = canvas.getContext( '2d' ); + const ctx = canvas.getContext( '2d' ); ctx.lineWidth = 1; ctx.strokeStyle = 'rgb( 63, 63, 63 )'; ctx.textAlign = 'center'; @@ -49,14 +49,14 @@ var UVsDebug = function ( geometry, size ) { } else { - var index = geometry.index; - var uvAttribute = geometry.attributes.uv; + const index = geometry.index; + const uvAttribute = geometry.attributes.uv; if ( index ) { // indexed geometry - for ( var i = 0, il = index.count; i < il; i += 3 ) { + for ( let i = 0, il = index.count; i < il; i += 3 ) { face[ 0 ] = index.getX( i ); face[ 1 ] = index.getX( i + 1 ); @@ -74,7 +74,7 @@ var UVsDebug = function ( geometry, size ) { // non-indexed geometry - for ( var i = 0, il = uvAttribute.count; i < il; i += 3 ) { + for ( let i = 0, il = uvAttribute.count; i < il; i += 3 ) { face[ 0 ] = i; face[ 1 ] = i + 1; @@ -102,9 +102,9 @@ var UVsDebug = function ( geometry, size ) { a.set( 0, 0 ); - for ( var j = 0, jl = uvs.length; j < jl; j ++ ) { + for ( let j = 0, jl = uvs.length; j < jl; j ++ ) { - var uv = uvs[ j ]; + const uv = uvs[ j ]; a.x += uv.x; a.y += uv.y; @@ -149,12 +149,12 @@ var UVsDebug = function ( geometry, size ) { // label uv edge orders - for ( j = 0, jl = uvs.length; j < jl; j ++ ) { + for ( let j = 0, jl = uvs.length; j < jl; j ++ ) { - var uv = uvs[ j ]; + const uv = uvs[ j ]; b.addVectors( a, uv ).divideScalar( 2 ); - var vnum = face[ j ]; + const vnum = face[ j ]; ctx.fillText( abc[ j ] + vnum, b.x * width, ( 1 - b.y ) * height ); if ( b.x > 0.95 ) { @@ -169,6 +169,6 @@ var UVsDebug = function ( geometry, size ) { } -}; +} export { UVsDebug }; diff --git a/examples/jsm/webxr/XRControllerModelFactory.js b/examples/jsm/webxr/XRControllerModelFactory.js index 770fc6393bbfab..c669abed77fa5c 100644 --- a/examples/jsm/webxr/XRControllerModelFactory.js +++ b/examples/jsm/webxr/XRControllerModelFactory.js @@ -16,20 +16,18 @@ import { const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles'; const DEFAULT_PROFILE = 'generic-trigger'; -function XRControllerModel( ) { +class XRControllerModel extends Object3D { - Object3D.call( this ); + constructor() { - this.motionController = null; - this.envMap = null; + super(); -} - -XRControllerModel.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.motionController = null; + this.envMap = null; - constructor: XRControllerModel, + } - setEnvironmentMap: function ( envMap ) { + setEnvironmentMap( envMap ) { if ( this.envMap == envMap ) { @@ -51,15 +49,15 @@ XRControllerModel.prototype = Object.assign( Object.create( Object3D.prototype ) return this; - }, + } /** * Polls data from the XRInputSource and updates the model's components to match * the real world data */ - updateMatrixWorld: function ( force ) { + updateMatrixWorld( force ) { - Object3D.prototype.updateMatrixWorld.call( this, force ); + super.updateMatrixWorld( force ); if ( ! this.motionController ) return; @@ -105,7 +103,7 @@ XRControllerModel.prototype = Object.assign( Object.create( Object3D.prototype ) } -} ); +} /** * Walks the model's tree to find the nodes needed to animate the components and @@ -206,9 +204,9 @@ function addAssetSceneToControllerModel( controllerModel, scene ) { } -var XRControllerModelFactory = ( function () { +class XRControllerModelFactory { - function XRControllerModelFactory( gltfLoader = null ) { + constructor( gltfLoader = null ) { this.gltfLoader = gltfLoader; this.path = DEFAULT_PROFILES_PATH; @@ -223,87 +221,79 @@ var XRControllerModelFactory = ( function () { } - XRControllerModelFactory.prototype = { + createControllerModel( controller ) { - constructor: XRControllerModelFactory, + const controllerModel = new XRControllerModel(); + let scene = null; - createControllerModel: function ( controller ) { + controller.addEventListener( 'connected', ( event ) => { - const controllerModel = new XRControllerModel(); - let scene = null; + const xrInputSource = event.data; - controller.addEventListener( 'connected', ( event ) => { + if ( xrInputSource.targetRayMode !== 'tracked-pointer' || ! xrInputSource.gamepad ) return; - const xrInputSource = event.data; + fetchProfile( xrInputSource, this.path, DEFAULT_PROFILE ).then( ( { profile, assetPath } ) => { - if ( xrInputSource.targetRayMode !== 'tracked-pointer' || ! xrInputSource.gamepad ) return; + controllerModel.motionController = new MotionController( + xrInputSource, + profile, + assetPath + ); - fetchProfile( xrInputSource, this.path, DEFAULT_PROFILE ).then( ( { profile, assetPath } ) => { + const cachedAsset = this._assetCache[ controllerModel.motionController.assetUrl ]; + if ( cachedAsset ) { - controllerModel.motionController = new MotionController( - xrInputSource, - profile, - assetPath - ); + scene = cachedAsset.scene.clone(); - const cachedAsset = this._assetCache[ controllerModel.motionController.assetUrl ]; - if ( cachedAsset ) { + addAssetSceneToControllerModel( controllerModel, scene ); - scene = cachedAsset.scene.clone(); + } else { - addAssetSceneToControllerModel( controllerModel, scene ); - - } else { - - if ( ! this.gltfLoader ) { + if ( ! this.gltfLoader ) { - throw new Error( 'GLTFLoader not set.' ); + throw new Error( 'GLTFLoader not set.' ); - } - - this.gltfLoader.setPath( '' ); - this.gltfLoader.load( controllerModel.motionController.assetUrl, ( asset ) => { + } - this._assetCache[ controllerModel.motionController.assetUrl ] = asset; + this.gltfLoader.setPath( '' ); + this.gltfLoader.load( controllerModel.motionController.assetUrl, ( asset ) => { - scene = asset.scene.clone(); + this._assetCache[ controllerModel.motionController.assetUrl ] = asset; - addAssetSceneToControllerModel( controllerModel, scene ); + scene = asset.scene.clone(); - }, - null, - () => { + addAssetSceneToControllerModel( controllerModel, scene ); - throw new Error( `Asset ${controllerModel.motionController.assetUrl} missing or malformed.` ); + }, + null, + () => { - } ); + throw new Error( `Asset ${controllerModel.motionController.assetUrl} missing or malformed.` ); - } + } ); - } ).catch( ( err ) => { + } - console.warn( err ); + } ).catch( ( err ) => { - } ); + console.warn( err ); } ); - controller.addEventListener( 'disconnected', () => { - - controllerModel.motionController = null; - controllerModel.remove( scene ); - scene = null; + } ); - } ); + controller.addEventListener( 'disconnected', () => { - return controllerModel; + controllerModel.motionController = null; + controllerModel.remove( scene ); + scene = null; - } + } ); - }; + return controllerModel; - return XRControllerModelFactory; + } -} )(); +} export { XRControllerModelFactory }; diff --git a/examples/jsm/webxr/XREstimatedLight.js b/examples/jsm/webxr/XREstimatedLight.js index 60c27f0b2d65d5..f9099cea60cb9b 100644 --- a/examples/jsm/webxr/XREstimatedLight.js +++ b/examples/jsm/webxr/XREstimatedLight.js @@ -3,7 +3,7 @@ import { Group, LightProbe, WebGLCubeRenderTarget -} from "../../../build/three.module.js"; +} from '../../../build/three.module.js'; class SessionLightProbe { @@ -43,11 +43,11 @@ class SessionLightProbe { this.xrWebGLBinding = new XRWebGLBinding( session, gl ); - this.lightProbe.addEventListener('reflectionchange', () => { + this.lightProbe.addEventListener( 'reflectionchange', () => { this.updateReflection(); - }); + } ); } diff --git a/examples/jsm/webxr/XRHandModelFactory.js b/examples/jsm/webxr/XRHandModelFactory.js index 1b83610271652b..3b226400fdf296 100644 --- a/examples/jsm/webxr/XRHandModelFactory.js +++ b/examples/jsm/webxr/XRHandModelFactory.js @@ -10,25 +10,23 @@ import { XRHandOculusMeshModel } from './XRHandOculusMeshModel.js'; -function XRHandModel( controller ) { +class XRHandModel extends Object3D { - Object3D.call( this ); + constructor( controller ) { - this.controller = controller; - this.motionController = null; - this.envMap = null; + super(); - this.mesh = null; + this.controller = controller; + this.motionController = null; + this.envMap = null; -} - -XRHandModel.prototype = Object.assign( Object.create( Object3D.prototype ), { + this.mesh = null; - constructor: XRHandModel, + } - updateMatrixWorld: function ( force ) { + updateMatrixWorld( force ) { - Object3D.prototype.updateMatrixWorld.call( this, force ); + super.updateMatrixWorld( force ); if ( this.motionController ) { @@ -36,78 +34,69 @@ XRHandModel.prototype = Object.assign( Object.create( Object3D.prototype ), { } - }, -} ); + } +} -const XRHandModelFactory = ( function () { +class XRHandModelFactory { - function XRHandModelFactory() { + constructor() { this.path = ''; } - XRHandModelFactory.prototype = { - - constructor: XRHandModelFactory, - - setPath: function ( path ) { + setPath( path ) { - this.path = path; - return this; + this.path = path; + return this; - }, - - createHandModel: function ( controller, profile, options ) { + } - const handModel = new XRHandModel( controller ); + createHandModel( controller, profile, options ) { - controller.addEventListener( 'connected', ( event ) => { + const handModel = new XRHandModel( controller ); - const xrInputSource = event.data; + controller.addEventListener( 'connected', ( event ) => { - if ( xrInputSource.hand && ! handModel.motionController ) { + const xrInputSource = event.data; - handModel.visible = true; - handModel.xrInputSource = xrInputSource; + if ( xrInputSource.hand && ! handModel.motionController ) { - // @todo Detect profile if not provided - if ( profile === undefined || profile === 'spheres' ) { + handModel.visible = true; + handModel.xrInputSource = xrInputSource; - handModel.motionController = new XRHandPrimitiveModel( handModel, controller, this.path, xrInputSource.handedness, { primitive: 'sphere' } ); + // @todo Detect profile if not provided + if ( profile === undefined || profile === 'spheres' ) { - } else if ( profile === 'boxes' ) { + handModel.motionController = new XRHandPrimitiveModel( handModel, controller, this.path, xrInputSource.handedness, { primitive: 'sphere' } ); - handModel.motionController = new XRHandPrimitiveModel( handModel, controller, this.path, xrInputSource.handedness, { primitive: 'box' } ); + } else if ( profile === 'boxes' ) { - } else if ( profile === 'oculus' ) { + handModel.motionController = new XRHandPrimitiveModel( handModel, controller, this.path, xrInputSource.handedness, { primitive: 'box' } ); - handModel.motionController = new XRHandOculusMeshModel( handModel, controller, this.path, xrInputSource.handedness, options ); + } else if ( profile === 'oculus' ) { - } + handModel.motionController = new XRHandOculusMeshModel( handModel, controller, this.path, xrInputSource.handedness, options ); } - } ); + } - controller.addEventListener( 'disconnected', () => { + } ); - // handModel.motionController = null; - // handModel.remove( scene ); - // scene = null; + controller.addEventListener( 'disconnected', () => { - } ); + // handModel.motionController = null; + // handModel.remove( scene ); + // scene = null; - return handModel; - - } + } ); - }; + return handModel; - return XRHandModelFactory; - -} )(); + } +} export { XRHandModelFactory }; diff --git a/examples/jsm/webxr/XRHandOculusMeshModel.js b/examples/jsm/webxr/XRHandOculusMeshModel.js index 8f5dc1c5dba09c..b52c85c508dd38 100644 --- a/examples/jsm/webxr/XRHandOculusMeshModel.js +++ b/examples/jsm/webxr/XRHandOculusMeshModel.js @@ -92,9 +92,9 @@ class XRHandOculusMeshModel { const bone = object.getObjectByName( boneName.replace( /%/g, handedness === 'right' ? 'r' : 'l' ) ); - if ( bone !== undefined) { + if ( bone !== undefined ) { - bone.jointName = joints [ i ]; + bone.jointName = joints[ i ]; } diff --git a/examples/jsm/webxr/XRHandPrimitiveModel.js b/examples/jsm/webxr/XRHandPrimitiveModel.js index adee8d124070c3..872b614c03ce68 100644 --- a/examples/jsm/webxr/XRHandPrimitiveModel.js +++ b/examples/jsm/webxr/XRHandPrimitiveModel.js @@ -1,107 +1,100 @@ import { + DynamicDrawUsage, SphereGeometry, BoxGeometry, MeshStandardMaterial, - Mesh, - Group + InstancedMesh, + Matrix4, + Vector3 } from '../../../build/three.module.js'; +const _matrix = new Matrix4(); +const _vector = new Vector3(); + class XRHandPrimitiveModel { constructor( handModel, controller, path, handedness, options ) { this.controller = controller; this.handModel = handModel; + this.envMap = null; - this.envMap = null; - - this.handMesh = new Group(); - this.handModel.add( this.handMesh ); - - if ( window.XRHand ) { + let geometry; - let geometry; + if ( ! options || ! options.primitive || options.primitive === 'sphere' ) { - if ( ! options || ! options.primitive || options.primitive === 'sphere' ) { + geometry = new SphereGeometry( 1, 10, 10 ); - geometry = new SphereGeometry( 1, 10, 10 ); + } else if ( options.primitive === 'box' ) { - } else if ( options.primitive === 'box' ) { + geometry = new BoxGeometry( 1, 1, 1 ); - geometry = new BoxGeometry( 1, 1, 1 ); - - } + } - const jointMaterial = new MeshStandardMaterial( { color: 0xffffff, roughness: 1, metalness: 0 } ); - const tipMaterial = new MeshStandardMaterial( { color: 0x999999, roughness: 1, metalness: 0 } ); - - const joints = [ - 'wrist', - 'thumb-metacarpal', - 'thumb-phalanx-proximal', - 'thumb-phalanx-distal', - 'thumb-tip', - 'index-finger-metacarpal', - 'index-finger-phalanx-proximal', - 'index-finger-phalanx-intermediate', - 'index-finger-phalanx-distal', - 'index-finger-tip', - 'middle-finger-metacarpal', - 'middle-finger-phalanx-proximal', - 'middle-finger-phalanx-intermediate', - 'middle-finger-phalanx-distal', - 'middle-finger-tip', - 'ring-finger-metacarpal', - 'ring-finger-phalanx-proximal', - 'ring-finger-phalanx-intermediate', - 'ring-finger-phalanx-distal', - 'ring-finger-tip', - 'pinky-finger-metacarpal', - 'pinky-finger-phalanx-proximal', - 'pinky-finger-phalanx-intermediate', - 'pinky-finger-phalanx-distal', - 'pinky-finger-tip' - ]; - - for ( const jointName of joints ) { - - var cube = new Mesh( geometry, jointName.indexOf( 'tip' ) !== - 1 ? tipMaterial : jointMaterial ); - cube.castShadow = true; - cube.receiveShadow = true; - cube.jointName = jointName; - this.handMesh.add( cube ); + const material = new MeshStandardMaterial(); - } + this.handMesh = new InstancedMesh( geometry, material, 30 ); + this.handMesh.instanceMatrix.setUsage( DynamicDrawUsage ); // will be updated every frame + this.handMesh.castShadow = true; + this.handMesh.receiveShadow = true; + this.handModel.add( this.handMesh ); - } + this.joints = [ + 'wrist', + 'thumb-metacarpal', + 'thumb-phalanx-proximal', + 'thumb-phalanx-distal', + 'thumb-tip', + 'index-finger-metacarpal', + 'index-finger-phalanx-proximal', + 'index-finger-phalanx-intermediate', + 'index-finger-phalanx-distal', + 'index-finger-tip', + 'middle-finger-metacarpal', + 'middle-finger-phalanx-proximal', + 'middle-finger-phalanx-intermediate', + 'middle-finger-phalanx-distal', + 'middle-finger-tip', + 'ring-finger-metacarpal', + 'ring-finger-phalanx-proximal', + 'ring-finger-phalanx-intermediate', + 'ring-finger-phalanx-distal', + 'ring-finger-tip', + 'pinky-finger-metacarpal', + 'pinky-finger-phalanx-proximal', + 'pinky-finger-phalanx-intermediate', + 'pinky-finger-phalanx-distal', + 'pinky-finger-tip' + ]; } updateMesh() { const defaultRadius = 0.008; - const objects = this.handMesh.children; + const joints = this.controller.joints; - // XR Joints - const XRJoints = this.controller.joints; + let count = 0; - for ( let i = 0; i < objects.length; i ++ ) { + for ( let i = 0; i < this.joints.length; i ++ ) { - const jointMesh = objects[ i ]; - const XRJoint = XRJoints[ jointMesh.jointName ]; + const joint = joints[ this.joints[ i ] ]; - if ( XRJoint.visible ) { + if ( joint.visible ) { - jointMesh.position.copy( XRJoint.position ); - jointMesh.quaternion.copy( XRJoint.quaternion ); - jointMesh.scale.setScalar( XRJoint.jointRadius || defaultRadius ); + _vector.setScalar( joint.jointRadius || defaultRadius ); + _matrix.compose( joint.position, joint.quaternion, _vector ); + this.handMesh.setMatrixAt( i, _matrix ); - } + count ++; - jointMesh.visible = XRJoint.visible; + } } + this.handMesh.count = count; + this.handMesh.instanceMatrix.needsUpdate = true; + } } diff --git a/examples/models/xfile/SSR06_model.x b/examples/models/xfile/SSR06_model.x deleted file mode 100644 index 5dcca732282a9e..00000000000000 --- a/examples/models/xfile/SSR06_model.x +++ /dev/null @@ -1,52304 +0,0 @@ -xof 0303txt 0032 - -template XSkinMeshHeader { - <3cf169ce-ff7c-44ab-93c0-f78f62d172e2> - WORD nMaxSkinWeightsPerVertex; - WORD nMaxSkinWeightsPerFace; - WORD nBones; -} - -template VertexDuplicationIndices { - - DWORD nIndices; - DWORD nOriginalVertices; - array DWORD indices[nIndices]; -} - -template SkinWeights { - <6f0d123b-bad2-4167-a0d0-80224f25fabb> - STRING transformNodeName; - DWORD nWeights; - array DWORD vertexIndices[nWeights]; - array FLOAT weights[nWeights]; - Matrix4x4 matrixOffset; -} - - -Frame Frame_SCENE_ROOT { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; - } - - Frame AllPutting_2_Layer1 { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; - } - - Mesh Mesh_AllPutting_2 { - 6202; - -1.157854;10.366903;1.400000;, - -1.157854;10.366903;-0.100000;, - -1.157854;8.063718;-0.200000;, - -1.157854;8.063718;1.400000;, - 0.000000;8.634896;-0.380000;, - -0.753840;8.634896;-0.380000;, - -0.753840;8.634896;-1.450000;, - 0.000000;8.634896;-1.450000;, - 0.000000;8.335782;1.300000;, - 0.000000;8.335782;-1.400000;, - -0.540000;6.512889;-1.250000;, - -0.540000;5.747889;-1.250000;, - 0.000000;4.472888;-1.360000;, - 0.000000;4.472888;1.400000;, - 0.000000;11.460281;0.922292;, - 0.000000;10.728957;0.922292;, - -0.320198;10.985079;1.340562;, - 0.000000;10.957540;1.928746;, - 0.000000;10.370019;1.071678;, - 0.000000;9.564607;-0.920000;, - -0.783621;9.564607;-0.920000;, - -0.783621;10.114978;1.320000;, - 0.000000;10.114978;1.320000;, - 0.000000;10.031889;1.000000;, - 0.000000;10.031889;0.150000;, - 0.000000;8.346831;-1.092274;, - 0.000000;8.844754;-2.226006;, - 0.000000;5.122600;-1.365000;, - 0.000000;4.439500;-1.365000;, - -1.650000;0.372590;-1.341000;, - -1.650000;0.012590;-1.341000;, - 0.000000;8.377817;2.627000;, - 0.000000;8.860044;2.627000;, - 0.000000;9.017695;1.730000;, - 0.000000;8.229440;1.730000;, - -1.054643;0.540345;-0.085888;, - -1.088500;6.391939;-0.509769;, - -1.586200;4.409444;-1.192000;, - -1.586200;4.409444;-0.991000;, - -1.586200;4.409444;-0.690000;, - -1.120000;2.735444;0.089000;, - -0.580000;2.735444;0.089000;, - -1.235402;0.607264;0.837000;, - -1.354000;0.372590;-1.341000;, - -1.354000;0.012590;-1.341000;, - -1.354000;0.552590;-0.191000;, - -1.354000;1.092590;-1.341000;, - -1.120000;2.285444;0.209000;, - -2.198000;-0.032410;-2.691000;, - -2.198000;-0.032410;-2.691000;, - -2.198000;0.057590;-2.841000;, - -2.198000;0.057590;-2.841000;, - -2.198000;0.057590;-2.841000;, - -1.650000;-0.032410;-2.691000;, - -1.650000;0.057590;-2.841000;, - -1.650000;0.057590;-2.841000;, - -1.102000;-0.032410;-2.691000;, - -1.102000;-0.032410;-2.691000;, - -1.102000;0.057590;-2.841000;, - -1.102000;0.057590;-2.841000;, - -1.102000;0.057590;-2.841000;, - -0.297220;5.130789;-2.375762;, - -0.297220;5.130789;-2.375762;, - -0.355000;5.248089;-2.490761;, - -0.355000;5.248089;-2.490761;, - -0.243220;4.404039;-2.145761;, - -0.243220;4.404039;-2.145761;, - -0.243220;4.404039;-2.145761;, - 0.000000;5.248089;-2.490761;, - 0.000000;4.404039;-2.145761;, - 0.000000;4.404039;-2.145761;, - 0.000000;5.130789;-2.375762;, - -0.355000;6.604689;-2.188261;, - -0.355000;6.604689;-2.188261;, - -0.355000;6.604689;-2.188261;, - -0.355000;6.604689;-2.188261;, - -0.355000;6.533288;-2.185761;, - -0.355000;6.533288;-2.185761;, - -0.355000;6.533288;-2.185761;, - -0.355000;6.533288;-2.185761;, - 0.000000;6.533288;-2.185761;, - 0.000000;6.533288;-2.185761;, - 0.000000;6.604689;-2.188261;, - 0.000000;6.604689;-2.188261;, - -0.434700;8.568343;-2.243182;, - -0.434700;8.568343;-2.243182;, - -0.348300;8.592272;-2.323182;, - -0.348300;8.592272;-2.323182;, - -0.348300;8.592272;-2.323182;, - 0.000000;8.592272;-2.323182;, - -0.621000;8.938809;-2.187204;, - -0.621000;8.938809;-2.187204;, - -0.621000;9.443933;-2.105358;, - -0.621000;9.443933;-2.105358;, - -0.434700;8.887272;-2.277475;, - -0.434700;8.887272;-2.277475;, - -0.434700;9.518987;-2.158886;, - -0.434700;9.634454;-2.098433;, - -0.434700;9.634454;-2.098433;, - -0.434700;8.796896;-2.166006;, - -0.348300;8.844754;-2.226006;, - -0.348300;8.844754;-2.226006;, - 0.000000;8.887272;-2.277475;, - 0.000000;8.887272;-2.277475;, - 0.000000;9.518987;-2.158886;, - 0.000000;9.634454;-2.098433;, - 0.000000;9.634454;-2.098433;, - -2.090000;0.642590;-1.891000;, - -2.090000;0.642590;-1.891000;, - -2.090000;0.642590;-1.891000;, - -1.946000;0.642590;-1.891000;, - -1.946000;0.642590;-1.891000;, - -2.198000;-0.032410;-1.921000;, - -2.198000;-0.032410;-1.921000;, - -2.198000;0.597590;-1.921000;, - -2.198000;0.597590;-1.921000;, - -1.650000;0.642590;-1.891000;, - -1.650000;0.642590;-1.891000;, - -1.650000;-0.032410;-1.921000;, - -1.650000;0.597590;-1.921000;, - -1.210000;0.642590;-1.891000;, - -1.210000;0.642590;-1.891000;, - -1.210000;0.642590;-1.891000;, - -1.354000;0.642590;-1.891000;, - -1.354000;0.642590;-1.891000;, - -1.102000;-0.032410;-1.921000;, - -1.102000;-0.032410;-1.921000;, - -1.102000;0.597590;-1.921000;, - -1.102000;0.597590;-1.921000;, - -2.211500;5.076511;-1.462134;, - -2.211500;5.076511;-1.462134;, - -2.211500;5.076511;-1.462134;, - -1.650000;5.076511;-1.462134;, - -1.650000;5.076511;-1.462134;, - -1.088500;5.076511;-1.462134;, - -1.088500;5.076511;-1.462134;, - -1.088500;5.076511;-1.462134;, - -0.455220;5.130789;-1.383261;, - -0.455220;5.130789;-1.383261;, - -0.455220;5.130789;-1.383261;, - -0.455220;5.130789;-1.383261;, - -0.401220;4.404039;-1.383261;, - -0.401220;4.404039;-1.383261;, - -0.401220;4.404039;-1.383261;, - -0.540000;5.747889;-1.600000;, - -0.540000;5.747889;-1.600000;, - -0.864000;5.747889;-1.600000;, - -0.864000;5.747889;-1.600000;, - -0.864000;5.747889;-1.600000;, - -0.270000;4.472888;-1.360000;, - -0.270000;4.472888;-1.360000;, - -0.270000;5.747889;-1.600000;, - -0.270000;5.747889;-1.600000;, - -0.270000;5.747889;-1.600000;, - 0.000000;5.747889;-1.600000;, - 0.000000;5.747889;-1.600000;, - 0.000000;5.130789;-1.383261;, - 0.000000;4.404039;-1.383261;, - 0.000000;4.404039;-1.383261;, - -0.344000;4.439500;-1.365000;, - -0.344000;4.439500;-1.365000;, - -0.434000;5.122600;-1.365000;, - -0.434000;5.122600;-1.365000;, - -0.442800;7.096839;-1.498261;, - -0.442800;7.096839;-1.498261;, - -0.442800;7.096839;-1.498261;, - -0.246460;6.979538;-2.088261;, - -0.246460;6.979538;-2.088261;, - -0.246460;6.979538;-2.088261;, - -0.864000;6.512889;-1.600000;, - -0.864000;6.512889;-1.600000;, - -0.864000;6.512889;-1.600000;, - -0.540000;6.512889;-1.600000;, - -0.540000;6.512889;-1.600000;, - 0.000000;6.979538;-2.088261;, - 0.000000;6.979538;-2.088261;, - 0.000000;7.096839;-1.498261;, - 0.000000;7.096839;-1.498261;, - -1.217160;8.469534;-1.810000;, - -1.217160;8.469534;-1.810000;, - -1.490400;8.469534;-1.586000;, - -1.490400;8.469534;-1.586000;, - -1.490400;8.469534;-1.586000;, - -1.490400;8.469534;-1.586000;, - -1.490400;8.469534;-1.746000;, - -1.490400;8.469534;-1.746000;, - -1.490400;8.469534;-1.746000;, - -1.304100;8.397746;-1.570000;, - -1.304100;8.397746;-1.570000;, - -1.304100;8.397746;-1.730000;, - -1.304100;8.397746;-1.730000;, - -1.304100;8.397746;-1.730000;, - -1.403460;8.547303;-1.830000;, - -0.360180;8.335782;-1.400000;, - -0.360180;8.335782;-1.400000;, - -0.621000;8.497011;-1.571497;, - -0.621000;8.497011;-1.571497;, - -0.621000;8.497011;-1.571497;, - -0.434700;8.321987;-1.506799;, - -0.434700;8.321987;-1.506799;, - -0.434700;8.321987;-1.506799;, - -0.434700;8.210368;-1.631449;, - -0.434700;7.903518;-1.723446;, - -0.434700;7.903518;-1.723446;, - -0.434700;8.703467;-2.074645;, - -0.348300;7.831731;-1.743446;, - -0.348300;7.831731;-1.743446;, - -0.348300;7.831731;-1.743446;, - -0.348300;7.831731;-1.743446;, - -0.720360;8.469534;-1.810000;, - -0.720360;8.469534;-1.810000;, - -0.621000;8.397746;-1.570000;, - -0.621000;8.397746;-1.570000;, - -0.621000;8.397746;-1.570000;, - -0.621000;8.397746;-1.730000;, - -0.621000;8.397746;-1.730000;, - -0.621000;8.397746;-1.730000;, - -0.621000;8.397746;-1.730000;, - 0.000000;8.321987;-1.506799;, - 0.000000;8.321987;-1.506799;, - 0.000000;7.831731;-1.743446;, - 0.000000;7.831731;-1.743446;, - -1.217160;9.041694;-2.060000;, - -1.490400;9.095534;-1.850000;, - -1.490400;9.095534;-1.850000;, - -1.490400;9.095534;-1.850000;, - -1.490400;9.095534;-1.850000;, - -1.490400;9.041694;-1.990000;, - -1.490400;9.041694;-1.990000;, - -1.304100;9.191251;-1.870000;, - -1.304100;9.191251;-1.870000;, - -1.304100;9.137410;-2.010000;, - -1.304100;9.137410;-2.010000;, - -1.403460;8.945976;-2.040000;, - -0.621000;9.099913;-1.933061;, - -0.621000;9.563389;-2.052839;, - -0.621000;9.563389;-2.052839;, - -0.621000;9.370822;-1.468720;, - -0.621000;9.720506;-1.617303;, - -0.621000;9.794942;-1.642888;, - -0.621000;9.794942;-1.642888;, - -0.434700;9.875455;-1.670560;, - -0.434700;8.921729;-1.855520;, - -0.348300;8.993517;-1.835520;, - -0.720360;9.041694;-2.060000;, - -0.621000;9.191251;-1.870000;, - -0.621000;9.191251;-1.870000;, - -0.621000;9.191251;-1.870000;, - -0.621000;9.137410;-2.010000;, - -0.621000;9.137410;-2.010000;, - -0.621000;9.137410;-2.010000;, - -0.621000;9.137410;-2.010000;, - 0.000000;9.875455;-1.670560;, - -2.090000;0.372590;-1.341000;, - -2.090000;0.372590;-1.341000;, - -2.090000;1.092590;-1.341000;, - -2.090000;1.092590;-1.341000;, - -1.946000;0.372590;-1.341000;, - -2.090000;0.012590;-1.341000;, - -2.090000;0.012590;-1.341000;, - -1.946000;0.012590;-1.341000;, - -1.946000;1.092590;-1.341000;, - -2.198000;-0.032410;-0.991000;, - -2.198000;-0.032410;-0.991000;, - -2.198000;-0.032410;-0.991000;, - -2.198000;0.597590;-0.991000;, - -2.198000;0.597590;-0.991000;, - -2.198000;0.597590;-0.991000;, - -2.225000;0.870444;-1.191000;, - -2.225000;0.870444;-1.191000;, - -2.225000;0.870444;-1.191000;, - -1.650000;1.092590;-1.341000;, - -1.650000;-0.032410;-0.991000;, - -1.650000;-0.032410;-0.991000;, - -1.650000;0.597590;-0.991000;, - -1.650000;0.597590;-0.991000;, - -1.650000;0.870444;-1.191000;, - -1.650000;0.870444;-1.191000;, - -1.210000;0.372590;-1.341000;, - -1.210000;0.372590;-1.341000;, - -1.210000;1.092590;-1.341000;, - -1.210000;1.092590;-1.341000;, - -1.210000;0.012590;-1.341000;, - -1.210000;0.012590;-1.341000;, - -1.102000;-0.032410;-0.991000;, - -1.102000;-0.032410;-0.991000;, - -1.102000;-0.032410;-0.991000;, - -1.102000;0.597590;-0.991000;, - -1.102000;0.597590;-0.991000;, - -1.102000;0.597590;-0.991000;, - -1.075000;0.870444;-1.191000;, - -1.075000;0.870444;-1.191000;, - -1.075000;0.870444;-1.191000;, - -2.139500;2.834444;-1.291000;, - -2.139500;2.834444;-1.291000;, - -2.139500;2.519444;-0.991000;, - -2.139500;2.519444;-0.991000;, - -2.139500;2.519444;-0.991000;, - -2.630000;2.735444;-0.831000;, - -2.630000;2.735444;-0.831000;, - -2.630000;2.735444;-0.831000;, - -2.180000;2.735444;-0.831000;, - -2.180000;2.735444;-0.831000;, - -2.180000;2.735444;-0.831000;, - -1.650000;2.834444;-1.291000;, - -1.650000;2.519444;-0.991000;, - -1.650000;2.519444;-0.991000;, - -1.160500;2.834444;-1.291000;, - -1.160500;2.834444;-1.291000;, - -1.160500;2.519444;-0.991000;, - -1.160500;2.519444;-0.991000;, - -1.160500;2.519444;-0.991000;, - -1.120000;2.735444;-0.831000;, - -1.120000;2.735444;-0.831000;, - -1.120000;2.735444;-0.831000;, - -0.670000;2.735444;-0.831000;, - -0.670000;2.735444;-0.831000;, - -0.670000;2.735444;-0.831000;, - -2.139500;4.319444;-1.291000;, - -2.139500;4.319444;-1.291000;, - -2.139500;4.319444;-1.291000;, - -2.139500;4.319444;-1.291000;, - -2.139500;4.319444;-0.991000;, - -2.139500;4.319444;-0.991000;, - -2.630000;4.040444;-0.831000;, - -2.630000;4.040444;-0.831000;, - -2.630000;4.040444;-0.831000;, - -2.180000;4.040444;-0.831000;, - -2.180000;4.040444;-0.831000;, - -2.180000;4.040444;-0.831000;, - -1.961750;3.663552;-0.683854;, - -1.961750;3.663552;-0.683854;, - -1.961750;4.011917;-0.683854;, - -1.961750;4.011917;-0.683854;, - -1.650000;4.319444;-1.291000;, - -1.650000;4.319444;-1.291000;, - -1.650000;4.319444;-0.991000;, - -1.650000;4.319444;-0.991000;, - -1.650000;4.011917;-0.683854;, - -1.650000;4.011917;-0.683854;, - -1.650000;3.663552;-0.683854;, - -1.650000;3.663552;-0.683854;, - -1.160500;4.319444;-1.291000;, - -1.160500;4.319444;-1.291000;, - -1.160500;4.319444;-1.291000;, - -1.160500;4.319444;-1.291000;, - -1.160500;4.319444;-0.991000;, - -1.160500;4.319444;-0.991000;, - -1.120000;4.040444;-0.831000;, - -1.120000;4.040444;-0.831000;, - -1.120000;4.040444;-0.831000;, - -1.338250;3.663552;-0.683854;, - -1.338250;3.663552;-0.683854;, - -1.338250;4.011917;-0.683854;, - -1.338250;4.011917;-0.683854;, - -0.670000;4.040444;-0.831000;, - -0.670000;4.040444;-0.831000;, - -0.670000;4.040444;-0.831000;, - -2.211500;4.896544;-1.134769;, - -2.211500;4.896544;-1.134769;, - -2.211500;4.896544;-1.134769;, - -2.183926;5.309234;-0.707269;, - -2.183926;5.309234;-0.707269;, - -2.070200;4.409444;-1.192000;, - -2.070200;4.409444;-1.192000;, - -2.070200;4.409444;-0.991000;, - -2.070200;4.409444;-0.991000;, - -2.070200;4.409444;-0.690000;, - -2.070200;4.409444;-0.690000;, - -1.650000;4.898689;-1.134137;, - -1.650000;4.898689;-1.134137;, - -1.108550;5.309234;-0.707269;, - -1.108550;5.309234;-0.707269;, - -1.713800;4.409444;-1.192000;, - -1.713800;4.409444;-0.991000;, - -1.713800;4.409444;-0.690000;, - -1.088500;4.896544;-1.134769;, - -1.088500;4.896544;-1.134769;, - -1.088500;4.896544;-1.134769;, - -1.229800;4.409444;-1.192000;, - -1.229800;4.409444;-1.192000;, - -1.229800;4.409444;-0.991000;, - -1.229800;4.409444;-0.991000;, - -1.229800;4.409444;-0.690000;, - -1.229800;4.409444;-0.690000;, - -0.567000;5.248089;-1.268261;, - -0.567000;5.248089;-1.268261;, - -0.567000;5.248089;-1.268261;, - -0.567000;5.248089;-1.268261;, - -0.864000;5.747889;-1.250000;, - -0.864000;5.747889;-1.250000;, - -0.864000;5.747889;-1.200000;, - -0.864000;5.747889;-1.200000;, - -0.864000;5.747889;-1.200000;, - -0.270000;5.747889;-1.200000;, - -0.270000;5.747889;-1.200000;, - -0.270000;5.747889;-1.200000;, - -0.270000;5.747889;-1.200000;, - 0.000000;5.747889;-1.200000;, - 0.000000;5.747889;-1.200000;, - -0.270000;4.472888;-1.200000;, - 0.000000;5.248089;-1.268261;, - -2.211500;6.504799;-0.897269;, - -2.211500;6.504799;-0.897269;, - -2.211500;6.899809;-0.659769;, - -2.211500;6.899809;-0.659769;, - -2.211500;6.899809;-0.659769;, - -2.211500;6.270950;-1.294258;, - -2.211500;6.270950;-1.294258;, - -1.650000;6.899809;-0.659769;, - -1.650000;6.899809;-0.659769;, - -1.650000;6.504799;-0.897269;, - -1.650000;6.270950;-1.294258;, - -1.088500;6.504799;-0.897269;, - -1.088500;6.504799;-0.897269;, - -1.088500;6.899809;-0.659769;, - -1.088500;6.899809;-0.659769;, - -1.088500;6.899809;-0.659769;, - -1.088500;6.270950;-1.294258;, - -1.088500;6.270950;-1.294258;, - 0.000000;6.553689;-1.234434;, - 0.000000;6.553689;-1.234434;, - -0.434700;6.553689;-1.234434;, - -0.434700;6.553689;-1.234434;, - -0.434700;6.553689;-1.234434;, - 0.000000;7.226889;-0.950000;, - -0.434700;7.226889;-0.950000;, - -0.434700;7.226889;-0.950000;, - -0.567000;6.604689;-1.268261;, - -0.567000;6.604689;-1.268261;, - -0.567000;6.604689;-1.268261;, - -0.567000;6.533288;-1.268261;, - -0.567000;6.533288;-1.268261;, - -0.567000;6.533288;-1.268261;, - -0.864000;6.512889;-1.250000;, - -0.864000;6.512889;-1.250000;, - -0.864000;6.512889;-1.200000;, - -0.864000;6.512889;-1.200000;, - -0.864000;6.512889;-1.200000;, - -0.270000;6.512889;-1.200000;, - -0.270000;6.512889;-1.200000;, - -0.270000;6.512889;-1.200000;, - 0.000000;6.512889;-1.200000;, - 0.000000;6.512889;-1.200000;, - 0.000000;6.604689;-1.268261;, - 0.000000;6.533288;-1.268261;, - 0.000000;8.299889;-1.100000;, - -0.645840;8.299889;-1.100000;, - -0.621000;8.494646;-1.080509;, - -0.621000;8.494646;-1.080509;, - -0.434700;8.323646;-1.004743;, - -0.434700;8.323646;-1.004743;, - -0.434700;8.322903;-1.172274;, - -0.434700;8.322903;-1.172274;, - -0.434700;7.901668;-1.294773;, - -0.434700;7.901668;-1.294773;, - -0.434700;7.901668;-1.294773;, - -0.348300;7.829880;-1.234773;, - -0.348300;7.829880;-1.234773;, - -0.348300;8.346831;-1.092274;, - -0.348300;8.346831;-1.092274;, - 0.000000;7.829880;-1.234773;, - 0.000000;8.323646;-1.004743;, - -0.434700;9.853403;-0.652941;, - -0.434700;9.853403;-0.652941;, - -0.621000;9.772565;-0.734962;, - -0.621000;9.772565;-0.734962;, - -0.621000;9.772565;-0.734962;, - -0.434700;10.156014;-0.776952;, - -0.434700;10.156014;-0.776952;, - -0.621000;10.117581;-0.864687;, - -0.621000;10.117581;-0.864687;, - -0.621000;10.154878;-0.975241;, - -0.621000;10.154878;-0.975241;, - 0.000000;10.156014;-0.776952;, - 0.000000;10.156014;-0.776952;, - 0.000000;9.853403;-0.652941;, - 0.000000;9.853403;-0.652941;, - -0.434700;10.240253;-0.992427;, - -0.280461;11.060905;-0.923241;, - -0.280461;11.060905;-0.923241;, - -0.233382;11.060905;-1.068951;, - -0.233382;11.060905;-1.068951;, - -0.233382;11.060905;-1.068951;, - -0.233382;11.060905;-1.068951;, - -0.233382;11.029785;-1.068951;, - -0.233382;11.029785;-1.068951;, - -0.233382;11.029785;-1.068951;, - -0.233382;11.029785;-1.068951;, - -0.280461;11.029785;-0.923241;, - -0.280461;11.029785;-0.923241;, - 0.000000;11.282440;-1.066862;, - 0.000000;11.282440;-1.066862;, - -0.124377;11.282440;-1.066862;, - -0.124377;11.282440;-1.066862;, - -0.203526;11.356547;-0.927240;, - 0.000000;11.356547;-0.927240;, - -0.226140;11.261694;-1.066862;, - -0.226140;11.261694;-1.066862;, - -0.226140;11.261694;-1.066862;, - -0.282675;11.325428;-0.927240;, - -0.282675;11.325428;-0.927240;, - 0.000000;10.863811;-1.066862;, - 0.000000;10.863811;-1.066862;, - 0.000000;10.749704;-0.927240;, - -0.192219;10.749704;-0.927240;, - -0.124377;10.863811;-1.066862;, - -0.124377;10.863811;-1.066862;, - -0.282675;10.780824;-0.927240;, - -0.282675;10.780824;-0.927240;, - -0.226140;10.884558;-1.066862;, - -0.226140;10.884558;-1.066862;, - -0.226140;10.884558;-1.066862;, - 0.000000;11.232752;-1.023456;, - 0.000000;11.080467;-1.023456;, - -0.113559;11.059278;-1.023456;, - -0.113559;11.059278;-1.023456;, - -0.078358;11.232752;-1.023456;, - 0.000000;11.010952;-1.023456;, - -0.113643;11.032139;-1.023456;, - -0.113643;11.032139;-1.023456;, - -0.158298;11.060905;-1.067771;, - -0.158298;11.060905;-1.067771;, - -0.158298;11.060905;-1.067771;, - -0.158298;11.029785;-1.067771;, - -0.158298;11.029785;-1.067771;, - -0.158298;11.029785;-1.067771;, - 0.000000;10.913136;-1.023456;, - -0.078358;10.913136;-1.023456;, - 0.000000;10.240253;-0.992427;, - -2.090000;0.552590;-0.191000;, - -2.090000;0.552590;-0.191000;, - -2.090000;0.777590;-0.191000;, - -2.090000;0.777590;-0.191000;, - -2.090000;0.777590;-0.191000;, - -2.090000;0.012590;-0.491000;, - -2.090000;0.012590;-0.491000;, - -2.090000;0.012590;-0.491000;, - -1.946000;0.012590;-0.491000;, - -1.946000;0.012590;-0.491000;, - -1.946000;0.552590;-0.191000;, - -1.946000;0.777590;-0.191000;, - -1.946000;0.777590;-0.191000;, - -1.650000;0.012590;-0.491000;, - -1.650000;0.012590;-0.491000;, - -1.650000;0.552590;-0.191000;, - -1.650000;0.777590;-0.191000;, - -1.650000;0.777590;-0.191000;, - -1.210000;0.552590;-0.191000;, - -1.210000;0.552590;-0.191000;, - -1.210000;0.777590;-0.191000;, - -1.210000;0.777590;-0.191000;, - -1.210000;0.777590;-0.191000;, - -1.210000;0.012590;-0.491000;, - -1.210000;0.012590;-0.491000;, - -1.210000;0.012590;-0.491000;, - -1.354000;0.012590;-0.491000;, - -1.354000;0.012590;-0.491000;, - -1.354000;0.777590;-0.191000;, - -1.354000;0.777590;-0.191000;, - -2.720000;2.735444;0.089000;, - -2.139500;2.519444;-0.591000;, - -2.139500;2.519444;-0.591000;, - -2.139500;2.519444;-0.591000;, - -2.180000;2.150444;0.089000;, - -2.180000;2.150444;0.089000;, - -2.180000;2.150444;0.089000;, - -2.630000;2.150444;0.089000;, - -2.630000;2.150444;0.089000;, - -2.630000;2.150444;0.089000;, - -2.180000;2.735444;0.089000;, - -2.180000;2.465444;-0.591000;, - -2.180000;2.465444;-0.591000;, - -1.650000;2.519444;-0.591000;, - -1.650000;2.519444;-0.591000;, - -1.650000;2.465444;-0.591000;, - -1.160500;2.519444;-0.591000;, - -1.160500;2.519444;-0.591000;, - -1.160500;2.519444;-0.591000;, - -1.120000;2.150444;0.089000;, - -1.120000;2.150444;0.089000;, - -1.120000;2.150444;0.089000;, - -1.120000;2.465444;-0.591000;, - -1.120000;2.465444;-0.591000;, - -0.670000;2.150444;0.089000;, - -0.670000;2.150444;0.089000;, - -0.670000;2.150444;0.089000;, - -2.720000;4.040444;0.089000;, - -2.720000;4.040444;0.089000;, - -2.191610;0.736228;-0.303535;, - -2.191610;0.736228;-0.303535;, - -2.191610;0.736228;-0.303535;, - -2.191610;0.540345;-0.393688;, - -2.191610;0.540345;-0.393688;, - -2.191610;0.344462;-0.303535;, - -2.191610;0.344462;-0.303535;, - -2.191610;0.344462;-0.303535;, - -2.191610;0.263325;-0.085888;, - -2.191610;0.263325;-0.085888;, - -2.238357;0.540345;-0.085888;, - -2.041625;4.121234;-0.469769;, - -2.041625;4.121234;-0.469769;, - -2.041625;4.121234;-0.469769;, - -2.139500;4.319444;-0.591000;, - -2.139500;4.319444;-0.591000;, - -2.139500;4.319444;-0.591000;, - -2.139500;4.319444;-0.591000;, - -2.180000;4.040444;0.089000;, - -2.180000;4.040444;0.089000;, - -2.180000;3.545444;-0.591000;, - -2.180000;3.545444;-0.591000;, - -2.180000;3.545444;-0.591000;, - -1.961750;4.067234;0.059254;, - -1.961750;4.067234;0.059254;, - -1.961750;4.067234;0.059254;, - -1.961750;4.067234;-0.583346;, - -1.961750;4.067234;-0.583346;, - -1.961750;4.067234;-0.583346;, - -1.961750;3.608234;0.059254;, - -1.961750;3.608234;0.059254;, - -1.961750;3.608234;0.059254;, - -1.961750;3.034714;0.059254;, - -1.961750;3.034714;0.059254;, - -1.961750;3.608234;-0.583346;, - -1.961750;3.608234;-0.583346;, - -1.961750;3.608234;-0.583346;, - -1.961750;3.202694;-0.395133;, - -1.961750;3.202694;-0.395133;, - -1.961750;3.202694;-0.395133;, - -2.096750;3.654134;-0.583346;, - -2.096750;3.654134;-0.583346;, - -2.096750;3.654134;-0.583346;, - -2.096750;3.654134;0.059254;, - -2.096750;3.654134;0.059254;, - -2.096750;3.654134;0.059254;, - -2.096750;4.021334;0.059254;, - -2.096750;4.021334;0.059254;, - -2.096750;4.021334;0.059254;, - -2.096750;4.021334;-0.583346;, - -2.096750;4.021334;-0.583346;, - -2.096750;4.021334;-0.583346;, - -1.646500;0.736228;-0.303535;, - -1.646500;0.736228;-0.303535;, - -1.646500;0.540345;-0.393688;, - -1.646500;0.344462;-0.303535;, - -1.646500;0.344462;-0.303535;, - -1.646500;0.263325;-0.085888;, - -1.208000;4.121234;-0.469769;, - -1.208000;4.121234;-0.469769;, - -1.208000;4.121234;-0.469769;, - -1.650000;4.319444;-0.591000;, - -1.650000;4.319444;-0.591000;, - -1.650000;3.545444;-0.591000;, - -1.650000;3.545444;-0.591000;, - -1.650000;4.067234;-0.583346;, - -1.650000;4.067234;-0.583346;, - -1.650000;3.202694;-0.395133;, - -1.650000;3.202694;-0.395133;, - -1.650000;3.034714;0.059254;, - -1.650000;3.608234;-0.583346;, - -1.650000;3.608234;-0.583346;, - -1.101390;0.736228;-0.303535;, - -1.101390;0.736228;-0.303535;, - -1.101390;0.736228;-0.303535;, - -1.101390;0.540345;-0.393688;, - -1.101390;0.540345;-0.393688;, - -1.101390;0.344462;-0.303535;, - -1.101390;0.344462;-0.303535;, - -1.101390;0.344462;-0.303535;, - -1.101390;0.263325;-0.085888;, - -1.101390;0.263325;-0.085888;, - -1.160500;4.319444;-0.591000;, - -1.160500;4.319444;-0.591000;, - -1.160500;4.319444;-0.591000;, - -1.160500;4.319444;-0.591000;, - -1.120000;4.040444;0.089000;, - -1.120000;4.040444;0.089000;, - -1.120000;3.545444;-0.591000;, - -1.120000;3.545444;-0.591000;, - -1.120000;3.545444;-0.591000;, - -1.338250;4.067234;0.059254;, - -1.338250;4.067234;0.059254;, - -1.338250;4.067234;0.059254;, - -1.338250;4.067234;-0.583346;, - -1.338250;4.067234;-0.583346;, - -1.338250;4.067234;-0.583346;, - -1.338250;3.608234;0.059254;, - -1.338250;3.608234;0.059254;, - -1.338250;3.608234;0.059254;, - -1.338250;3.034714;0.059254;, - -1.338250;3.034714;0.059254;, - -1.338250;3.608234;-0.583346;, - -1.338250;3.608234;-0.583346;, - -1.338250;3.608234;-0.583346;, - -1.338250;3.202694;-0.395133;, - -1.338250;3.202694;-0.395133;, - -1.338250;3.202694;-0.395133;, - -1.203250;3.654134;-0.583346;, - -1.203250;3.654134;-0.583346;, - -1.203250;3.654134;-0.583346;, - -1.203250;3.654134;0.059254;, - -1.203250;3.654134;0.059254;, - -1.203250;3.654134;0.059254;, - -1.203250;4.021334;0.059254;, - -1.203250;4.021334;0.059254;, - -1.203250;4.021334;0.059254;, - -1.203250;4.021334;-0.583346;, - -1.203250;4.021334;-0.583346;, - -1.203250;4.021334;-0.583346;, - -0.580000;4.040444;0.089000;, - -0.580000;4.040444;0.089000;, - -2.191610;0.817365;-0.085888;, - -2.191610;0.817365;-0.085888;, - -1.961750;4.640755;0.059254;, - -1.961750;4.640755;0.059254;, - -1.961750;4.472775;-0.395133;, - -1.961750;4.472775;-0.395133;, - -1.961750;4.472775;-0.395133;, - -1.646500;0.817365;-0.085888;, - -1.650000;4.640755;0.059254;, - -1.650000;4.472775;-0.395133;, - -1.650000;4.472775;-0.395133;, - -1.101390;0.817365;-0.085888;, - -1.101390;0.817365;-0.085888;, - -1.338250;4.640755;0.059254;, - -1.338250;4.640755;0.059254;, - -1.338250;4.472775;-0.395133;, - -1.338250;4.472775;-0.395133;, - -1.338250;4.472775;-0.395133;, - -5.537655;7.308371;-0.122373;, - -5.537655;7.308371;-0.122373;, - -5.537655;7.308371;-0.122373;, - -5.737680;7.308371;-0.123683;, - -5.737680;7.308371;-0.123683;, - -5.737680;7.308371;-0.123683;, - -2.211500;6.391939;-0.509769;, - 0.000000;6.553689;-0.193089;, - -0.869400;6.553689;-0.193089;, - -0.869400;6.553689;-0.193089;, - -0.729000;7.226889;-0.250000;, - -1.157854;8.456665;-0.357500;, - -1.304100;8.392207;-0.380000;, - -1.304100;8.392207;-0.380000;, - -1.614600;8.428101;-0.460000;, - -1.614600;8.428101;-0.460000;, - -1.614600;8.428101;-0.460000;, - -1.304100;8.332384;-0.460000;, - -1.614600;8.487924;-0.380000;, - -1.614600;8.487924;-0.380000;, - -1.614600;8.487924;-0.380000;, - -1.291183;8.380595;0.035000;, - -1.291183;8.380595;0.035000;, - -1.291183;8.380595;0.035000;, - -1.206975;7.730014;-0.148713;, - -1.206975;7.730014;-0.148713;, - -1.206975;8.252790;-0.393860;, - -1.291183;8.380595;-0.380000;, - -1.291183;8.380595;-0.380000;, - -1.291183;7.708855;-0.065000;, - -1.291183;7.708855;-0.065000;, - -1.291183;7.708855;-0.065000;, - -1.291183;7.708855;-0.065000;, - 0.000000;8.299889;-0.380000;, - 0.000000;8.299889;-0.380000;, - -0.645840;8.299889;-0.380000;, - -0.645840;8.299889;-0.380000;, - -0.729000;8.335782;-0.250000;, - -0.621000;8.491881;-0.506934;, - -0.621000;8.491881;-0.506934;, - -0.621000;8.491881;-0.506934;, - -0.434700;8.325909;-0.320215;, - -0.434700;8.325909;-0.320215;, - -0.434700;8.325909;-0.320215;, - -0.434700;8.325909;-0.320215;, - -0.621000;8.392207;-0.380000;, - -0.621000;8.392207;-0.380000;, - -0.621000;8.392207;-0.380000;, - -0.621000;8.332384;-0.460000;, - -0.621000;8.332384;-0.460000;, - 0.000000;8.325909;-0.320215;, - 0.000000;8.325909;-0.320215;, - -0.701730;8.380595;0.035000;, - -0.701730;8.380595;0.035000;, - -0.701730;8.380595;0.035000;, - -0.701730;7.708855;-0.065000;, - -0.701730;7.708855;-0.065000;, - -0.701730;7.708855;-0.065000;, - -0.701730;7.708855;-0.065000;, - -0.701730;8.380595;-0.380000;, - -0.701730;8.380595;-0.380000;, - -0.785938;8.252790;-0.393860;, - -0.785938;7.730014;-0.148713;, - -0.785938;7.730014;-0.148713;, - -6.193715;8.999975;-0.085702;, - -6.193715;8.999975;-0.085702;, - -6.193715;8.999975;-0.085702;, - -6.273846;9.094374;-0.151701;, - -6.273846;9.094374;-0.151701;, - -6.273846;9.094374;-0.151701;, - -6.273846;9.094374;-0.151701;, - -6.273846;9.849567;-0.151701;, - -6.273846;9.849567;-0.151701;, - -6.273846;9.849567;-0.151701;, - -6.273846;9.849567;-0.151701;, - -6.193715;9.943968;-0.085702;, - -6.193715;9.943968;-0.085702;, - -6.193715;9.943968;-0.085702;, - -7.060897;9.725492;-0.129548;, - -7.060897;9.725492;-0.129548;, - -7.060897;9.725492;-0.129548;, - -6.982975;9.563503;-0.129548;, - -6.982975;9.563503;-0.129548;, - -6.671293;9.725492;-0.129548;, - -6.671293;9.725492;-0.129548;, - -6.671293;9.340767;-0.129548;, - -6.671293;9.340767;-0.129548;, - -6.858303;9.340767;-0.129548;, - -6.858303;9.340767;-0.129548;, - -6.858303;9.340767;-0.129548;, - -6.671293;9.563503;-0.129548;, - -6.751895;9.313591;0.542340;, - -6.751895;9.313591;0.542340;, - -6.751895;9.313591;0.542340;, - -6.912178;9.319603;0.515226;, - -6.912178;9.319603;0.515226;, - -6.912178;9.319603;0.515226;, - -6.937339;9.170279;0.515226;, - -6.937339;9.170279;0.515226;, - -6.937339;9.170279;0.515226;, - -6.916745;9.323501;0.515226;, - -6.916745;9.323501;0.515226;, - -6.916745;9.323501;0.515226;, - -7.001220;9.409288;0.515226;, - -7.001220;9.409288;0.515226;, - -7.001220;9.409288;0.515226;, - -7.095283;9.321381;0.515226;, - -7.095283;9.321381;0.515226;, - -7.095283;9.321381;0.515226;, - -6.943227;9.166967;0.515226;, - -6.943227;9.166967;0.515226;, - -6.943227;9.166967;0.515226;, - -6.993157;9.433917;0.515226;, - -6.993157;9.433917;0.515226;, - -6.993157;9.433917;0.515226;, - -7.002631;9.569713;0.515226;, - -7.002631;9.569713;0.515226;, - -7.119660;9.611607;0.515226;, - -7.119660;9.611607;0.515226;, - -7.119660;9.611607;0.515226;, - -7.100082;9.330963;0.515226;, - -7.100082;9.330963;0.515226;, - -7.100082;9.330963;0.515226;, - -5.816796;9.094374;-0.151701;, - -5.816796;9.094374;-0.151701;, - -5.781181;8.999975;-0.085701;, - -5.781181;8.999975;-0.085701;, - -5.816796;9.849567;-0.151701;, - -5.816796;9.849567;-0.151701;, - -5.781182;9.943968;-0.085701;, - -5.781182;9.943968;-0.085701;, - -5.499784;9.980371;0.045354;, - -5.499784;9.980371;0.045354;, - -5.499784;9.980371;0.045354;, - -5.499784;9.836371;0.045354;, - -5.499784;9.836371;0.045354;, - -5.499784;9.836371;0.045354;, - -5.529781;9.428371;-0.592264;, - -5.529781;9.428371;-0.592264;, - -5.729806;9.428371;-0.593574;, - -5.729806;9.428371;-0.593574;, - -5.537655;8.948371;-0.122373;, - -5.537655;8.948371;-0.122373;, - -5.737680;8.948371;-0.123683;, - -5.737680;8.948371;-0.123683;, - -5.537608;9.428371;-0.125206;, - -5.737632;9.428371;-0.126516;, - -4.021242;9.094375;0.068299;, - -4.021242;9.094375;0.068299;, - -4.021242;9.094375;0.068299;, - -4.021242;9.094375;0.068299;, - -4.326931;8.999975;-0.085701;, - -4.326931;8.999975;-0.085701;, - -4.273510;9.094375;-0.151701;, - -4.273510;9.094375;-0.151701;, - -4.439710;8.999975;-0.085701;, - -4.439710;8.999975;-0.085701;, - -5.000635;8.999975;-0.085701;, - -5.000635;9.094375;-0.151701;, - -5.000635;9.094375;-0.151701;, - -4.439710;9.094375;-0.151701;, - -4.439710;9.094375;-0.151701;, - -4.021242;9.849568;0.068299;, - -4.021242;9.849568;0.068299;, - -4.021242;9.849568;0.068299;, - -4.021242;9.849568;0.068299;, - -4.273510;9.849568;-0.151701;, - -4.273510;9.849568;-0.151701;, - -4.326931;9.943968;-0.085701;, - -4.326931;9.943968;-0.085701;, - -4.439710;9.943968;-0.085701;, - -4.439710;9.943968;-0.085701;, - -4.439710;9.849568;-0.151701;, - -4.439710;9.849568;-0.151701;, - -5.000635;9.849568;-0.151701;, - -5.000635;9.849568;-0.151701;, - -5.000635;9.943968;-0.085701;, - -4.569112;9.980371;0.038033;, - -4.569112;9.980371;0.038033;, - -4.569112;9.836371;0.038033;, - -4.569112;9.836371;0.038033;, - -4.529347;9.836371;0.038294;, - -4.529347;9.836371;0.038294;, - -4.529347;9.836371;0.038294;, - -4.529347;9.980371;0.038294;, - -4.529347;9.980371;0.038294;, - -4.529347;9.980371;0.038294;, - -3.739634;9.114357;0.049999;, - -3.739634;9.114357;0.049999;, - -3.739634;9.114357;0.049999;, - -3.739634;9.465427;0.049999;, - -3.739634;9.465427;0.049999;, - -3.739634;9.816500;0.049999;, - -3.739634;9.816500;0.049999;, - -3.739634;9.816500;0.049999;, - -6.197741;9.416677;0.121999;, - -6.197741;9.416677;0.121999;, - -6.197741;9.625625;0.121999;, - -6.197741;9.625625;0.121999;, - -6.454175;9.625625;0.121999;, - -6.454175;9.625625;0.121999;, - -6.454175;9.416677;0.121999;, - -6.454175;9.416677;0.121999;, - -3.477382;10.049524;-0.300001;, - -3.477382;10.049524;-0.300001;, - -3.477382;10.049524;0.049999;, - -3.477382;10.049524;0.049999;, - -3.477382;10.049524;0.049999;, - -3.477382;9.541996;-0.300001;, - -3.477382;9.541996;-0.300001;, - -3.477382;9.541996;0.049999;, - -3.477382;9.541996;0.049999;, - -3.308206;9.330525;-0.300001;, - -3.308206;9.330525;-0.300001;, - -3.308206;9.330525;-0.300001;, - -3.308206;9.330525;-0.300001;, - -3.308206;9.330525;0.049999;, - -3.308206;9.330525;0.049999;, - -3.308206;9.330525;0.049999;, - -3.370776;9.681329;-0.450001;, - -3.370776;9.681329;-0.450001;, - -3.308206;9.541996;0.049999;, - -3.370776;10.087790;-0.450001;, - -3.370776;10.087790;-0.450001;, - -3.308206;10.049524;0.049999;, - -3.308206;10.049524;0.049999;, - -3.347260;9.836371;0.050102;, - -3.347260;9.836371;0.050102;, - -3.347260;9.836371;0.050102;, - -3.347260;9.980371;0.050102;, - -3.347260;9.980371;0.050102;, - -3.347260;9.980371;0.050102;, - -5.498027;9.908371;-0.030170;, - -5.610232;9.972371;0.049085;, - -5.610232;9.972371;0.049085;, - -5.610232;9.972371;0.049085;, - -5.499367;10.036371;0.049811;, - -5.499367;10.036371;0.049811;, - -5.499367;10.036371;0.049811;, - -5.610232;9.844371;0.049085;, - -5.610232;9.844371;0.049085;, - -5.610232;9.844371;0.049085;, - -5.499367;9.780371;0.049811;, - -5.499367;9.780371;0.049811;, - -5.499367;9.780371;0.049811;, - -5.388502;9.844371;0.050537;, - -5.388502;9.844371;0.050537;, - -5.388502;9.844371;0.050537;, - -5.388502;9.972371;0.050537;, - -5.388502;9.972371;0.050537;, - -5.388502;9.972371;0.050537;, - -2.351901;9.114357;0.050000;, - -2.351901;9.114357;0.050000;, - -2.351901;9.114357;0.050000;, - -2.351901;9.465427;0.050000;, - -2.351901;9.465427;0.050000;, - -2.351901;9.816500;0.050000;, - -2.351901;9.816500;0.050000;, - -2.351901;9.816500;0.050000;, - -2.610355;9.541996;0.050000;, - -2.610355;9.541996;0.050000;, - -2.610355;9.541996;-0.300000;, - -2.610355;9.541996;-0.300000;, - -2.610355;9.541996;-0.300000;, - -2.737237;9.330525;-0.300000;, - -2.737237;9.330525;-0.300000;, - -2.737237;9.330525;-0.300000;, - -2.737237;9.330525;0.050000;, - -2.737237;9.330525;0.050000;, - -2.737237;9.330525;0.050000;, - -2.605451;10.087790;-0.450000;, - -2.673121;9.681329;-0.450000;, - -2.673121;9.681329;-0.450000;, - -2.610355;10.049524;0.050000;, - -2.610355;10.049524;0.050000;, - -3.221444;9.664412;-0.450001;, - -3.263738;9.504920;-0.450001;, - -3.263738;9.504920;-0.450001;, - -2.810496;9.504920;-0.450000;, - -3.221444;10.087790;-0.450001;, - -1.785622;9.541996;-0.300000;, - -1.785622;9.541996;-0.300000;, - -1.785622;9.541996;-0.300000;, - -1.785622;9.541996;0.050000;, - -1.785622;9.541996;0.050000;, - -1.574152;9.711170;-0.300000;, - -1.574152;9.711170;-0.300000;, - -1.574152;9.711170;-0.300000;, - -1.574152;9.711170;-0.300000;, - -1.574152;9.711170;0.050000;, - -1.574152;9.711170;0.050000;, - -1.574152;9.711170;0.050000;, - -1.943341;10.228918;-0.450000;, - -1.877459;9.681329;-0.450000;, - -1.877459;9.681329;-0.450000;, - -1.574152;10.218699;0.050000;, - -1.574152;10.218699;0.050000;, - -1.574152;10.218699;0.050000;, - -1.574152;10.218699;-0.300000;, - -1.574152;10.218699;-0.300000;, - -1.690794;10.228918;-0.450000;, - -1.690794;10.228918;-0.450000;, - -1.690794;9.822455;-0.450000;, - -1.690794;9.822455;-0.450000;, - -1.785622;10.218699;0.050000;, - -1.785622;10.218699;0.050000;, - -1.291183;9.629884;0.035000;, - -1.291183;9.629884;0.035000;, - -1.291183;9.629884;0.035000;, - -1.291183;9.629884;-0.380000;, - -1.291183;9.629884;-0.380000;, - -1.291183;9.629884;-0.380000;, - -1.291183;10.090521;0.035000;, - -1.291183;10.090521;0.035000;, - -1.291183;10.090521;0.035000;, - -1.206975;10.200697;-0.393860;, - -1.291183;10.090521;-0.380000;, - -1.291183;10.090521;-0.380000;, - -1.157854;9.729999;-0.357500;, - -1.304100;10.010826;-0.380000;, - -1.304100;10.010826;-0.380000;, - -1.614600;9.891180;-0.460000;, - -1.614600;9.891180;-0.460000;, - -1.614600;9.891180;-0.460000;, - -1.304100;10.010826;-0.460000;, - -1.614600;9.891180;-0.380000;, - -1.614600;9.891180;-0.380000;, - -1.614600;9.891180;-0.380000;, - -1.291183;8.914934;-0.380000;, - -1.291183;8.914934;-0.380000;, - -1.291183;8.914934;-0.380000;, - -1.291183;8.914934;0.035000;, - -1.291183;8.914934;0.035000;, - -1.291183;8.914934;0.035000;, - -0.701730;10.090521;0.035000;, - -0.701730;10.090521;0.035000;, - -0.701730;10.090521;0.035000;, - -0.701730;10.090521;-0.380000;, - -0.701730;10.090521;-0.380000;, - -0.701730;9.629884;-0.380000;, - -0.701730;9.629884;-0.380000;, - -0.701730;9.629884;-0.380000;, - -0.701730;9.629884;0.035000;, - -0.701730;9.629884;0.035000;, - -0.701730;9.629884;0.035000;, - -0.785938;10.200697;-0.393860;, - -0.324000;10.031889;0.150000;, - -0.621000;10.010826;-0.380000;, - -0.621000;10.010826;-0.380000;, - -0.621000;10.010826;-0.380000;, - -0.621000;10.010826;-0.460000;, - -0.621000;10.010826;-0.460000;, - -0.783621;10.114978;-0.154000;, - 0.000000;10.114978;-0.154000;, - -0.701730;8.914934;-0.380000;, - -0.701730;8.914934;-0.380000;, - -0.701730;8.914934;-0.380000;, - -0.701730;8.914934;0.035000;, - -0.701730;8.914934;0.035000;, - -0.701730;8.914934;0.035000;, - -5.529781;11.108371;-0.592264;, - -5.529781;11.108371;-0.592264;, - -5.529781;11.108371;-0.592264;, - -5.729806;11.108371;-0.593574;, - -5.729806;11.108371;-0.593574;, - -5.729806;11.108371;-0.593574;, - -5.737632;11.108371;-0.126516;, - -5.737632;11.108371;-0.126516;, - -5.537608;11.108371;-0.125206;, - -5.537608;11.108371;-0.125206;, - -5.537608;10.788371;-0.125206;, - -5.537608;10.788371;-0.125206;, - -5.537608;10.788371;-0.125206;, - -5.737632;10.788371;-0.126516;, - -5.737632;10.788371;-0.126516;, - -5.737632;10.788371;-0.126516;, - -5.729806;10.788371;-0.593574;, - -5.729806;10.788371;-0.593574;, - -5.529781;10.788371;-0.592264;, - -5.529781;10.788371;-0.592264;, - -5.529781;10.948371;-0.592264;, - -5.529781;10.948371;-0.592264;, - -5.537608;10.948371;-0.125206;, - -5.537608;10.948371;-0.125206;, - -5.537608;10.948371;-0.125206;, - -5.737632;10.948371;-0.126516;, - -5.737632;10.948371;-0.126516;, - -5.737632;10.948371;-0.126516;, - -5.729806;10.948371;-0.593574;, - -5.729806;10.948371;-0.593574;, - -3.477382;10.768522;0.049999;, - -3.477382;10.768522;0.049999;, - -3.477382;10.768522;-0.300001;, - -3.477382;10.768522;-0.300001;, - -3.477382;10.768522;-0.300001;, - -3.477382;10.768522;-0.300001;, - -3.308206;10.895405;0.049999;, - -3.308206;10.895405;-0.300001;, - -3.308206;10.895405;-0.300001;, - -3.308206;10.895405;-0.300001;, - -3.370776;10.653745;-0.450001;, - -3.370776;10.653745;-0.450001;, - -2.610355;10.895405;-0.300000;, - -2.610355;10.895405;-0.300000;, - -2.610355;10.895405;0.050000;, - -2.605451;10.759588;-0.450000;, - -2.605451;10.759588;-0.450000;, - -3.221444;10.759588;-0.450001;, - -3.221444;10.759588;-0.450001;, - -1.954798;10.895405;-0.300000;, - -1.954798;10.895405;-0.300000;, - -1.954798;10.895405;-0.300000;, - -1.954798;10.895405;-0.300000;, - -1.954798;10.895405;0.050000;, - -1.954798;10.895405;0.050000;, - -1.574152;10.514757;0.050000;, - -1.574152;10.514757;-0.300000;, - -1.574152;10.514757;-0.300000;, - -1.574152;10.514757;-0.300000;, - -2.026791;10.759588;-0.450000;, - -2.026791;10.759588;-0.450000;, - -1.690794;10.442054;-0.450000;, - -1.690794;10.442054;-0.450000;, - -1.206975;10.651367;-0.148713;, - -1.206975;10.651367;-0.148713;, - -1.291183;10.669608;-0.065000;, - -1.291183;10.669608;-0.065000;, - -1.291183;10.669608;-0.065000;, - -1.291183;10.669608;-0.065000;, - -0.701730;10.669608;-0.065000;, - -0.701730;10.669608;-0.065000;, - -0.701730;10.669608;-0.065000;, - -0.701730;10.669608;-0.065000;, - -0.785938;10.651367;-0.148713;, - -0.785938;10.651367;-0.148713;, - -0.384438;10.303647;-0.092313;, - -0.384438;10.303647;-0.092313;, - -0.384438;10.303647;-0.092313;, - -0.384438;10.687464;-0.005502;, - -0.384438;10.687464;-0.005502;, - -0.384438;10.687464;-0.005502;, - -0.306190;10.687464;-0.005502;, - -0.306190;10.687464;-0.005502;, - -0.306190;10.303647;-0.092313;, - -0.306190;10.303647;-0.092313;, - -0.290080;11.185386;-0.116549;, - -0.290080;11.185386;-0.116549;, - -0.290080;11.154265;-0.116549;, - -0.290080;11.154265;-0.116549;, - -0.280074;11.060905;-0.350670;, - -0.280074;11.060905;-0.350670;, - -0.280074;11.029785;-0.350670;, - -0.280074;11.029785;-0.350670;, - 0.000000;11.460281;-0.116549;, - -0.203526;11.460281;-0.116549;, - -0.282675;11.429161;-0.116549;, - -0.282675;11.429161;-0.116549;, - -0.282675;11.408415;-0.398685;, - -0.282675;11.408415;-0.398685;, - -0.203526;11.439535;-0.398685;, - 0.000000;11.439535;-0.398685;, - -0.282675;10.760077;-0.398685;, - -0.282675;10.760077;-0.398685;, - -0.192219;10.728957;-0.398685;, - -0.192219;10.728957;-0.116549;, - -0.282675;10.760077;-0.116549;, - -0.282675;10.760077;-0.116549;, - 0.000000;10.728957;-0.398685;, - 0.000000;10.728957;-0.116549;, - -0.296411;10.604476;0.095053;, - -0.296411;10.604476;0.095053;, - -0.791490;10.604476;0.095053;, - -0.791490;10.604476;0.095053;, - -0.791490;10.604476;0.095053;, - -0.791490;10.604476;0.095053;, - -0.296411;10.977919;0.095053;, - -0.296411;10.977919;0.095053;, - -0.791490;10.977919;0.095053;, - -0.791490;10.977919;0.095053;, - -0.791490;10.977919;0.095053;, - -0.791490;10.977919;0.095053;, - -0.319025;10.666717;0.040796;, - -0.723648;10.666717;0.040796;, - -0.723648;10.915678;0.040796;, - -0.319025;10.915678;0.040796;, - -0.191908;10.391821;-0.356500;, - -0.191908;10.391821;-0.356500;, - -0.191908;10.827504;-0.458200;, - -0.191908;10.827504;-0.458200;, - -0.191908;10.827504;-0.458200;, - -0.191908;10.827504;-0.458200;, - -0.118468;10.732613;-0.538774;, - -0.118468;10.732613;-0.538774;, - -0.118468;10.732613;-0.538774;, - -0.118468;10.440549;-0.470599;, - -0.118468;10.440549;-0.470599;, - -0.118468;10.440549;-0.470599;, - 0.000000;10.732613;-0.538774;, - 0.000000;10.732613;-0.538774;, - 0.000000;10.440549;-0.470599;, - 0.000000;10.440549;-0.470599;, - 0.000000;10.827504;-0.458200;, - 0.000000;10.827504;-0.458200;, - 0.000000;10.391821;-0.356500;, - -2.087155;0.022285;0.449062;, - -2.087155;0.022285;0.449062;, - -2.062198;0.686398;0.209303;, - -2.062198;0.686398;0.209303;, - -2.062198;0.686398;0.209303;, - -2.087155;0.022285;0.837000;, - -2.087155;0.022285;0.837000;, - -2.045719;1.096842;0.837000;, - -2.045719;1.096842;0.837000;, - -2.045719;1.096842;0.837000;, - -2.045719;1.096842;0.837000;, - -2.064598;0.607264;0.837000;, - -2.405000;0.645445;0.209000;, - -2.405000;0.645445;0.209000;, - -1.650000;0.686398;0.209303;, - -1.650000;0.686398;0.209303;, - -1.650000;0.022285;0.449062;, - -1.650000;0.022285;0.837000;, - -1.650000;1.096842;0.837000;, - -1.650000;0.645445;0.209000;, - -1.212845;0.022285;0.449062;, - -1.212845;0.022285;0.449062;, - -1.237802;0.686398;0.209303;, - -1.237802;0.686398;0.209303;, - -1.237802;0.686398;0.209303;, - -1.212845;0.022285;0.837000;, - -1.212845;0.022285;0.837000;, - -1.254281;1.096842;0.837000;, - -1.254281;1.096842;0.837000;, - -1.254281;1.096842;0.837000;, - -1.254281;1.096842;0.837000;, - -0.895000;0.645445;0.209000;, - -0.895000;0.645445;0.209000;, - -2.180000;2.285444;0.209000;, - -2.191610;0.736228;0.131760;, - -2.191610;0.736228;0.131760;, - -2.191610;0.736228;0.131760;, - -2.191610;0.540345;0.221912;, - -2.191610;0.540345;0.221912;, - -2.191610;0.344462;0.131760;, - -2.191610;0.344462;0.131760;, - -2.191610;0.344462;0.131760;, - -2.041625;4.121234;0.527731;, - -2.041625;4.121234;0.527731;, - -2.041625;4.121234;0.527731;, - -2.180000;3.545444;0.209000;, - -2.180000;3.545444;0.209000;, - -1.961750;4.067234;0.701854;, - -1.961750;4.067234;0.701854;, - -1.961750;3.202694;0.513641;, - -1.961750;3.202694;0.513641;, - -1.961750;3.202694;0.513641;, - -1.961750;3.608234;0.701854;, - -1.961750;3.608234;0.701854;, - -1.961750;3.608234;0.701854;, - -1.646500;0.540345;0.221912;, - -1.646500;0.736228;0.131760;, - -1.646500;0.736228;0.131760;, - -1.646500;0.344462;0.131760;, - -1.646500;0.344462;0.131760;, - -1.208000;4.121234;0.527731;, - -1.208000;4.121234;0.527731;, - -1.208000;4.121234;0.527731;, - -1.650000;3.545444;0.209000;, - -1.650000;4.067234;0.701854;, - -1.650000;3.202694;0.513641;, - -1.650000;3.202694;0.513641;, - -1.650000;3.608234;0.701854;, - -1.650000;3.608234;0.701854;, - -1.101390;0.736228;0.131760;, - -1.101390;0.736228;0.131760;, - -1.101390;0.736228;0.131760;, - -1.101390;0.540345;0.221912;, - -1.101390;0.540345;0.221912;, - -1.101390;0.344462;0.131760;, - -1.101390;0.344462;0.131760;, - -1.101390;0.344462;0.131760;, - -1.120000;3.545444;0.209000;, - -1.120000;3.545444;0.209000;, - -1.338250;4.067234;0.701854;, - -1.338250;4.067234;0.701854;, - -1.338250;3.202694;0.513641;, - -1.338250;3.202694;0.513641;, - -1.338250;3.202694;0.513641;, - -1.338250;3.608234;0.701854;, - -1.338250;3.608234;0.701854;, - -1.338250;3.608234;0.701854;, - -2.211500;4.924759;0.527731;, - -2.211500;4.924759;0.527731;, - -1.961750;4.472775;0.513641;, - -1.961750;4.472775;0.513641;, - -1.961750;4.472775;0.513641;, - -1.650000;4.924759;0.527731;, - -1.650000;4.472775;0.513641;, - -1.650000;4.472775;0.513641;, - -1.088500;4.924759;0.527731;, - -1.088500;4.924759;0.527731;, - -1.338250;4.472775;0.513641;, - -1.338250;4.472775;0.513641;, - -1.338250;4.472775;0.513641;, - -1.291183;8.380595;0.600000;, - -1.291183;8.380595;0.600000;, - -1.291183;7.708855;0.600000;, - -1.291183;7.708855;0.600000;, - -0.701730;8.380595;0.600000;, - -0.701730;8.380595;0.600000;, - -0.701730;7.708855;0.600000;, - -0.701730;7.708855;0.600000;, - -6.273846;9.094374;0.662299;, - -6.273846;9.094374;0.662299;, - -6.273846;9.094374;0.662299;, - -6.273846;9.094374;0.662299;, - -6.193715;8.999975;0.662299;, - -6.193715;8.999975;0.662299;, - -6.193715;8.999975;0.662299;, - -6.193715;8.999975;0.607299;, - -6.193715;8.999975;0.607299;, - -6.193715;8.999975;0.607299;, - -6.273846;9.094374;0.607298;, - -6.273846;9.094374;0.607298;, - -6.273846;9.094374;0.607298;, - -6.273846;9.094374;0.607298;, - -6.273846;9.849567;0.662299;, - -6.273846;9.849567;0.662299;, - -6.273846;9.849567;0.662299;, - -6.273846;9.849567;0.662299;, - -6.193715;9.943968;0.662299;, - -6.193715;9.943968;0.662299;, - -6.193715;9.943968;0.662299;, - -6.193715;9.943968;0.607299;, - -6.193715;9.943968;0.607299;, - -6.193715;9.943968;0.607299;, - -6.273846;9.849567;0.607298;, - -6.273846;9.849567;0.607298;, - -6.273846;9.849567;0.607298;, - -6.273846;9.849567;0.607298;, - -6.982975;9.563503;0.726668;, - -6.982975;9.563503;0.726668;, - -7.060897;9.725492;0.726668;, - -7.060897;9.725492;0.726668;, - -7.060897;9.725492;0.726668;, - -6.359611;9.563503;0.568268;, - -6.359611;9.563503;0.568268;, - -6.359611;9.563503;0.002452;, - -6.359611;9.563503;0.002452;, - -6.359611;9.725492;0.002452;, - -6.359611;9.725492;0.002452;, - -6.359611;9.725492;0.002452;, - -6.359611;9.725492;0.568268;, - -6.359611;9.725492;0.568268;, - -6.359611;9.725492;0.568268;, - -6.671293;9.725492;0.726668;, - -6.671293;9.725492;0.726668;, - -6.671293;9.563503;0.726668;, - -6.359611;9.340767;0.002452;, - -6.359611;9.340767;0.002452;, - -6.359611;9.340767;0.002452;, - -6.359611;9.340767;0.568268;, - -6.359611;9.340767;0.568268;, - -6.359611;9.340767;0.568268;, - -6.671293;9.340767;0.726668;, - -6.671293;9.340767;0.726668;, - -6.858303;9.340767;0.726668;, - -6.858303;9.340767;0.726668;, - -6.858303;9.340767;0.726668;, - -6.751895;9.313591;0.677907;, - -6.751895;9.313591;0.677907;, - -6.751895;9.313591;0.677907;, - -6.912178;9.319603;0.705020;, - -6.912178;9.319603;0.705020;, - -6.912178;9.319603;0.705020;, - -6.937339;9.170279;0.705020;, - -6.937339;9.170279;0.705020;, - -6.937339;9.170279;0.705020;, - -6.693048;9.269262;0.664350;, - -6.693048;9.269262;0.664350;, - -6.693048;9.269262;0.664350;, - -6.693048;9.269262;0.555896;, - -6.693048;9.269262;0.555896;, - -6.693048;9.269262;0.555896;, - -6.916745;9.323501;0.705020;, - -6.916745;9.323501;0.705020;, - -6.916745;9.323501;0.705020;, - -7.001220;9.409288;0.705020;, - -7.001220;9.409288;0.705020;, - -7.001220;9.409288;0.705020;, - -7.095283;9.321381;0.705020;, - -7.095283;9.321381;0.705020;, - -7.095283;9.321381;0.705020;, - -6.943227;9.166967;0.705020;, - -6.943227;9.166967;0.705020;, - -6.943227;9.166967;0.705020;, - -6.993157;9.433917;0.705020;, - -6.993157;9.433917;0.705020;, - -6.993157;9.433917;0.705020;, - -7.002631;9.569713;0.705020;, - -7.002631;9.569713;0.705020;, - -7.119660;9.611607;0.705020;, - -7.119660;9.611607;0.705020;, - -7.119660;9.611607;0.705020;, - -7.100082;9.330963;0.705020;, - -7.100082;9.330963;0.705020;, - -7.100082;9.330963;0.705020;, - -5.781182;8.999975;0.607299;, - -5.781182;8.999975;0.607299;, - -5.781182;8.999975;0.607299;, - -5.781182;8.999975;0.662299;, - -5.781182;8.999975;0.662299;, - -5.781182;8.999975;0.662299;, - -5.781182;9.943968;0.607299;, - -5.781182;9.943968;0.607299;, - -5.781182;9.943968;0.662299;, - -5.781182;9.943968;0.662299;, - -6.554913;9.416677;0.408793;, - -6.554913;9.416677;0.408793;, - -6.554913;9.416677;0.408793;, - -6.554913;9.625625;0.408793;, - -6.554913;9.625625;0.408793;, - -6.554913;9.625625;0.408793;, - -6.596640;9.625625;0.289999;, - -6.596640;9.625625;0.289999;, - -6.596640;9.416677;0.289999;, - -6.596640;9.416677;0.289999;, - -6.554913;9.416677;0.171205;, - -6.554913;9.416677;0.171205;, - -6.554913;9.416677;0.171205;, - -6.554913;9.625625;0.171205;, - -6.554913;9.625625;0.171205;, - -6.554913;9.625625;0.171205;, - -4.092471;8.999975;0.827299;, - -4.092471;8.999975;0.827299;, - -4.021242;9.094375;0.893299;, - -4.021242;9.094375;0.893299;, - -4.021242;9.094375;0.893299;, - -4.092471;8.999975;0.134299;, - -4.092471;8.999975;0.134299;, - -4.092471;8.999975;0.607299;, - -4.092471;8.999975;0.607299;, - -4.092471;8.999975;0.607299;, - -4.326931;8.999975;0.607299;, - -4.326931;8.999975;0.607299;, - -4.021242;9.094375;0.607299;, - -4.021242;9.094375;0.607299;, - -4.021242;9.094375;0.607299;, - -4.021242;9.094375;0.607299;, - -4.092471;8.999975;0.662299;, - -4.092471;8.999975;0.662299;, - -4.092471;8.999975;0.662299;, - -4.326931;8.999975;0.662299;, - -4.326931;8.999975;0.662299;, - -4.021242;9.094375;0.662299;, - -4.021242;9.094375;0.662299;, - -4.021242;9.094375;0.662299;, - -4.021242;9.094375;0.662299;, - -4.439710;8.999975;0.497299;, - -4.439710;8.999975;0.497299;, - -4.911600;8.999975;0.497299;, - -4.911600;8.999975;0.497299;, - -4.911600;8.999975;0.497299;, - -4.439710;8.999975;0.552299;, - -4.439710;8.999975;0.552299;, - -4.911600;8.999975;0.552299;, - -4.911600;8.999975;0.552299;, - -4.911600;8.999975;0.552299;, - -5.000635;8.999975;0.607299;, - -5.000635;8.999975;0.607299;, - -5.000635;8.999975;0.662299;, - -5.000635;8.999975;0.662299;, - -4.021242;9.849568;0.893299;, - -4.021242;9.849568;0.893299;, - -4.021242;9.849568;0.893299;, - -4.092471;9.943968;0.827299;, - -4.092471;9.943968;0.827299;, - -4.092471;9.943968;0.134299;, - -4.092471;9.943968;0.134299;, - -4.326931;9.943968;0.607299;, - -4.326931;9.943968;0.607299;, - -4.092471;9.943968;0.607299;, - -4.092471;9.943968;0.607299;, - -4.092471;9.943968;0.607299;, - -4.021242;9.849568;0.607299;, - -4.021242;9.849568;0.607299;, - -4.021242;9.849568;0.607299;, - -4.021242;9.849568;0.607299;, - -4.326931;9.943968;0.662299;, - -4.326931;9.943968;0.662299;, - -4.092471;9.943968;0.662299;, - -4.092471;9.943968;0.662299;, - -4.092471;9.943968;0.662299;, - -4.021242;9.849568;0.662299;, - -4.021242;9.849568;0.662299;, - -4.021242;9.849568;0.662299;, - -4.021242;9.849568;0.662299;, - -4.439710;9.943968;0.497299;, - -4.439710;9.943968;0.497299;, - -4.911600;9.943968;0.497299;, - -4.911600;9.943968;0.497299;, - -4.911600;9.943968;0.497299;, - -4.911600;9.943968;0.552299;, - -4.911600;9.943968;0.552299;, - -4.911600;9.943968;0.552299;, - -4.439710;9.943968;0.552299;, - -4.439710;9.943968;0.552299;, - -5.000635;9.943968;0.607299;, - -5.000635;9.943968;0.607299;, - -5.000635;9.943968;0.607299;, - -5.000635;9.943968;0.662299;, - -5.000635;9.943968;0.662299;, - -5.000635;9.943968;0.662299;, - -4.582514;9.980371;0.837847;, - -4.582514;9.980371;0.837847;, - -4.582514;9.836371;0.837847;, - -4.582514;9.836371;0.837847;, - -4.542748;9.836371;0.838107;, - -4.542748;9.836371;0.838107;, - -4.542748;9.836371;0.838107;, - -4.542748;9.980371;0.838107;, - -4.542748;9.980371;0.838107;, - -4.542748;9.980371;0.838107;, - -3.853407;9.114357;0.199999;, - -3.853407;9.114357;0.199999;, - -3.739634;9.114357;0.849999;, - -3.739634;9.114357;0.849999;, - -3.739634;9.114357;0.849999;, - -3.853407;9.114357;0.699999;, - -3.853407;9.114357;0.699999;, - -3.853407;9.465427;0.699999;, - -3.853407;9.465427;0.199999;, - -3.739634;9.465427;0.849999;, - -3.739634;9.465427;0.849999;, - -3.853407;9.816500;0.199999;, - -3.853407;9.816500;0.199999;, - -3.853407;9.816500;0.699999;, - -3.853407;9.816500;0.699999;, - -3.739634;9.816500;0.849999;, - -3.739634;9.816500;0.849999;, - -3.739634;9.816500;0.849999;, - -6.097003;9.416677;0.408793;, - -6.097003;9.416677;0.408793;, - -6.097003;9.416677;0.408793;, - -6.069272;9.416677;0.191822;, - -6.069272;9.416677;0.191822;, - -6.069272;9.625625;0.191822;, - -6.069272;9.625625;0.191822;, - -6.097003;9.625625;0.408793;, - -6.097003;9.625625;0.408793;, - -6.097003;9.625625;0.408793;, - -6.097003;9.416677;0.171205;, - -6.097003;9.416677;0.171205;, - -6.097003;9.416677;0.171205;, - -6.097003;9.625625;0.171205;, - -6.097003;9.625625;0.171205;, - -6.097003;9.625625;0.171205;, - -6.197741;9.625625;0.457999;, - -6.197741;9.625625;0.457999;, - -6.197741;9.416677;0.457999;, - -6.197741;9.416677;0.457999;, - -6.454175;9.416677;0.457999;, - -6.454175;9.416677;0.457999;, - -6.454175;9.625625;0.457999;, - -6.454175;9.625625;0.457999;, - -3.332740;9.836371;0.849896;, - -3.332740;9.836371;0.849896;, - -3.332740;9.836371;0.849896;, - -3.332740;9.980371;0.849896;, - -3.332740;9.980371;0.849896;, - -3.332740;9.980371;0.849896;, - -5.513439;10.036371;0.889615;, - -5.513439;10.036371;0.889615;, - -5.513439;10.036371;0.889615;, - -5.624304;9.972371;0.888889;, - -5.624304;9.972371;0.888889;, - -5.624304;9.972371;0.888889;, - -5.624304;9.844371;0.888889;, - -5.624304;9.844371;0.888889;, - -5.624304;9.844371;0.888889;, - -5.513439;9.780371;0.889615;, - -5.513439;9.780371;0.889615;, - -5.513439;9.780371;0.889615;, - -3.477382;10.049524;0.480000;, - -3.477382;10.049524;0.480000;, - -3.308206;10.049524;0.480000;, - -3.477382;10.049524;0.860001;, - -3.477382;10.049524;0.860001;, - -3.477382;10.049524;0.860001;, - -3.477382;9.541996;0.860001;, - -3.477382;9.541996;0.860001;, - -3.308206;9.330525;0.860001;, - -3.308206;9.330525;0.860001;, - -3.308206;9.330525;0.860001;, - -3.308206;9.541996;0.860001;, - -3.308206;10.049524;0.860001;, - -3.308206;10.049524;0.860001;, - -2.351901;9.114357;0.850000;, - -2.351901;9.114357;0.850000;, - -2.351901;9.114357;0.850000;, - -2.238127;9.114357;0.200000;, - -2.238127;9.114357;0.200000;, - -2.238127;9.114357;0.700000;, - -2.238127;9.114357;0.700000;, - -2.351901;9.465427;0.850000;, - -2.351901;9.465427;0.850000;, - -2.238127;9.465427;0.700000;, - -2.238127;9.465427;0.200000;, - -2.351901;9.816500;0.850000;, - -2.351901;9.816500;0.850000;, - -2.351901;9.816500;0.850000;, - -2.238127;9.816500;0.700000;, - -2.238127;9.816500;0.700000;, - -2.238127;9.816500;0.200000;, - -2.238127;9.816500;0.200000;, - -5.402574;9.844371;0.890341;, - -5.402574;9.844371;0.890341;, - -5.402574;9.844371;0.890341;, - -5.402574;9.972371;0.890341;, - -5.402574;9.972371;0.890341;, - -5.402574;9.972371;0.890341;, - -2.625627;9.706669;0.706400;, - -2.625627;9.706669;0.706400;, - -2.625627;9.706669;0.706400;, - -2.625627;9.706669;0.213600;, - -2.625627;9.706669;0.213600;, - -2.625627;9.706669;0.213600;, - -2.625627;9.208800;0.706400;, - -2.625627;9.208800;0.706400;, - -2.625627;9.208800;0.706400;, - -2.625627;9.208800;0.213600;, - -2.625627;9.208800;0.213600;, - -2.625627;9.208800;0.213600;, - -2.610355;10.049524;0.480000;, - -2.610355;9.541996;0.860000;, - -2.610355;9.541996;0.860000;, - -2.737237;9.330525;0.860000;, - -2.737237;9.330525;0.860000;, - -2.737237;9.330525;0.860000;, - -2.610355;10.049524;0.860000;, - -2.610355;10.049524;0.860000;, - -2.273581;10.058715;0.706400;, - -2.273581;10.058715;0.706400;, - -1.775712;10.058715;0.706400;, - -1.775712;10.058715;0.706400;, - -1.775712;10.058715;0.213600;, - -1.775712;10.058715;0.213600;, - -2.273581;10.058715;0.213600;, - -2.273581;10.058715;0.213600;, - -2.273581;8.856754;0.706400;, - -2.273581;8.856754;0.706400;, - -2.273581;8.856754;0.213600;, - -2.273581;8.856754;0.213600;, - -1.775712;8.856754;0.213600;, - -1.775712;8.856754;0.213600;, - -1.775712;8.856754;0.706400;, - -1.775712;8.856754;0.706400;, - -1.491860;10.058715;0.213600;, - -1.491860;10.058715;0.213600;, - -1.491860;10.058715;0.706400;, - -1.491860;10.058715;0.706400;, - -2.024647;9.457734;0.706400;, - -2.024647;9.457734;0.213600;, - -1.574152;10.218699;0.480000;, - -1.574152;10.218699;0.480000;, - -1.785622;10.218699;0.480000;, - -1.785622;9.541996;0.860000;, - -1.785622;9.541996;0.860000;, - -1.574152;9.711170;0.860000;, - -1.574152;9.711170;0.860000;, - -1.574152;9.711170;0.860000;, - -1.574152;10.218699;0.860000;, - -1.574152;10.218699;0.860000;, - -1.574152;10.218699;0.860000;, - -1.785622;10.218699;0.860000;, - -1.785622;10.218699;0.860000;, - -1.291183;10.090521;0.600000;, - -1.291183;10.090521;0.600000;, - -1.179814;8.968801;0.706400;, - -1.179814;8.968801;0.706400;, - -1.179814;8.968801;0.706400;, - -1.179814;8.968801;0.213600;, - -1.179814;8.968801;0.213600;, - -1.179814;8.968801;0.213600;, - -1.179814;9.706669;0.213600;, - -1.179814;9.706669;0.213600;, - -1.179814;9.706669;0.213600;, - -1.179814;9.706669;0.706400;, - -1.179814;9.706669;0.706400;, - -1.179814;9.706669;0.706400;, - -1.423666;9.208800;0.706400;, - -1.423666;9.208800;0.706400;, - -1.423666;9.208800;0.706400;, - -1.423666;9.208800;0.706400;, - -1.423666;9.706669;0.706400;, - -1.423666;9.706669;0.213600;, - -1.423666;9.208800;0.213600;, - -1.423666;9.208800;0.213600;, - -1.423666;9.208800;0.213600;, - -1.423666;9.208800;0.213600;, - -0.701730;10.090521;0.600000;, - -0.701730;10.090521;0.600000;, - -3.477382;10.768522;0.480000;, - -3.477382;10.768522;0.480000;, - -3.308206;10.895405;0.480000;, - -3.477382;10.768522;0.860001;, - -3.477382;10.768522;0.860001;, - -3.308206;10.895405;0.860001;, - -2.610355;10.895405;0.480000;, - -2.610355;10.895405;0.860000;, - -1.954798;10.895405;0.480000;, - -1.954798;10.895405;0.480000;, - -1.574152;10.514757;0.480000;, - -1.954798;10.895405;0.860000;, - -1.954798;10.895405;0.860000;, - -1.574152;10.514757;0.860000;, - -1.291183;10.669608;0.600000;, - -1.291183;10.669608;0.600000;, - -0.701730;10.669608;0.600000;, - -0.701730;10.669608;0.600000;, - -0.162000;10.592889;0.850000;, - -0.162000;10.592889;0.850000;, - -0.162000;10.592889;0.400000;, - -0.162000;10.592889;0.400000;, - -0.384438;11.237040;0.797501;, - -0.384438;11.237040;0.797501;, - -0.384438;10.687464;0.732393;, - -0.384438;10.687464;0.732393;, - -0.384438;10.687464;0.732393;, - -0.384438;10.303647;0.732393;, - -0.384438;10.303647;0.732393;, - -0.384438;11.486215;0.839315;, - -0.384438;11.486215;0.839315;, - -0.384438;11.486215;0.839315;, - -0.306190;11.559654;0.839315;, - -0.306190;11.559654;0.839315;, - 0.000000;11.559654;0.839315;, - 0.000000;11.559654;0.839315;, - -0.306190;10.687464;0.732393;, - -0.306190;10.687464;0.732393;, - 0.000000;10.687464;0.732393;, - 0.000000;10.303647;0.732393;, - 0.000000;10.303647;0.732393;, - -0.306190;10.303647;0.732393;, - -0.306190;10.303647;0.732393;, - -0.306190;10.303647;0.732393;, - -0.290080;11.185386;0.360912;, - -0.290080;11.185386;0.360912;, - -0.290080;11.154265;0.360912;, - -0.290080;11.154265;0.360912;, - -0.203526;11.460281;0.360912;, - 0.000000;11.460281;0.360912;, - -0.282675;11.429161;0.360912;, - -0.282675;11.429161;0.360912;, - -0.192219;10.728957;0.360912;, - 0.000000;10.728957;0.360912;, - -0.282675;10.760077;0.360912;, - -0.282675;10.760077;0.360912;, - -0.296411;10.604476;0.827522;, - -0.296411;10.604476;0.827522;, - -0.791490;10.604476;0.827522;, - -0.791490;10.604476;0.827522;, - -0.791490;10.604476;0.827522;, - -0.296411;10.977919;0.827522;, - -0.296411;10.977919;0.827522;, - -0.791490;10.977919;0.827522;, - -0.791490;10.977919;0.827522;, - -0.791490;10.977919;0.827522;, - 0.000000;10.592889;0.850000;, - 0.000000;10.592889;0.850000;, - 0.000000;10.592889;0.400000;, - 0.000000;10.592889;0.400000;, - -2.022394;0.022285;1.224938;, - -2.022394;0.022285;1.224938;, - -2.022394;0.022285;1.224938;, - -1.964576;0.527998;1.508697;, - -1.964576;0.527998;1.508697;, - -1.964576;0.527998;1.508697;, - -2.225000;1.050444;1.309000;, - -2.225000;1.050444;1.309000;, - -2.225000;1.050444;1.309000;, - -1.650000;0.022285;1.224938;, - -1.650000;0.022285;1.224938;, - -1.650000;0.527998;1.508697;, - -1.650000;0.527998;1.508697;, - -1.650000;1.050444;1.309000;, - -1.650000;1.050444;1.309000;, - -1.277606;0.022285;1.224938;, - -1.277606;0.022285;1.224938;, - -1.277606;0.022285;1.224938;, - -1.335424;0.527998;1.508697;, - -1.335424;0.527998;1.508697;, - -1.335424;0.527998;1.508697;, - -1.075000;1.050444;1.309000;, - -1.075000;1.050444;1.309000;, - -1.075000;1.050444;1.309000;, - -2.180000;2.735444;1.009000;, - -2.180000;2.735444;1.009000;, - -2.180000;2.735444;1.009000;, - -2.630000;2.735444;1.009000;, - -2.630000;2.735444;1.009000;, - -2.630000;2.735444;1.009000;, - -2.180000;2.465444;1.009000;, - -2.180000;2.465444;1.009000;, - -1.650000;2.465444;1.009000;, - -1.120000;2.735444;1.009000;, - -1.120000;2.735444;1.009000;, - -1.120000;2.735444;1.009000;, - -1.120000;2.465444;1.009000;, - -1.120000;2.465444;1.009000;, - -0.670000;2.735444;1.009000;, - -0.670000;2.735444;1.009000;, - -0.670000;2.735444;1.009000;, - -2.180000;4.040444;1.009000;, - -2.180000;4.040444;1.009000;, - -2.180000;4.040444;1.009000;, - -2.630000;4.040444;1.009000;, - -2.630000;4.040444;1.009000;, - -2.630000;4.040444;1.009000;, - -2.180000;3.545444;1.009000;, - -2.180000;3.545444;1.009000;, - -2.180000;3.545444;1.009000;, - -1.650000;3.545444;1.009000;, - -1.650000;3.545444;1.009000;, - -1.120000;4.040444;1.009000;, - -1.120000;4.040444;1.009000;, - -1.120000;4.040444;1.009000;, - -1.120000;3.545444;1.009000;, - -1.120000;3.545444;1.009000;, - -1.120000;3.545444;1.009000;, - -0.670000;4.040444;1.009000;, - -0.670000;4.040444;1.009000;, - -0.670000;4.040444;1.009000;, - -2.211500;4.924759;0.955231;, - -2.211500;4.924759;0.955231;, - -2.211500;4.924759;0.955231;, - -2.183926;5.309234;0.907731;, - -2.183926;5.309234;0.907731;, - -1.650000;4.924759;0.955231;, - -1.650000;4.924759;0.955231;, - -1.108550;5.309234;0.907731;, - -1.108550;5.309234;0.907731;, - -1.088500;4.924759;0.955231;, - -1.088500;4.924759;0.955231;, - -1.088500;4.924759;0.955231;, - -0.864000;5.747889;1.400000;, - -0.864000;5.747889;1.400000;, - -0.864000;5.747889;1.400000;, - -0.270000;5.747889;1.400000;, - -0.270000;5.747889;1.400000;, - -0.270000;5.747889;1.400000;, - -0.270000;5.747889;1.400000;, - 0.000000;5.747889;1.400000;, - -0.270000;4.472888;1.400000;, - -0.270000;4.472888;1.400000;, - -0.344000;4.439500;1.395000;, - -0.344000;4.439500;1.395000;, - -0.344000;4.439500;1.395000;, - 0.000000;4.439500;1.395000;, - 0.000000;4.439500;1.395000;, - -0.434000;5.122600;1.395000;, - -0.434000;5.122600;1.395000;, - -0.434000;5.122600;1.395000;, - 0.000000;5.122600;1.395000;, - 0.000000;5.122600;1.395000;, - -5.557411;7.308371;1.056685;, - -5.557411;7.308371;1.056685;, - -5.757436;7.308371;1.055375;, - -5.757436;7.308371;1.055375;, - -5.564542;7.308371;1.482253;, - -5.564542;7.308371;1.482253;, - -5.564542;7.308371;1.482253;, - -5.764566;7.308371;1.480943;, - -5.764566;7.308371;1.480943;, - -5.764566;7.308371;1.480943;, - -2.211500;6.391939;1.240231;, - -2.211500;6.391939;1.240231;, - -2.211500;6.899809;1.050231;, - -2.211500;6.899809;1.050231;, - -2.211500;6.899809;1.050231;, - -1.650000;6.391939;1.240231;, - -1.650000;6.899809;1.050231;, - -1.650000;6.899809;1.050231;, - -1.088500;6.391939;1.240231;, - -1.088500;6.391939;1.240231;, - -1.088500;6.899809;1.050231;, - -1.088500;6.899809;1.050231;, - -1.088500;6.899809;1.050231;, - 0.000000;6.553689;1.368093;, - 0.000000;6.553689;1.368093;, - -0.621000;6.553689;1.368093;, - -0.621000;6.553689;1.368093;, - -0.621000;6.553689;1.368093;, - -0.864000;6.512889;1.400000;, - -0.864000;6.512889;1.400000;, - -0.864000;6.512889;1.400000;, - -0.270000;6.512889;1.400000;, - -0.270000;6.512889;1.400000;, - -0.270000;6.512889;1.400000;, - -0.270000;6.512889;1.400000;, - 0.000000;6.512889;1.400000;, - 0.000000;6.512889;1.400000;, - -0.474000;6.505000;1.395000;, - -0.474000;6.505000;1.395000;, - -0.474000;6.505000;1.395000;, - 0.000000;6.505000;1.395000;, - 0.000000;6.505000;1.395000;, - -1.157854;8.456665;1.570000;, - -1.144800;8.335900;1.292500;, - -1.144800;8.335900;1.292500;, - -1.144800;8.417500;1.427500;, - -1.001073;8.438701;1.587800;, - -1.001073;8.438701;1.587800;, - -1.295585;8.438701;1.587800;, - -1.295585;8.438701;1.587800;, - -1.295585;8.438701;1.587800;, - -1.295585;8.438701;1.587800;, - -1.291183;8.380595;1.165000;, - -1.291183;8.380595;1.165000;, - -1.291183;8.380595;1.165000;, - -1.206975;8.252790;1.593860;, - -1.206975;7.730014;1.348713;, - -1.206975;7.730014;1.348713;, - -1.291183;8.380595;1.580000;, - -1.291183;8.380595;1.580000;, - -1.291183;7.708855;1.265000;, - -1.291183;7.708855;1.265000;, - -1.291183;7.708855;1.265000;, - -1.291183;7.708855;1.265000;, - 0.000000;7.481889;1.150000;, - -0.729000;8.335782;1.300000;, - -0.729000;8.335782;1.300000;, - -0.621000;7.481889;1.150000;, - -0.621000;7.481889;1.150000;, - -0.712800;8.335900;1.292500;, - -0.712800;8.335900;1.292500;, - 0.000000;8.335900;1.292500;, - 0.000000;8.335900;1.292500;, - 0.000000;8.417500;1.427500;, - -0.712800;8.417500;1.427500;, - -0.701730;8.380595;1.165000;, - -0.701730;8.380595;1.165000;, - -0.701730;8.380595;1.165000;, - -0.701730;8.380595;1.580000;, - -0.701730;8.380595;1.580000;, - -0.701730;7.708855;1.265000;, - -0.701730;7.708855;1.265000;, - -0.701730;7.708855;1.265000;, - -0.701730;7.708855;1.265000;, - -0.785938;8.252790;1.593860;, - -0.785938;7.730014;1.348713;, - -0.785938;7.730014;1.348713;, - -5.781182;8.999975;1.102299;, - -5.781182;8.999975;1.102299;, - -5.781182;8.999975;1.102299;, - -5.816796;9.094374;1.168299;, - -5.816796;9.094374;1.168299;, - -5.816796;9.094374;1.168299;, - -5.816796;9.094374;1.168299;, - -5.816796;9.849567;1.168299;, - -5.816796;9.849567;1.168299;, - -5.816796;9.849567;1.168299;, - -5.816796;9.849567;1.168299;, - -5.781182;9.943968;1.102299;, - -5.781182;9.943968;1.102299;, - -5.781182;9.943968;1.102299;, - -5.513186;9.980371;0.845168;, - -5.513186;9.980371;0.845168;, - -5.513186;9.980371;0.845168;, - -5.513186;9.836371;0.845168;, - -5.513186;9.836371;0.845168;, - -5.513186;9.836371;0.845168;, - -5.557411;9.428371;1.056685;, - -5.557411;8.948371;1.056685;, - -5.757436;9.428371;1.055375;, - -5.757436;8.948371;1.055375;, - -5.564542;9.428371;1.482253;, - -5.564542;9.428371;1.482253;, - -5.564542;8.948371;1.482253;, - -5.564542;8.948371;1.482253;, - -5.764566;9.428371;1.480943;, - -5.764566;9.428371;1.480943;, - -5.764566;8.948371;1.480943;, - -5.764566;8.948371;1.480943;, - -4.273510;9.094375;1.168299;, - -4.273510;9.094375;1.168299;, - -4.273510;9.094375;1.168299;, - -4.273510;9.094375;1.168299;, - -4.326932;8.999975;1.102299;, - -4.439710;9.094375;1.168299;, - -4.439710;9.094375;1.168299;, - -5.000635;9.094375;1.168299;, - -5.000635;9.094375;1.168299;, - -5.000635;8.999975;1.102299;, - -5.000635;8.999975;1.102299;, - -4.439710;8.999975;1.102299;, - -4.439710;8.999975;1.102299;, - -4.273510;9.849568;1.168299;, - -4.273510;9.849568;1.168299;, - -4.273510;9.849568;1.168299;, - -4.326932;9.943968;1.102299;, - -4.439710;9.849568;1.168299;, - -4.439710;9.849568;1.168299;, - -4.439710;9.943968;1.102299;, - -4.439710;9.943968;1.102299;, - -5.000635;9.943968;1.102299;, - -5.000635;9.943968;1.102299;, - -5.000635;9.849568;1.168299;, - -5.000635;9.849568;1.168299;, - -5.514779;9.908371;0.969597;, - -3.477382;10.049524;1.210001;, - -3.477382;10.049524;1.210001;, - -3.477382;9.541996;1.210001;, - -3.477382;9.541996;1.210001;, - -3.308206;9.330525;1.210001;, - -3.308206;9.330525;1.210001;, - -3.308206;9.330525;1.210001;, - -3.308206;9.330525;1.210001;, - -3.370776;9.681329;1.360001;, - -3.370776;9.681329;1.360001;, - -3.370776;10.087790;1.360001;, - -3.370776;10.087790;1.360001;, - -2.610355;9.541996;1.210000;, - -2.610355;9.541996;1.210000;, - -2.610355;9.541996;1.210000;, - -2.737237;9.330525;1.210000;, - -2.737237;9.330525;1.210000;, - -2.737237;9.330525;1.210000;, - -2.605451;10.087790;1.360000;, - -2.673121;9.681329;1.360000;, - -2.673121;9.681329;1.360000;, - -3.263738;9.504920;1.360001;, - -3.263738;9.504920;1.360001;, - -3.221444;9.664412;1.360001;, - -2.810496;9.504920;1.360000;, - -3.221444;10.087790;1.360001;, - -1.785622;9.541996;1.210000;, - -1.785622;9.541996;1.210000;, - -1.785622;9.541996;1.210000;, - -1.574152;9.711170;1.210000;, - -1.574152;9.711170;1.210000;, - -1.574152;9.711170;1.210000;, - -1.574152;9.711170;1.210000;, - -1.943341;10.228918;1.360000;, - -1.877459;9.681329;1.360000;, - -1.877459;9.681329;1.360000;, - -1.574152;10.218699;1.210000;, - -1.574152;10.218699;1.210000;, - -1.690794;10.228918;1.360000;, - -1.690794;10.228918;1.360000;, - -1.690794;9.822455;1.360000;, - -1.690794;9.822455;1.360000;, - -1.144800;10.003599;1.427500;, - -1.144800;10.105600;1.292500;, - -1.144800;10.105600;1.292500;, - -1.295585;9.903199;1.587800;, - -1.295585;9.903199;1.587800;, - -1.295585;9.903199;1.587800;, - -1.295585;9.903199;1.587800;, - -1.001073;9.903199;1.587800;, - -1.001073;9.903199;1.587800;, - -1.291183;9.629884;2.100000;, - -1.291183;9.629884;2.100000;, - -1.291183;9.629884;2.100000;, - -1.291183;9.629884;1.165000;, - -1.291183;9.629884;1.165000;, - -1.291183;9.629884;1.165000;, - -1.291183;10.090521;1.165000;, - -1.291183;10.090521;1.165000;, - -1.291183;10.090521;1.165000;, - -1.206975;10.200697;2.113860;, - -1.291183;10.090521;2.100000;, - -1.291183;10.090521;2.100000;, - -1.291183;8.914934;1.165000;, - -1.291183;8.914934;1.165000;, - -1.291183;8.914934;1.165000;, - -1.291183;8.914934;1.580000;, - -1.291183;8.914934;1.580000;, - -1.291183;8.914934;1.580000;, - -0.324000;10.031889;1.000000;, - 0.000000;10.003599;1.427500;, - -0.712800;10.003599;1.427500;, - -0.712800;10.105600;1.292500;, - -0.712800;10.105600;1.292500;, - 0.000000;10.105600;1.292500;, - 0.000000;10.105600;1.292500;, - -0.473000;7.990001;1.320000;, - -0.473000;7.990001;1.320000;, - -0.473000;7.990001;1.320000;, - -0.350000;7.990001;1.320000;, - -0.350000;7.990001;1.320000;, - -0.350000;7.990001;1.580000;, - -0.350000;7.990001;1.580000;, - -0.473000;7.990001;1.580000;, - -0.473000;7.990001;1.580000;, - -0.473000;9.840000;1.400000;, - -0.473000;9.840000;1.400000;, - -0.350000;9.840000;1.400000;, - -0.602000;8.120901;1.438300;, - -0.602000;9.824600;1.518300;, - -0.350000;9.716153;1.400000;, - -0.350000;9.716153;1.400000;, - -0.602000;9.714376;1.518300;, - -0.602000;9.714376;1.518300;, - -0.473000;9.716153;1.400000;, - -0.701730;10.090521;1.165000;, - -0.701730;10.090521;1.165000;, - -0.701730;10.090521;1.165000;, - -0.701730;10.090521;2.100000;, - -0.701730;10.090521;2.100000;, - -0.701730;9.629884;2.100000;, - -0.701730;9.629884;2.100000;, - -0.701730;9.629884;2.100000;, - -0.701730;9.629884;1.165000;, - -0.701730;9.629884;1.165000;, - -0.701730;9.629884;1.165000;, - -0.785938;10.200697;2.113860;, - -0.701730;8.914934;1.580000;, - -0.701730;8.914934;1.580000;, - -0.701730;8.914934;1.580000;, - -0.701730;8.914934;1.165000;, - -0.701730;8.914934;1.165000;, - -0.701730;8.914934;1.165000;, - -5.757436;10.788371;1.055375;, - -5.757436;10.788371;1.055375;, - -5.757436;10.788371;1.055375;, - -5.557411;10.788371;1.056685;, - -5.557411;10.788371;1.056685;, - -5.557411;10.788371;1.056685;, - -5.557411;11.108371;1.056685;, - -5.557411;11.108371;1.056685;, - -5.757436;11.108371;1.055375;, - -5.757436;11.108371;1.055375;, - -5.764566;11.108371;1.480943;, - -5.764566;11.108371;1.480943;, - -5.764566;11.108371;1.480943;, - -5.564542;11.108371;1.482253;, - -5.564542;11.108371;1.482253;, - -5.564542;11.108371;1.482253;, - -5.564542;10.788371;1.482253;, - -5.564542;10.788371;1.482253;, - -5.764566;10.788371;1.480943;, - -5.764566;10.788371;1.480943;, - -5.557411;10.948371;1.056685;, - -5.557411;10.948371;1.056685;, - -5.557411;10.948371;1.056685;, - -5.564542;10.948371;1.482253;, - -5.564542;10.948371;1.482253;, - -5.764566;10.948371;1.480943;, - -5.764566;10.948371;1.480943;, - -5.757436;10.948371;1.055375;, - -5.757436;10.948371;1.055375;, - -5.757436;10.948371;1.055375;, - -3.477382;10.768522;1.210001;, - -3.477382;10.768522;1.210001;, - -3.477382;10.768522;1.210001;, - -3.477382;10.768522;1.210001;, - -3.308206;10.895405;1.210001;, - -3.308206;10.895405;1.210001;, - -3.308206;10.895405;1.210001;, - -3.370776;10.653745;1.360001;, - -3.370776;10.653745;1.360001;, - -2.610355;10.895405;1.210000;, - -2.610355;10.895405;1.210000;, - -2.605451;10.759588;1.360000;, - -2.605451;10.759588;1.360000;, - -3.221444;10.759588;1.360001;, - -3.221444;10.759588;1.360001;, - -1.954798;10.895405;1.210000;, - -1.954798;10.895405;1.210000;, - -1.954798;10.895405;1.210000;, - -1.954798;10.895405;1.210000;, - -1.574152;10.514757;1.210000;, - -1.574152;10.514757;1.210000;, - -1.574152;10.514757;1.210000;, - -2.026791;10.759588;1.360000;, - -2.026791;10.759588;1.360000;, - -1.690794;10.442054;1.360000;, - -1.690794;10.442054;1.360000;, - -1.206975;10.651367;1.868713;, - -1.206975;10.651367;1.868713;, - -1.291183;10.669608;1.785000;, - -1.291183;10.669608;1.785000;, - -1.291183;10.669608;1.785000;, - -1.291183;10.669608;1.785000;, - -0.384438;11.348052;1.336887;, - -0.384438;10.811944;1.336887;, - -0.384438;10.811944;1.336887;, - -0.384438;10.811944;1.336887;, - -0.384438;11.621069;1.336887;, - -0.384438;11.621069;1.336887;, - -0.384438;10.303647;1.119859;, - -0.384438;10.303647;1.119859;, - -0.306190;11.694510;1.336887;, - 0.000000;11.694510;1.336887;, - 0.000000;10.811944;1.336887;, - 0.000000;10.811944;1.336887;, - -0.306190;10.811944;1.336887;, - -0.306190;10.811944;1.336887;, - -0.306190;10.811944;1.336887;, - 0.000000;10.303647;1.119859;, - -0.306190;10.303647;1.119859;, - -0.306190;10.303647;1.119859;, - -0.290080;11.185386;0.922292;, - -0.290080;11.185386;0.922292;, - -0.290080;11.154265;0.922292;, - -0.290080;11.154265;0.922292;, - -0.203526;11.460281;0.922292;, - -0.282675;11.429161;0.922292;, - -0.282675;11.429161;0.922292;, - -0.192219;10.728957;0.922292;, - -0.282675;10.760077;0.922292;, - -0.282675;10.760077;0.922292;, - -0.191908;10.391821;0.997700;, - -0.191908;10.391821;0.997700;, - -0.191908;10.827504;0.997700;, - -0.191908;10.827504;0.997700;, - 0.000000;10.827504;0.997700;, - 0.000000;10.391821;0.997700;, - -0.320198;10.370019;1.071678;, - -0.320198;10.370019;1.071678;, - -0.701730;10.669608;1.785000;, - -0.701730;10.669608;1.785000;, - -0.701730;10.669608;1.785000;, - -0.701730;10.669608;1.785000;, - -0.785938;10.651367;1.868713;, - -0.785938;10.651367;1.868713;, - 0.000000;5.117500;1.770000;, - -0.434000;5.117500;1.770000;, - -0.434000;5.117500;1.770000;, - -0.434000;5.117500;1.770000;, - -0.434000;5.117500;1.770000;, - -0.474000;6.403000;1.770000;, - -0.474000;6.403000;1.770000;, - 0.000000;6.403000;1.770000;, - -1.380187;8.442361;1.740032;, - -1.380187;8.442361;1.740032;, - -1.380187;8.442361;1.881088;, - -1.380187;8.442361;1.881088;, - -1.380187;8.442361;1.881088;, - -1.375398;8.500993;1.659580;, - -1.375398;8.500993;1.659580;, - -1.300374;8.378100;1.690000;, - -1.300374;8.378100;1.690000;, - -1.001073;8.378100;1.690000;, - -1.001073;8.378100;1.920000;, - -1.001073;8.378100;1.920000;, - -1.300374;8.378100;1.920000;, - -1.300374;8.378100;1.920000;, - -1.300374;8.378100;1.920000;, - -1.157854;9.729999;1.670000;, - -1.380187;9.932087;2.125760;, - -1.380187;9.932087;1.740032;, - -1.380187;9.932087;1.740032;, - -1.380187;9.193751;2.311072;, - -1.380187;9.193751;2.311072;, - -1.380187;9.786242;2.311072;, - -1.380187;9.786242;2.311072;, - -1.375398;9.853255;1.659580;, - -1.375398;9.853255;1.659580;, - -1.001073;9.165900;2.390000;, - -1.300374;9.165900;2.390000;, - -1.300374;9.165900;2.390000;, - -1.001073;9.822401;2.390000;, - -1.001073;9.822401;2.390000;, - -1.300374;9.822401;2.390000;, - -1.300374;9.822401;2.390000;, - -1.300374;9.822401;2.390000;, - -1.300374;9.822401;2.390000;, - -1.001073;9.984000;2.180000;, - -1.300374;9.984000;2.180000;, - -1.300374;9.984000;2.180000;, - -1.001073;9.984000;1.690000;, - -1.300374;9.984000;1.690000;, - -1.300374;9.984000;1.690000;, - -0.602000;8.120901;1.664500;, - -0.602000;8.120901;1.664500;, - -0.350000;9.731160;1.943483;, - -0.350000;9.731160;1.943483;, - -0.602000;9.727733;1.991131;, - -0.310000;9.017695;1.730000;, - -0.350000;8.980601;1.730000;, - -0.350000;8.980601;1.730000;, - -0.350000;8.266534;1.730000;, - -0.350000;8.266534;1.730000;, - -0.310000;8.229440;1.730000;, - -0.384438;10.811944;1.906371;, - -0.384438;10.811944;1.906371;, - -0.384438;10.811944;1.906371;, - -0.384438;11.434348;2.052865;, - -0.384438;11.434348;2.052865;, - -0.384438;11.434348;2.052865;, - -0.306190;10.811944;1.983195;, - -0.306190;10.811944;1.983195;, - -0.306190;11.507788;2.129689;, - -0.306190;11.507788;2.129689;, - -0.306190;11.507788;2.129689;, - -0.306190;11.507788;2.129689;, - 0.000000;10.811944;1.983195;, - 0.000000;10.811944;1.983195;, - 0.000000;11.507788;2.129689;, - 0.000000;11.507788;2.129689;, - -0.300186;10.544438;1.851922;, - -0.300186;10.544438;1.851922;, - -0.300186;10.957540;1.928746;, - -0.300186;10.957540;1.928746;, - 0.000000;10.544438;1.851922;, - -0.473000;10.370001;2.115000;, - -0.473000;10.370001;2.115000;, - -0.350000;10.370001;2.115000;, - -0.602000;10.285300;2.140350;, - -0.602000;10.285300;2.140350;, - -0.350000;8.929999;2.830000;, - -0.350000;8.929999;2.830000;, - -0.350000;8.929999;2.830000;, - -0.473000;8.929999;2.830000;, - -0.473000;8.929999;2.830000;, - -0.473000;8.929999;2.830000;, - -0.473000;8.929999;2.830000;, - -0.473000;9.770000;3.220000;, - -0.473000;9.770000;3.220000;, - -0.350000;9.770000;3.220000;, - -0.350000;9.770000;3.220000;, - -0.350000;9.770000;3.220000;, - -0.350000;9.770000;3.220000;, - -0.602000;9.014699;2.762400;, - -0.602000;9.014699;2.762400;, - -0.602000;9.014699;2.762400;, - -0.602000;9.762300;3.101700;, - -0.350000;9.755640;2.960000;, - -0.350000;9.755640;2.960000;, - -0.602000;9.749520;2.875500;, - -0.210000;8.377817;2.627000;, - -0.210000;8.377817;2.627000;, - -0.170000;8.452005;2.965000;, - -0.170000;8.452005;2.965000;, - -0.170000;8.452005;2.965000;, - -0.170000;8.804401;2.965000;, - -0.170000;8.804401;2.965000;, - -0.170000;8.804401;2.965000;, - -0.210000;8.860044;2.627000;, - -0.210000;8.860044;2.627000;, - 0.000000;8.452005;2.965000;, - 0.000000;8.452005;2.965000;, - 0.000000;8.804401;2.965000;, - 0.000000;8.804401;2.965000;, - -0.308518;9.017695;2.354001;, - -0.208518;8.924960;2.705000;, - -0.208518;8.924960;2.705000;, - 0.000000;8.924960;2.705000;, - 0.000000;8.924960;2.705000;, - 0.000000;9.017695;2.354001;, - -0.350000;8.979228;2.354001;, - -0.350000;8.979228;2.354001;, - -0.250000;8.886491;2.705000;, - -0.250000;8.886491;2.705000;, - -0.250000;8.886491;2.705000;, - -0.350000;8.267908;2.354001;, - -0.350000;8.267908;2.354001;, - -0.250000;8.360644;2.705000;, - -0.250000;8.360644;2.705000;, - -0.250000;8.360644;2.705000;, - -0.308518;8.229440;2.354001;, - 0.000000;8.229440;2.354001;, - 0.000000;8.322174;2.705000;, - 0.000000;8.322174;2.705000;, - -0.208518;8.322174;2.705000;, - -0.208518;8.322174;2.705000;, - 0.000000;8.887866;2.705000;, - 0.000000;8.359270;2.705000;, - -0.350000;10.300000;3.220000;, - -0.350000;10.300000;3.220000;, - -0.473000;10.300000;3.220000;, - -0.473000;10.300000;3.220000;, - -0.473000;10.300000;3.220000;, - -0.473000;10.300000;3.220000;, - -0.473000;10.370001;3.103000;, - -0.473000;10.370001;3.103000;, - -0.350000;10.370001;3.103000;, - -0.602000;10.285300;2.999910;, - -0.602000;10.285300;2.999910;, - -0.602000;10.223000;3.101700;, - -1.108750;4.035734;0.052731;, - -2.148500;4.277565;-0.215970;, - -2.148500;4.277565;-0.215970;, - -2.148500;4.277565;-0.215970;, - -2.148500;4.035734;-0.327269;, - -2.148500;4.035734;-0.327269;, - -2.148500;3.793904;-0.215970;, - -2.148500;3.793904;-0.215970;, - -2.148500;3.793904;-0.215970;, - -2.148500;3.693734;0.052731;, - -2.148500;3.693734;0.052731;, - -2.191250;4.035734;0.052731;, - -1.650000;4.277565;-0.215970;, - -1.650000;4.277565;-0.215970;, - -1.650000;4.035734;-0.327269;, - -1.650000;3.793904;-0.215970;, - -1.650000;3.793904;-0.215970;, - -1.650000;3.693734;0.052731;, - -1.151500;4.277565;-0.215970;, - -1.151500;4.277565;-0.215970;, - -1.151500;4.277565;-0.215970;, - -1.151500;4.035734;-0.327269;, - -1.151500;4.035734;-0.327269;, - -1.151500;3.793904;-0.215970;, - -1.151500;3.793904;-0.215970;, - -1.151500;3.793904;-0.215970;, - -1.151500;3.693734;0.052731;, - -1.151500;3.693734;0.052731;, - -2.148500;4.377734;0.052731;, - -2.148500;4.377734;0.052731;, - -1.650000;4.377734;0.052731;, - -1.151500;4.377734;0.052731;, - -1.151500;4.377734;0.052731;, - -2.148500;4.277565;0.321432;, - -2.148500;4.277565;0.321432;, - -2.148500;4.277565;0.321432;, - -2.148500;4.035734;0.432731;, - -2.148500;4.035734;0.432731;, - -2.148500;3.793904;0.321432;, - -2.148500;3.793904;0.321432;, - -2.148500;3.793904;0.321432;, - -1.650000;4.035734;0.432731;, - -1.650000;4.277565;0.321432;, - -1.650000;4.277565;0.321432;, - -1.650000;3.793904;0.321432;, - -1.650000;3.793904;0.321432;, - -1.151500;4.277565;0.321432;, - -1.151500;4.277565;0.321432;, - -1.151500;4.277565;0.321432;, - -1.151500;4.035734;0.432731;, - -1.151500;4.035734;0.432731;, - -1.151500;3.793904;0.321432;, - -1.151500;3.793904;0.321432;, - -1.151500;3.793904;0.321432;, - 0.000000;9.095578;3.157000;, - 0.000000;9.577806;3.157000;, - 0.000000;9.735457;2.260000;, - 0.000000;8.947201;2.260000;, - -0.310000;9.735457;2.260000;, - -0.350000;9.698363;2.260000;, - -0.350000;9.698363;2.260000;, - -0.350000;8.984295;2.260000;, - -0.350000;8.984295;2.260000;, - -0.310000;8.947201;2.260000;, - -0.210000;9.095578;3.157000;, - -0.210000;9.095578;3.157000;, - -0.170000;9.169767;3.495000;, - -0.170000;9.169767;3.495000;, - -0.170000;9.169767;3.495000;, - -0.170000;9.522163;3.495000;, - -0.170000;9.522163;3.495000;, - -0.170000;9.522163;3.495000;, - -0.210000;9.577806;3.157000;, - -0.210000;9.577806;3.157000;, - 0.000000;9.169767;3.495000;, - 0.000000;9.169767;3.495000;, - 0.000000;9.522163;3.495000;, - 0.000000;9.522163;3.495000;, - -0.308518;9.735457;2.884000;, - -0.208518;9.642721;3.235000;, - -0.208518;9.642721;3.235000;, - 0.000000;9.642721;3.235000;, - 0.000000;9.642721;3.235000;, - 0.000000;9.735457;2.884000;, - -0.350000;9.696989;2.884000;, - -0.350000;9.696989;2.884000;, - -0.250000;9.604253;3.235000;, - -0.250000;9.604253;3.235000;, - -0.250000;9.604253;3.235000;, - -0.350000;8.985670;2.884000;, - -0.350000;8.985670;2.884000;, - -0.250000;9.078405;3.235000;, - -0.250000;9.078405;3.235000;, - -0.250000;9.078405;3.235000;, - -0.308518;8.947201;2.884000;, - 0.000000;8.947201;2.884000;, - 0.000000;9.039936;3.235000;, - 0.000000;9.039936;3.235000;, - -0.208518;9.039936;3.235000;, - -0.208518;9.039936;3.235000;, - 0.000000;9.605628;3.235000;, - 0.000000;9.077031;3.235000;, - -0.706562;8.438701;1.587800;, - -0.706562;8.438701;1.587800;, - -0.706562;8.438701;1.587800;, - -0.706562;8.438701;1.587800;, - -0.706562;9.903199;1.587800;, - -0.706562;9.903199;1.587800;, - -0.706562;9.903199;1.587800;, - -0.706562;9.903199;1.587800;, - -0.621959;8.442361;1.740032;, - -0.621959;8.442361;1.740032;, - -0.621959;8.442361;1.881088;, - -0.621959;8.442361;1.881088;, - -0.621959;8.442361;1.881088;, - -0.626748;8.500993;1.659580;, - -0.626748;8.500993;1.659580;, - -0.701773;8.378100;1.690000;, - -0.701773;8.378100;1.690000;, - -0.701773;8.378100;1.920000;, - -0.701773;8.378100;1.920000;, - -0.701773;8.378100;1.920000;, - -0.621959;9.932087;2.125760;, - -0.621959;9.932087;1.740032;, - -0.621959;9.932087;1.740032;, - -0.621959;9.193751;2.311072;, - -0.621959;9.193751;2.311072;, - -0.621959;9.786242;2.311072;, - -0.621959;9.786242;2.311072;, - -0.626748;9.853255;1.659580;, - -0.626748;9.853255;1.659580;, - -0.701773;9.165900;2.390000;, - -0.701773;9.165900;2.390000;, - -0.701773;9.822401;2.390000;, - -0.701773;9.822401;2.390000;, - -0.701773;9.822401;2.390000;, - -0.701773;9.822401;2.390000;, - -0.701773;9.984000;2.180000;, - -0.701773;9.984000;2.180000;, - -0.701773;9.984000;1.690000;, - -0.701773;9.984000;1.690000;, - -6.594306;9.104997;0.024595;, - -6.594306;9.104997;0.024595;, - -6.594306;9.104997;0.024595;, - -6.561830;9.228369;-0.117754;, - -6.561830;9.228369;-0.117754;, - -6.561830;9.228369;-0.117754;, - -6.561830;9.093629;-0.249652;, - -6.561830;9.093629;-0.249652;, - -6.561830;9.093629;-0.249652;, - -6.561830;9.235703;-0.119092;, - -6.561830;9.235703;-0.119092;, - -6.561830;9.235703;-0.119092;, - -6.561830;9.385450;-0.133884;, - -6.561830;9.385450;-0.133884;, - -6.561830;9.385450;-0.133884;, - -6.561830;9.364082;-0.284082;, - -6.561830;9.364082;-0.284082;, - -6.561830;9.364082;-0.284082;, - -6.561830;9.094540;-0.257456;, - -6.561830;9.094540;-0.257456;, - -6.561830;9.094540;-0.257456;, - -6.561830;9.404812;-0.108547;, - -6.561830;9.404812;-0.108547;, - -6.561830;9.404812;-0.108547;, - -6.561830;9.551003;-0.018219;, - -6.561830;9.551003;-0.018219;, - -6.561830;9.679543;-0.094811;, - -6.561830;9.679543;-0.094811;, - -6.561830;9.679543;-0.094811;, - -6.561830;9.377419;-0.281490;, - -6.561830;9.377419;-0.281490;, - -6.561830;9.377419;-0.281490;, - -6.756689;9.104997;0.024595;, - -6.756689;9.104997;0.024595;, - -6.756689;9.104997;0.024595;, - -6.789165;9.228369;-0.117754;, - -6.789165;9.228369;-0.117754;, - -6.789165;9.228369;-0.117754;, - -6.789165;9.093629;-0.249652;, - -6.789165;9.093629;-0.249652;, - -6.789165;9.093629;-0.249652;, - -6.740450;9.016507;0.046151;, - -6.740450;9.016507;0.046151;, - -6.740450;9.016507;0.046151;, - -6.610544;9.016507;0.046151;, - -6.610544;9.016507;0.046151;, - -6.610544;9.016507;0.046151;, - -6.789165;9.235703;-0.119092;, - -6.789165;9.235703;-0.119092;, - -6.789165;9.235703;-0.119092;, - -6.789165;9.385450;-0.133884;, - -6.789165;9.385450;-0.133884;, - -6.789165;9.385450;-0.133884;, - -6.789165;9.364082;-0.284082;, - -6.789165;9.364082;-0.284082;, - -6.789165;9.364082;-0.284082;, - -6.789165;9.094540;-0.257456;, - -6.789165;9.094540;-0.257456;, - -6.789165;9.094540;-0.257456;, - -6.789165;9.404812;-0.108547;, - -6.789165;9.404812;-0.108547;, - -6.789165;9.404812;-0.108547;, - -6.789165;9.551003;-0.018219;, - -6.789165;9.551003;-0.018219;, - -6.789165;9.679543;-0.094811;, - -6.789165;9.679543;-0.094811;, - -6.789165;9.679543;-0.094811;, - -6.789165;9.377419;-0.281490;, - -6.789165;9.377419;-0.281490;, - -6.789165;9.377419;-0.281490;, - -6.728245;9.275375;0.120996;, - -6.728245;9.275375;0.120996;, - -6.728245;9.275375;0.120996;, - -6.900592;9.282207;0.093882;, - -6.900592;9.282207;0.093882;, - -6.900592;9.282207;0.093882;, - -6.927647;9.112520;0.093882;, - -6.927647;9.112520;0.093882;, - -6.927647;9.112520;0.093882;, - -6.905502;9.286638;0.093882;, - -6.905502;9.286638;0.093882;, - -6.905502;9.286638;0.093882;, - -6.996336;9.384120;0.093882;, - -6.996336;9.384120;0.093882;, - -6.996336;9.384120;0.093882;, - -7.097478;9.284227;0.093882;, - -7.097478;9.284227;0.093882;, - -7.097478;9.284227;0.093882;, - -6.933978;9.108757;0.093882;, - -6.933978;9.108757;0.093882;, - -6.933978;9.108757;0.093882;, - -6.987667;9.412109;0.093882;, - -6.987667;9.412109;0.093882;, - -6.987667;9.412109;0.093882;, - -6.997853;9.566422;0.093882;, - -6.997853;9.566422;0.093882;, - -7.123692;9.614031;0.093882;, - -7.123692;9.614031;0.093882;, - -7.123692;9.614031;0.093882;, - -7.102638;9.295116;0.093882;, - -7.102638;9.295116;0.093882;, - -7.102638;9.295116;0.093882;, - -6.728245;9.275375;0.256563;, - -6.728245;9.275375;0.256563;, - -6.728245;9.275375;0.256563;, - -6.900592;9.282207;0.283676;, - -6.900592;9.282207;0.283676;, - -6.900592;9.282207;0.283676;, - -6.927647;9.112520;0.283676;, - -6.927647;9.112520;0.283676;, - -6.927647;9.112520;0.283676;, - -6.664969;9.225002;0.243006;, - -6.664969;9.225002;0.243006;, - -6.664969;9.225002;0.243006;, - -6.664969;9.225002;0.134552;, - -6.664969;9.225002;0.134552;, - -6.664969;9.225002;0.134552;, - -6.905502;9.286638;0.283676;, - -6.905502;9.286638;0.283676;, - -6.905502;9.286638;0.283676;, - -6.996336;9.384120;0.283676;, - -6.996336;9.384120;0.283676;, - -6.996336;9.384120;0.283676;, - -7.097478;9.284227;0.283676;, - -7.097478;9.284227;0.283676;, - -7.097478;9.284227;0.283676;, - -6.933978;9.108757;0.283676;, - -6.933978;9.108757;0.283676;, - -6.933978;9.108757;0.283676;, - -6.987667;9.412109;0.283676;, - -6.987667;9.412109;0.283676;, - -6.987667;9.412109;0.283676;, - -6.997853;9.566422;0.283676;, - -6.997853;9.566422;0.283676;, - -7.123692;9.614031;0.283676;, - -7.123692;9.614031;0.283676;, - -7.123692;9.614031;0.283676;, - -7.102638;9.295116;0.283676;, - -7.102638;9.295116;0.283676;, - -7.102638;9.295116;0.283676;, - -6.751895;9.313591;0.331667;, - -6.751895;9.313591;0.331667;, - -6.751895;9.313591;0.331667;, - -6.912178;9.319603;0.304554;, - -6.912178;9.319603;0.304554;, - -6.912178;9.319603;0.304554;, - -6.937339;9.170279;0.304554;, - -6.937339;9.170279;0.304554;, - -6.937339;9.170279;0.304554;, - -6.916745;9.323501;0.304554;, - -6.916745;9.323501;0.304554;, - -6.916745;9.323501;0.304554;, - -7.001220;9.409288;0.304554;, - -7.001220;9.409288;0.304554;, - -7.001220;9.409288;0.304554;, - -7.095283;9.321381;0.304554;, - -7.095283;9.321381;0.304554;, - -7.095283;9.321381;0.304554;, - -6.943227;9.166967;0.304554;, - -6.943227;9.166967;0.304554;, - -6.943227;9.166967;0.304554;, - -6.993157;9.433917;0.304554;, - -6.993157;9.433917;0.304554;, - -6.993157;9.433917;0.304554;, - -7.002631;9.569713;0.304554;, - -7.002631;9.569713;0.304554;, - -7.119660;9.611607;0.304554;, - -7.119660;9.611607;0.304554;, - -7.119660;9.611607;0.304554;, - -7.100082;9.330963;0.304554;, - -7.100082;9.330963;0.304554;, - -7.100082;9.330963;0.304554;, - -6.751895;9.313591;0.467235;, - -6.751895;9.313591;0.467235;, - -6.751895;9.313591;0.467235;, - -6.912178;9.319603;0.494348;, - -6.912178;9.319603;0.494348;, - -6.912178;9.319603;0.494348;, - -6.937339;9.170279;0.494348;, - -6.937339;9.170279;0.494348;, - -6.937339;9.170279;0.494348;, - -6.693048;9.269262;0.453678;, - -6.693048;9.269262;0.453678;, - -6.693048;9.269262;0.453678;, - -6.693048;9.269262;0.345224;, - -6.693048;9.269262;0.345224;, - -6.693048;9.269262;0.345224;, - -6.916745;9.323501;0.494348;, - -6.916745;9.323501;0.494348;, - -6.916745;9.323501;0.494348;, - -7.001220;9.409288;0.494348;, - -7.001220;9.409288;0.494348;, - -7.001220;9.409288;0.494348;, - -7.095283;9.321381;0.494348;, - -7.095283;9.321381;0.494348;, - -7.095283;9.321381;0.494348;, - -6.943227;9.166967;0.494348;, - -6.943227;9.166967;0.494348;, - -6.943227;9.166967;0.494348;, - -6.993157;9.433917;0.494348;, - -6.993157;9.433917;0.494348;, - -6.993157;9.433917;0.494348;, - -7.002631;9.569713;0.494348;, - -7.002631;9.569713;0.494348;, - -7.119660;9.611607;0.494348;, - -7.119660;9.611607;0.494348;, - -7.119660;9.611607;0.494348;, - -7.100082;9.330963;0.494348;, - -7.100082;9.330963;0.494348;, - -7.100082;9.330963;0.494348;, - -6.728245;9.275375;-0.089676;, - -6.728245;9.275375;-0.089676;, - -6.728245;9.275375;-0.089676;, - -6.900592;9.282207;-0.116790;, - -6.900592;9.282207;-0.116790;, - -6.900592;9.282207;-0.116790;, - -6.927647;9.112520;-0.116790;, - -6.927647;9.112520;-0.116790;, - -6.927647;9.112520;-0.116790;, - -6.905502;9.286638;-0.116790;, - -6.905502;9.286638;-0.116790;, - -6.905502;9.286638;-0.116790;, - -6.996336;9.384120;-0.116790;, - -6.996336;9.384120;-0.116790;, - -6.996336;9.384120;-0.116790;, - -7.097478;9.284227;-0.116790;, - -7.097478;9.284227;-0.116790;, - -7.097478;9.284227;-0.116790;, - -6.933978;9.108757;-0.116790;, - -6.933978;9.108757;-0.116790;, - -6.933978;9.108757;-0.116790;, - -6.987667;9.412109;-0.116790;, - -6.987667;9.412109;-0.116790;, - -6.987667;9.412109;-0.116790;, - -6.997853;9.566422;-0.116790;, - -6.997853;9.566422;-0.116790;, - -7.123692;9.614031;-0.116790;, - -7.123692;9.614031;-0.116790;, - -7.123692;9.614031;-0.116790;, - -7.102638;9.295116;-0.116790;, - -7.102638;9.295116;-0.116790;, - -7.102638;9.295116;-0.116790;, - -6.728245;9.275375;0.045891;, - -6.728245;9.275375;0.045891;, - -6.728245;9.275375;0.045891;, - -6.900592;9.282207;0.073004;, - -6.900592;9.282207;0.073004;, - -6.900592;9.282207;0.073004;, - -6.927647;9.112520;0.073004;, - -6.927647;9.112520;0.073004;, - -6.927647;9.112520;0.073004;, - -6.664969;9.225002;0.032334;, - -6.664969;9.225002;0.032334;, - -6.664969;9.225002;0.032334;, - -6.664969;9.225002;-0.076120;, - -6.664969;9.225002;-0.076120;, - -6.664969;9.225002;-0.076120;, - -6.905502;9.286638;0.073004;, - -6.905502;9.286638;0.073004;, - -6.905502;9.286638;0.073004;, - -6.996336;9.384120;0.073004;, - -6.996336;9.384120;0.073004;, - -6.996336;9.384120;0.073004;, - -7.097478;9.284227;0.073004;, - -7.097478;9.284227;0.073004;, - -7.097478;9.284227;0.073004;, - -6.933978;9.108757;0.073004;, - -6.933978;9.108757;0.073004;, - -6.933978;9.108757;0.073004;, - -6.987667;9.412109;0.073004;, - -6.987667;9.412109;0.073004;, - -6.987667;9.412109;0.073004;, - -6.997853;9.566422;0.073004;, - -6.997853;9.566422;0.073004;, - -7.123692;9.614031;0.073004;, - -7.123692;9.614031;0.073004;, - -7.123692;9.614031;0.073004;, - -7.102638;9.295116;0.073004;, - -7.102638;9.295116;0.073004;, - -7.102638;9.295116;0.073004;, - -1.567670;5.483616;0.004405;, - -1.567670;5.483616;0.004405;, - -1.567670;5.404343;-0.032080;, - -1.567670;5.325069;0.004405;, - -1.567670;5.325069;0.004405;, - -1.567670;5.292233;0.092487;, - -0.832316;5.483616;0.004405;, - -0.832316;5.483616;0.004405;, - -0.832316;5.404343;-0.032080;, - -0.832316;5.325069;0.004405;, - -0.832316;5.325069;0.004405;, - -0.832316;5.292233;0.092487;, - -0.096963;5.483616;0.004405;, - -0.096963;5.483616;0.004405;, - -0.096963;5.404343;-0.032080;, - -0.096963;5.325069;0.004405;, - -0.096963;5.325069;0.004405;, - -0.096963;5.292233;0.092487;, - -1.567670;5.516453;0.092487;, - -0.832316;5.516453;0.092487;, - -0.096963;5.516453;0.092487;, - -1.567670;5.483616;0.180569;, - -1.567670;5.483616;0.180569;, - -1.567670;5.404343;0.217054;, - -1.567670;5.325069;0.180569;, - -1.567670;5.325069;0.180569;, - -0.832316;5.404343;0.217054;, - -0.832316;5.483616;0.180569;, - -0.832316;5.483616;0.180569;, - -0.832316;5.325069;0.180569;, - -0.832316;5.325069;0.180569;, - -0.096963;5.483616;0.180569;, - -0.096963;5.483616;0.180569;, - -0.096963;5.404343;0.217054;, - -0.096963;5.325069;0.180569;, - -0.096963;5.325069;0.180569;, - -1.567670;6.178721;-0.218650;, - -1.567670;6.178721;-0.218650;, - -1.567670;5.914475;-0.340266;, - -1.567670;5.650230;-0.218650;, - -1.567670;5.650230;-0.218650;, - -1.567670;5.540776;0.074957;, - -0.832316;6.178721;-0.218650;, - -0.832316;6.178721;-0.218650;, - -0.832316;5.914475;-0.340266;, - -0.832316;5.650230;-0.218650;, - -0.832316;5.650230;-0.218650;, - -0.832316;5.540776;0.074957;, - -0.096963;6.178721;-0.218650;, - -0.096963;6.178721;-0.218650;, - -0.096963;5.914475;-0.340266;, - -0.096963;5.650230;-0.218650;, - -0.096963;5.650230;-0.218650;, - -0.096963;5.540776;0.074957;, - -1.567670;6.288176;0.074957;, - -0.832316;6.288176;0.074957;, - -0.096963;6.288176;0.074957;, - -1.567670;6.178721;0.368563;, - -1.567670;6.178721;0.368563;, - -1.567670;5.914475;0.490179;, - -1.567670;5.650230;0.368563;, - -1.567670;5.650230;0.368563;, - -0.832316;5.914475;0.490179;, - -0.832316;6.178721;0.368563;, - -0.832316;6.178721;0.368563;, - -0.832316;5.650230;0.368563;, - -0.832316;5.650230;0.368563;, - -0.096963;6.178721;0.368563;, - -0.096963;6.178721;0.368563;, - -0.096963;5.914475;0.490179;, - -0.096963;5.650230;0.368563;, - -0.096963;5.650230;0.368563;, - -3.694536;9.277638;0.149999;, - -3.694536;9.277638;0.149999;, - -3.694536;9.650759;0.149999;, - -3.694536;9.650759;0.149999;, - -4.152457;9.650759;0.149999;, - -4.152457;9.650759;0.149999;, - -4.152457;9.277638;0.149999;, - -4.152457;9.277638;0.149999;, - -4.332345;9.277638;0.662131;, - -4.332345;9.277638;0.662131;, - -4.332345;9.277638;0.662131;, - -4.332345;9.650759;0.662131;, - -4.332345;9.650759;0.662131;, - -4.332345;9.650759;0.662131;, - -4.406857;9.650759;0.449999;, - -4.406857;9.650759;0.449999;, - -4.406857;9.277638;0.449999;, - -4.406857;9.277638;0.449999;, - -4.332345;9.277638;0.237867;, - -4.332345;9.277638;0.237867;, - -4.332345;9.277638;0.237867;, - -4.332345;9.650759;0.237867;, - -4.332345;9.650759;0.237867;, - -4.332345;9.650759;0.237867;, - -3.514649;9.277638;0.662131;, - -3.514649;9.277638;0.662131;, - -3.514649;9.277638;0.662131;, - -3.440137;9.277638;0.449999;, - -3.440137;9.277638;0.449999;, - -3.440137;9.650759;0.449999;, - -3.440137;9.650759;0.449999;, - -3.514649;9.650759;0.662131;, - -3.514649;9.650759;0.662131;, - -3.514649;9.650759;0.662131;, - -3.514649;9.277638;0.237867;, - -3.514649;9.277638;0.237867;, - -3.514649;9.277638;0.237867;, - -3.514649;9.650759;0.237867;, - -3.514649;9.650759;0.237867;, - -3.514649;9.650759;0.237867;, - -3.694537;9.650759;0.749999;, - -3.694537;9.650759;0.749999;, - -3.694537;9.277638;0.749999;, - -3.694537;9.277638;0.749999;, - -4.152457;9.277638;0.749999;, - -4.152457;9.277638;0.749999;, - -4.152457;9.650759;0.749999;, - -4.152457;9.650759;0.749999;, - -3.348027;9.908371;-0.050170;, - -3.460232;9.972371;0.029085;, - -3.460232;9.972371;0.029085;, - -3.460232;9.972371;0.029085;, - -3.349367;10.036371;0.029811;, - -3.349367;10.036371;0.029811;, - -3.349367;10.036371;0.029811;, - -3.460232;9.844371;0.029085;, - -3.460232;9.844371;0.029085;, - -3.460232;9.844371;0.029085;, - -3.349367;9.780371;0.029811;, - -3.349367;9.780371;0.029811;, - -3.349367;9.780371;0.029811;, - -3.238502;9.844371;0.030537;, - -3.238502;9.844371;0.030537;, - -3.238502;9.844371;0.030537;, - -3.238502;9.972371;0.030537;, - -3.238502;9.972371;0.030537;, - -3.238502;9.972371;0.030537;, - -3.363439;10.036371;0.869615;, - -3.363439;10.036371;0.869615;, - -3.363439;10.036371;0.869615;, - -3.474304;9.972371;0.868889;, - -3.474304;9.972371;0.868889;, - -3.474304;9.972371;0.868889;, - -3.474304;9.844371;0.868889;, - -3.474304;9.844371;0.868889;, - -3.474304;9.844371;0.868889;, - -3.363439;9.780371;0.869615;, - -3.363439;9.780371;0.869615;, - -3.363439;9.780371;0.869615;, - -3.252574;9.844371;0.870341;, - -3.252574;9.844371;0.870341;, - -3.252574;9.844371;0.870341;, - -3.252574;9.972371;0.870341;, - -3.252574;9.972371;0.870341;, - -3.252574;9.972371;0.870341;, - -3.364779;9.908371;0.949597;, - -4.548027;9.908371;-0.030170;, - -4.660232;9.972371;0.049085;, - -4.660232;9.972371;0.049085;, - -4.660232;9.972371;0.049085;, - -4.549367;10.036371;0.049811;, - -4.549367;10.036371;0.049811;, - -4.549367;10.036371;0.049811;, - -4.660232;9.844371;0.049085;, - -4.660232;9.844371;0.049085;, - -4.660232;9.844371;0.049085;, - -4.549367;9.780371;0.049811;, - -4.549367;9.780371;0.049811;, - -4.549367;9.780371;0.049811;, - -4.438502;9.844371;0.050537;, - -4.438502;9.844371;0.050537;, - -4.438502;9.844371;0.050537;, - -4.438502;9.972371;0.050537;, - -4.438502;9.972371;0.050537;, - -4.438502;9.972371;0.050537;, - -4.563439;10.036371;0.889615;, - -4.563439;10.036371;0.889615;, - -4.563439;10.036371;0.889615;, - -4.674304;9.972371;0.888889;, - -4.674304;9.972371;0.888889;, - -4.674304;9.972371;0.888889;, - -4.674304;9.844371;0.888889;, - -4.674304;9.844371;0.888889;, - -4.674304;9.844371;0.888889;, - -4.563439;9.780371;0.889615;, - -4.563439;9.780371;0.889615;, - -4.563439;9.780371;0.889615;, - -4.452574;9.844371;0.890341;, - -4.452574;9.844371;0.890341;, - -4.452574;9.844371;0.890341;, - -4.452574;9.972371;0.890341;, - -4.452574;9.972371;0.890341;, - -4.452574;9.972371;0.890341;, - -4.564779;9.908371;0.969597;, - 1.157854;10.366903;1.400000;, - 1.157854;10.366903;-0.100000;, - 1.157854;8.063718;-0.200000;, - 1.157854;8.063718;1.400000;, - 0.753840;8.634896;-0.380000;, - 0.753840;8.634896;-1.450000;, - 0.540000;6.512889;-1.250000;, - 0.540000;5.747889;-1.250000;, - 0.320198;10.985079;1.340562;, - 0.783621;9.564607;-0.920000;, - 0.783621;10.114978;1.320000;, - 1.650000;0.372590;-1.341000;, - 1.650000;0.012590;-1.341000;, - 1.054643;0.540345;-0.085888;, - 1.088500;6.391939;-0.509769;, - 1.586200;4.409444;-1.192000;, - 1.586200;4.409444;-0.991000;, - 1.586200;4.409444;-0.690000;, - 1.120000;2.735444;0.089000;, - 0.580000;2.735444;0.089000;, - 1.235402;0.607264;0.837000;, - 1.354000;0.372590;-1.341000;, - 1.354000;0.012590;-1.341000;, - 1.354000;0.552590;-0.191000;, - 1.354000;1.092590;-1.341000;, - 1.120000;2.285444;0.209000;, - 2.198000;-0.032410;-2.691000;, - 2.198000;-0.032410;-2.691000;, - 2.198000;0.057590;-2.841000;, - 2.198000;0.057590;-2.841000;, - 2.198000;0.057590;-2.841000;, - 1.650000;-0.032410;-2.691000;, - 1.650000;0.057590;-2.841000;, - 1.650000;0.057590;-2.841000;, - 1.102000;-0.032410;-2.691000;, - 1.102000;-0.032410;-2.691000;, - 1.102000;0.057590;-2.841000;, - 1.102000;0.057590;-2.841000;, - 1.102000;0.057590;-2.841000;, - 0.297220;5.130789;-2.375762;, - 0.297220;5.130789;-2.375762;, - 0.355000;5.248089;-2.490761;, - 0.355000;5.248089;-2.490761;, - 0.243220;4.404039;-2.145761;, - 0.243220;4.404039;-2.145761;, - 0.243220;4.404039;-2.145761;, - 0.355000;6.604689;-2.188261;, - 0.355000;6.604689;-2.188261;, - 0.355000;6.604689;-2.188261;, - 0.355000;6.604689;-2.188261;, - 0.355000;6.533288;-2.185761;, - 0.355000;6.533288;-2.185761;, - 0.355000;6.533288;-2.185761;, - 0.355000;6.533288;-2.185761;, - 0.434700;8.568343;-2.243182;, - 0.434700;8.568343;-2.243182;, - 0.348300;8.592272;-2.323182;, - 0.348300;8.592272;-2.323182;, - 0.348300;8.592272;-2.323182;, - 0.621000;8.938809;-2.187204;, - 0.621000;8.938809;-2.187204;, - 0.621000;9.443933;-2.105358;, - 0.621000;9.443933;-2.105358;, - 0.434700;8.887272;-2.277475;, - 0.434700;8.887272;-2.277475;, - 0.434700;9.518987;-2.158886;, - 0.434700;9.634454;-2.098433;, - 0.434700;9.634454;-2.098433;, - 0.434700;8.796896;-2.166006;, - 0.348300;8.844754;-2.226006;, - 0.348300;8.844754;-2.226006;, - 2.090000;0.642590;-1.891000;, - 2.090000;0.642590;-1.891000;, - 2.090000;0.642590;-1.891000;, - 1.946000;0.642590;-1.891000;, - 1.946000;0.642590;-1.891000;, - 2.198000;-0.032410;-1.921000;, - 2.198000;-0.032410;-1.921000;, - 2.198000;0.597590;-1.921000;, - 2.198000;0.597590;-1.921000;, - 1.650000;0.642590;-1.891000;, - 1.650000;0.642590;-1.891000;, - 1.650000;-0.032410;-1.921000;, - 1.650000;0.597590;-1.921000;, - 1.210000;0.642590;-1.891000;, - 1.210000;0.642590;-1.891000;, - 1.210000;0.642590;-1.891000;, - 1.354000;0.642590;-1.891000;, - 1.354000;0.642590;-1.891000;, - 1.102000;-0.032410;-1.921000;, - 1.102000;-0.032410;-1.921000;, - 1.102000;0.597590;-1.921000;, - 1.102000;0.597590;-1.921000;, - 2.211500;5.076511;-1.462134;, - 2.211500;5.076511;-1.462134;, - 2.211500;5.076511;-1.462134;, - 1.650000;5.076511;-1.462134;, - 1.650000;5.076511;-1.462134;, - 1.088500;5.076511;-1.462134;, - 1.088500;5.076511;-1.462134;, - 1.088500;5.076511;-1.462134;, - 0.455220;5.130789;-1.383261;, - 0.455220;5.130789;-1.383261;, - 0.455220;5.130789;-1.383261;, - 0.455220;5.130789;-1.383261;, - 0.401220;4.404039;-1.383261;, - 0.401220;4.404039;-1.383261;, - 0.401220;4.404039;-1.383261;, - 0.540000;5.747889;-1.600000;, - 0.540000;5.747889;-1.600000;, - 0.864000;5.747889;-1.600000;, - 0.864000;5.747889;-1.600000;, - 0.864000;5.747889;-1.600000;, - 0.270000;4.472888;-1.360000;, - 0.270000;4.472888;-1.360000;, - 0.270000;5.747889;-1.600000;, - 0.270000;5.747889;-1.600000;, - 0.270000;5.747889;-1.600000;, - 0.344000;4.439500;-1.365000;, - 0.344000;4.439500;-1.365000;, - 0.434000;5.122600;-1.365000;, - 0.434000;5.122600;-1.365000;, - 0.442800;7.096839;-1.498261;, - 0.442800;7.096839;-1.498261;, - 0.442800;7.096839;-1.498261;, - 0.246460;6.979538;-2.088261;, - 0.246460;6.979538;-2.088261;, - 0.246460;6.979538;-2.088261;, - 0.864000;6.512889;-1.600000;, - 0.864000;6.512889;-1.600000;, - 0.864000;6.512889;-1.600000;, - 0.540000;6.512889;-1.600000;, - 0.540000;6.512889;-1.600000;, - 1.217160;8.469534;-1.810000;, - 1.217160;8.469534;-1.810000;, - 1.490400;8.469534;-1.586000;, - 1.490400;8.469534;-1.586000;, - 1.490400;8.469534;-1.586000;, - 1.490400;8.469534;-1.586000;, - 1.490400;8.469534;-1.746000;, - 1.490400;8.469534;-1.746000;, - 1.490400;8.469534;-1.746000;, - 1.304100;8.397746;-1.570000;, - 1.304100;8.397746;-1.570000;, - 1.304100;8.397746;-1.730000;, - 1.304100;8.397746;-1.730000;, - 1.304100;8.397746;-1.730000;, - 1.403460;8.547303;-1.830000;, - 0.360180;8.335782;-1.400000;, - 0.360180;8.335782;-1.400000;, - 0.621000;8.497011;-1.571497;, - 0.621000;8.497011;-1.571497;, - 0.621000;8.497011;-1.571497;, - 0.434700;8.321987;-1.506799;, - 0.434700;8.321987;-1.506799;, - 0.434700;8.321987;-1.506799;, - 0.434700;8.210368;-1.631449;, - 0.434700;7.903518;-1.723446;, - 0.434700;7.903518;-1.723446;, - 0.434700;8.703467;-2.074645;, - 0.348300;7.831731;-1.743446;, - 0.348300;7.831731;-1.743446;, - 0.348300;7.831731;-1.743446;, - 0.348300;7.831731;-1.743446;, - 0.720360;8.469534;-1.810000;, - 0.720360;8.469534;-1.810000;, - 0.621000;8.397746;-1.570000;, - 0.621000;8.397746;-1.570000;, - 0.621000;8.397746;-1.570000;, - 0.621000;8.397746;-1.730000;, - 0.621000;8.397746;-1.730000;, - 0.621000;8.397746;-1.730000;, - 0.621000;8.397746;-1.730000;, - 1.217160;9.041694;-2.060000;, - 1.490400;9.095534;-1.850000;, - 1.490400;9.095534;-1.850000;, - 1.490400;9.095534;-1.850000;, - 1.490400;9.095534;-1.850000;, - 1.490400;9.041694;-1.990000;, - 1.490400;9.041694;-1.990000;, - 1.304100;9.191251;-1.870000;, - 1.304100;9.191251;-1.870000;, - 1.304100;9.137410;-2.010000;, - 1.304100;9.137410;-2.010000;, - 1.403460;8.945976;-2.040000;, - 0.621000;9.099913;-1.933061;, - 0.621000;9.563389;-2.052839;, - 0.621000;9.563389;-2.052839;, - 0.621000;9.370822;-1.468720;, - 0.621000;9.720506;-1.617303;, - 0.621000;9.794942;-1.642888;, - 0.621000;9.794942;-1.642888;, - 0.434700;9.875455;-1.670560;, - 0.434700;8.921729;-1.855520;, - 0.348300;8.993517;-1.835520;, - 0.720360;9.041694;-2.060000;, - 0.621000;9.191251;-1.870000;, - 0.621000;9.191251;-1.870000;, - 0.621000;9.191251;-1.870000;, - 0.621000;9.137410;-2.010000;, - 0.621000;9.137410;-2.010000;, - 0.621000;9.137410;-2.010000;, - 0.621000;9.137410;-2.010000;, - 2.090000;0.372590;-1.341000;, - 2.090000;0.372590;-1.341000;, - 2.090000;1.092590;-1.341000;, - 2.090000;1.092590;-1.341000;, - 1.946000;0.372590;-1.341000;, - 2.090000;0.012590;-1.341000;, - 2.090000;0.012590;-1.341000;, - 1.946000;0.012590;-1.341000;, - 1.946000;1.092590;-1.341000;, - 2.198000;-0.032410;-0.991000;, - 2.198000;-0.032410;-0.991000;, - 2.198000;-0.032410;-0.991000;, - 2.198000;0.597590;-0.991000;, - 2.198000;0.597590;-0.991000;, - 2.198000;0.597590;-0.991000;, - 2.225000;0.870444;-1.191000;, - 2.225000;0.870444;-1.191000;, - 2.225000;0.870444;-1.191000;, - 1.650000;1.092590;-1.341000;, - 1.650000;-0.032410;-0.991000;, - 1.650000;-0.032410;-0.991000;, - 1.650000;0.597590;-0.991000;, - 1.650000;0.597590;-0.991000;, - 1.650000;0.870444;-1.191000;, - 1.650000;0.870444;-1.191000;, - 1.210000;0.372590;-1.341000;, - 1.210000;0.372590;-1.341000;, - 1.210000;1.092590;-1.341000;, - 1.210000;1.092590;-1.341000;, - 1.210000;0.012590;-1.341000;, - 1.210000;0.012590;-1.341000;, - 1.102000;-0.032410;-0.991000;, - 1.102000;-0.032410;-0.991000;, - 1.102000;-0.032410;-0.991000;, - 1.102000;0.597590;-0.991000;, - 1.102000;0.597590;-0.991000;, - 1.102000;0.597590;-0.991000;, - 1.075000;0.870444;-1.191000;, - 1.075000;0.870444;-1.191000;, - 1.075000;0.870444;-1.191000;, - 2.139500;2.834444;-1.291000;, - 2.139500;2.834444;-1.291000;, - 2.139500;2.519444;-0.991000;, - 2.139500;2.519444;-0.991000;, - 2.139500;2.519444;-0.991000;, - 2.630000;2.735444;-0.831000;, - 2.630000;2.735444;-0.831000;, - 2.630000;2.735444;-0.831000;, - 2.180000;2.735444;-0.831000;, - 2.180000;2.735444;-0.831000;, - 2.180000;2.735444;-0.831000;, - 1.650000;2.834444;-1.291000;, - 1.650000;2.519444;-0.991000;, - 1.650000;2.519444;-0.991000;, - 1.160500;2.834444;-1.291000;, - 1.160500;2.834444;-1.291000;, - 1.160500;2.519444;-0.991000;, - 1.160500;2.519444;-0.991000;, - 1.160500;2.519444;-0.991000;, - 1.120000;2.735444;-0.831000;, - 1.120000;2.735444;-0.831000;, - 1.120000;2.735444;-0.831000;, - 0.670000;2.735444;-0.831000;, - 0.670000;2.735444;-0.831000;, - 0.670000;2.735444;-0.831000;, - 2.139500;4.319444;-1.291000;, - 2.139500;4.319444;-1.291000;, - 2.139500;4.319444;-1.291000;, - 2.139500;4.319444;-1.291000;, - 2.139500;4.319444;-0.991000;, - 2.139500;4.319444;-0.991000;, - 2.630000;4.040444;-0.831000;, - 2.630000;4.040444;-0.831000;, - 2.630000;4.040444;-0.831000;, - 2.180000;4.040444;-0.831000;, - 2.180000;4.040444;-0.831000;, - 2.180000;4.040444;-0.831000;, - 1.961750;3.663552;-0.683854;, - 1.961750;3.663552;-0.683854;, - 1.961750;4.011917;-0.683854;, - 1.961750;4.011917;-0.683854;, - 1.650000;4.319444;-1.291000;, - 1.650000;4.319444;-1.291000;, - 1.650000;4.319444;-0.991000;, - 1.650000;4.319444;-0.991000;, - 1.650000;4.011917;-0.683854;, - 1.650000;4.011917;-0.683854;, - 1.650000;3.663552;-0.683854;, - 1.650000;3.663552;-0.683854;, - 1.160500;4.319444;-1.291000;, - 1.160500;4.319444;-1.291000;, - 1.160500;4.319444;-1.291000;, - 1.160500;4.319444;-1.291000;, - 1.160500;4.319444;-0.991000;, - 1.160500;4.319444;-0.991000;, - 1.120000;4.040444;-0.831000;, - 1.120000;4.040444;-0.831000;, - 1.120000;4.040444;-0.831000;, - 1.338250;3.663552;-0.683854;, - 1.338250;3.663552;-0.683854;, - 1.338250;4.011917;-0.683854;, - 1.338250;4.011917;-0.683854;, - 0.670000;4.040444;-0.831000;, - 0.670000;4.040444;-0.831000;, - 0.670000;4.040444;-0.831000;, - 2.211500;4.896544;-1.134769;, - 2.211500;4.896544;-1.134769;, - 2.211500;4.896544;-1.134769;, - 2.183926;5.309234;-0.707269;, - 2.183926;5.309234;-0.707269;, - 2.070200;4.409444;-1.192000;, - 2.070200;4.409444;-1.192000;, - 2.070200;4.409444;-0.991000;, - 2.070200;4.409444;-0.991000;, - 2.070200;4.409444;-0.690000;, - 2.070200;4.409444;-0.690000;, - 1.650000;4.898689;-1.134137;, - 1.650000;4.898689;-1.134137;, - 1.108550;5.309234;-0.707269;, - 1.108550;5.309234;-0.707269;, - 1.713800;4.409444;-1.192000;, - 1.713800;4.409444;-0.991000;, - 1.713800;4.409444;-0.690000;, - 1.088500;4.896544;-1.134769;, - 1.088500;4.896544;-1.134769;, - 1.088500;4.896544;-1.134769;, - 1.229800;4.409444;-1.192000;, - 1.229800;4.409444;-1.192000;, - 1.229800;4.409444;-0.991000;, - 1.229800;4.409444;-0.991000;, - 1.229800;4.409444;-0.690000;, - 1.229800;4.409444;-0.690000;, - 0.567000;5.248089;-1.268261;, - 0.567000;5.248089;-1.268261;, - 0.567000;5.248089;-1.268261;, - 0.567000;5.248089;-1.268261;, - 0.864000;5.747889;-1.250000;, - 0.864000;5.747889;-1.250000;, - 0.864000;5.747889;-1.200000;, - 0.864000;5.747889;-1.200000;, - 0.864000;5.747889;-1.200000;, - 0.270000;5.747889;-1.200000;, - 0.270000;5.747889;-1.200000;, - 0.270000;5.747889;-1.200000;, - 0.270000;5.747889;-1.200000;, - 0.270000;4.472888;-1.200000;, - 2.211500;6.504799;-0.897269;, - 2.211500;6.504799;-0.897269;, - 2.211500;6.899809;-0.659769;, - 2.211500;6.899809;-0.659769;, - 2.211500;6.899809;-0.659769;, - 2.211500;6.270950;-1.294258;, - 2.211500;6.270950;-1.294258;, - 1.650000;6.899809;-0.659769;, - 1.650000;6.899809;-0.659769;, - 1.650000;6.504799;-0.897269;, - 1.650000;6.270950;-1.294258;, - 1.088500;6.504799;-0.897269;, - 1.088500;6.504799;-0.897269;, - 1.088500;6.899809;-0.659769;, - 1.088500;6.899809;-0.659769;, - 1.088500;6.899809;-0.659769;, - 1.088500;6.270950;-1.294258;, - 1.088500;6.270950;-1.294258;, - 0.434700;6.553689;-1.234434;, - 0.434700;6.553689;-1.234434;, - 0.434700;6.553689;-1.234434;, - 0.434700;7.226889;-0.950000;, - 0.434700;7.226889;-0.950000;, - 0.567000;6.604689;-1.268261;, - 0.567000;6.604689;-1.268261;, - 0.567000;6.604689;-1.268261;, - 0.567000;6.533288;-1.268261;, - 0.567000;6.533288;-1.268261;, - 0.567000;6.533288;-1.268261;, - 0.864000;6.512889;-1.250000;, - 0.864000;6.512889;-1.250000;, - 0.864000;6.512889;-1.200000;, - 0.864000;6.512889;-1.200000;, - 0.864000;6.512889;-1.200000;, - 0.270000;6.512889;-1.200000;, - 0.270000;6.512889;-1.200000;, - 0.270000;6.512889;-1.200000;, - 0.645840;8.299889;-1.100000;, - 0.621000;8.494646;-1.080509;, - 0.621000;8.494646;-1.080509;, - 0.434700;8.323646;-1.004743;, - 0.434700;8.323646;-1.004743;, - 0.434700;8.322903;-1.172274;, - 0.434700;8.322903;-1.172274;, - 0.434700;7.901668;-1.294773;, - 0.434700;7.901668;-1.294773;, - 0.434700;7.901668;-1.294773;, - 0.348300;7.829880;-1.234773;, - 0.348300;7.829880;-1.234773;, - 0.348300;8.346831;-1.092274;, - 0.348300;8.346831;-1.092274;, - 0.434700;9.853403;-0.652941;, - 0.434700;9.853403;-0.652941;, - 0.621000;9.772565;-0.734962;, - 0.621000;9.772565;-0.734962;, - 0.621000;9.772565;-0.734962;, - 0.434700;10.156014;-0.776952;, - 0.434700;10.156014;-0.776952;, - 0.621000;10.117581;-0.864687;, - 0.621000;10.117581;-0.864687;, - 0.621000;10.154878;-0.975241;, - 0.621000;10.154878;-0.975241;, - 0.434700;10.240253;-0.992427;, - 0.280461;11.060905;-0.923241;, - 0.280461;11.060905;-0.923241;, - 0.233382;11.060905;-1.068951;, - 0.233382;11.060905;-1.068951;, - 0.233382;11.060905;-1.068951;, - 0.233382;11.060905;-1.068951;, - 0.233382;11.029785;-1.068951;, - 0.233382;11.029785;-1.068951;, - 0.233382;11.029785;-1.068951;, - 0.233382;11.029785;-1.068951;, - 0.280461;11.029785;-0.923241;, - 0.280461;11.029785;-0.923241;, - 0.124377;11.282440;-1.066862;, - 0.124377;11.282440;-1.066862;, - 0.203526;11.356547;-0.927240;, - 0.226140;11.261694;-1.066862;, - 0.226140;11.261694;-1.066862;, - 0.226140;11.261694;-1.066862;, - 0.282675;11.325428;-0.927240;, - 0.282675;11.325428;-0.927240;, - 0.192219;10.749704;-0.927240;, - 0.124377;10.863811;-1.066862;, - 0.124377;10.863811;-1.066862;, - 0.282675;10.780824;-0.927240;, - 0.282675;10.780824;-0.927240;, - 0.226140;10.884558;-1.066862;, - 0.226140;10.884558;-1.066862;, - 0.226140;10.884558;-1.066862;, - 0.113559;11.059278;-1.023456;, - 0.113559;11.059278;-1.023456;, - 0.078358;11.232752;-1.023456;, - 0.113643;11.032139;-1.023456;, - 0.113643;11.032139;-1.023456;, - 0.158298;11.060905;-1.067771;, - 0.158298;11.060905;-1.067771;, - 0.158298;11.060905;-1.067771;, - 0.158298;11.029785;-1.067771;, - 0.158298;11.029785;-1.067771;, - 0.158298;11.029785;-1.067771;, - 0.078358;10.913136;-1.023456;, - 2.090000;0.552590;-0.191000;, - 2.090000;0.552590;-0.191000;, - 2.090000;0.777590;-0.191000;, - 2.090000;0.777590;-0.191000;, - 2.090000;0.777590;-0.191000;, - 2.090000;0.012590;-0.491000;, - 2.090000;0.012590;-0.491000;, - 2.090000;0.012590;-0.491000;, - 1.946000;0.012590;-0.491000;, - 1.946000;0.012590;-0.491000;, - 1.946000;0.552590;-0.191000;, - 1.946000;0.777590;-0.191000;, - 1.946000;0.777590;-0.191000;, - 1.650000;0.012590;-0.491000;, - 1.650000;0.012590;-0.491000;, - 1.650000;0.552590;-0.191000;, - 1.650000;0.777590;-0.191000;, - 1.650000;0.777590;-0.191000;, - 1.210000;0.552590;-0.191000;, - 1.210000;0.552590;-0.191000;, - 1.210000;0.777590;-0.191000;, - 1.210000;0.777590;-0.191000;, - 1.210000;0.777590;-0.191000;, - 1.210000;0.012590;-0.491000;, - 1.210000;0.012590;-0.491000;, - 1.210000;0.012590;-0.491000;, - 1.354000;0.012590;-0.491000;, - 1.354000;0.012590;-0.491000;, - 1.354000;0.777590;-0.191000;, - 1.354000;0.777590;-0.191000;, - 2.720000;2.735444;0.089000;, - 2.139500;2.519444;-0.591000;, - 2.139500;2.519444;-0.591000;, - 2.139500;2.519444;-0.591000;, - 2.180000;2.150444;0.089000;, - 2.180000;2.150444;0.089000;, - 2.180000;2.150444;0.089000;, - 2.630000;2.150444;0.089000;, - 2.630000;2.150444;0.089000;, - 2.630000;2.150444;0.089000;, - 2.180000;2.735444;0.089000;, - 2.180000;2.465444;-0.591000;, - 2.180000;2.465444;-0.591000;, - 1.650000;2.519444;-0.591000;, - 1.650000;2.519444;-0.591000;, - 1.650000;2.465444;-0.591000;, - 1.160500;2.519444;-0.591000;, - 1.160500;2.519444;-0.591000;, - 1.160500;2.519444;-0.591000;, - 1.120000;2.150444;0.089000;, - 1.120000;2.150444;0.089000;, - 1.120000;2.150444;0.089000;, - 1.120000;2.465444;-0.591000;, - 1.120000;2.465444;-0.591000;, - 0.670000;2.150444;0.089000;, - 0.670000;2.150444;0.089000;, - 0.670000;2.150444;0.089000;, - 2.720000;4.040444;0.089000;, - 2.720000;4.040444;0.089000;, - 2.191610;0.736228;-0.303535;, - 2.191610;0.736228;-0.303535;, - 2.191610;0.736228;-0.303535;, - 2.191610;0.540345;-0.393688;, - 2.191610;0.540345;-0.393688;, - 2.191610;0.344462;-0.303535;, - 2.191610;0.344462;-0.303535;, - 2.191610;0.344462;-0.303535;, - 2.191610;0.263325;-0.085888;, - 2.191610;0.263325;-0.085888;, - 2.238357;0.540345;-0.085888;, - 2.041625;4.121234;-0.469769;, - 2.041625;4.121234;-0.469769;, - 2.041625;4.121234;-0.469769;, - 2.139500;4.319444;-0.591000;, - 2.139500;4.319444;-0.591000;, - 2.139500;4.319444;-0.591000;, - 2.139500;4.319444;-0.591000;, - 2.180000;4.040444;0.089000;, - 2.180000;4.040444;0.089000;, - 2.180000;3.545444;-0.591000;, - 2.180000;3.545444;-0.591000;, - 2.180000;3.545444;-0.591000;, - 1.961750;4.067234;0.059254;, - 1.961750;4.067234;0.059254;, - 1.961750;4.067234;0.059254;, - 1.961750;4.067234;-0.583346;, - 1.961750;4.067234;-0.583346;, - 1.961750;4.067234;-0.583346;, - 1.961750;3.608234;0.059254;, - 1.961750;3.608234;0.059254;, - 1.961750;3.608234;0.059254;, - 1.961750;3.034714;0.059254;, - 1.961750;3.034714;0.059254;, - 1.961750;3.608234;-0.583346;, - 1.961750;3.608234;-0.583346;, - 1.961750;3.608234;-0.583346;, - 1.961750;3.202694;-0.395133;, - 1.961750;3.202694;-0.395133;, - 1.961750;3.202694;-0.395133;, - 2.096750;3.654134;-0.583346;, - 2.096750;3.654134;-0.583346;, - 2.096750;3.654134;-0.583346;, - 2.096750;3.654134;0.059254;, - 2.096750;3.654134;0.059254;, - 2.096750;3.654134;0.059254;, - 2.096750;4.021334;0.059254;, - 2.096750;4.021334;0.059254;, - 2.096750;4.021334;0.059254;, - 2.096750;4.021334;-0.583346;, - 2.096750;4.021334;-0.583346;, - 2.096750;4.021334;-0.583346;, - 1.646500;0.736228;-0.303535;, - 1.646500;0.736228;-0.303535;, - 1.646500;0.540345;-0.393688;, - 1.646500;0.344462;-0.303535;, - 1.646500;0.344462;-0.303535;, - 1.646500;0.263325;-0.085888;, - 1.208000;4.121234;-0.469769;, - 1.208000;4.121234;-0.469769;, - 1.208000;4.121234;-0.469769;, - 1.650000;4.319444;-0.591000;, - 1.650000;4.319444;-0.591000;, - 1.650000;3.545444;-0.591000;, - 1.650000;3.545444;-0.591000;, - 1.650000;4.067234;-0.583346;, - 1.650000;4.067234;-0.583346;, - 1.650000;3.202694;-0.395133;, - 1.650000;3.202694;-0.395133;, - 1.650000;3.034714;0.059254;, - 1.650000;3.608234;-0.583346;, - 1.650000;3.608234;-0.583346;, - 1.101390;0.736228;-0.303535;, - 1.101390;0.736228;-0.303535;, - 1.101390;0.736228;-0.303535;, - 1.101390;0.540345;-0.393688;, - 1.101390;0.540345;-0.393688;, - 1.101390;0.344462;-0.303535;, - 1.101390;0.344462;-0.303535;, - 1.101390;0.344462;-0.303535;, - 1.101390;0.263325;-0.085888;, - 1.101390;0.263325;-0.085888;, - 1.160500;4.319444;-0.591000;, - 1.160500;4.319444;-0.591000;, - 1.160500;4.319444;-0.591000;, - 1.160500;4.319444;-0.591000;, - 1.120000;4.040444;0.089000;, - 1.120000;4.040444;0.089000;, - 1.120000;3.545444;-0.591000;, - 1.120000;3.545444;-0.591000;, - 1.120000;3.545444;-0.591000;, - 1.338250;4.067234;0.059254;, - 1.338250;4.067234;0.059254;, - 1.338250;4.067234;0.059254;, - 1.338250;4.067234;-0.583346;, - 1.338250;4.067234;-0.583346;, - 1.338250;4.067234;-0.583346;, - 1.338250;3.608234;0.059254;, - 1.338250;3.608234;0.059254;, - 1.338250;3.608234;0.059254;, - 1.338250;3.034714;0.059254;, - 1.338250;3.034714;0.059254;, - 1.338250;3.608234;-0.583346;, - 1.338250;3.608234;-0.583346;, - 1.338250;3.608234;-0.583346;, - 1.338250;3.202694;-0.395133;, - 1.338250;3.202694;-0.395133;, - 1.338250;3.202694;-0.395133;, - 1.203250;3.654134;-0.583346;, - 1.203250;3.654134;-0.583346;, - 1.203250;3.654134;-0.583346;, - 1.203250;3.654134;0.059254;, - 1.203250;3.654134;0.059254;, - 1.203250;3.654134;0.059254;, - 1.203250;4.021334;0.059254;, - 1.203250;4.021334;0.059254;, - 1.203250;4.021334;0.059254;, - 1.203250;4.021334;-0.583346;, - 1.203250;4.021334;-0.583346;, - 1.203250;4.021334;-0.583346;, - 0.580000;4.040444;0.089000;, - 0.580000;4.040444;0.089000;, - 2.191610;0.817365;-0.085888;, - 2.191610;0.817365;-0.085888;, - 1.961750;4.640755;0.059254;, - 1.961750;4.640755;0.059254;, - 1.961750;4.472775;-0.395133;, - 1.961750;4.472775;-0.395133;, - 1.961750;4.472775;-0.395133;, - 1.646500;0.817365;-0.085888;, - 1.650000;4.640755;0.059254;, - 1.650000;4.472775;-0.395133;, - 1.650000;4.472775;-0.395133;, - 1.101390;0.817365;-0.085888;, - 1.101390;0.817365;-0.085888;, - 1.338250;4.640755;0.059254;, - 1.338250;4.640755;0.059254;, - 1.338250;4.472775;-0.395133;, - 1.338250;4.472775;-0.395133;, - 1.338250;4.472775;-0.395133;, - 5.537655;7.308371;-0.122373;, - 5.537655;7.308371;-0.122373;, - 5.537655;7.308371;-0.122373;, - 5.737680;7.308371;-0.123683;, - 5.737680;7.308371;-0.123683;, - 5.737680;7.308371;-0.123683;, - 2.211500;6.391939;-0.509769;, - 0.869400;6.553689;-0.193089;, - 0.869400;6.553689;-0.193089;, - 0.729000;7.226889;-0.250000;, - 1.157854;8.456665;-0.357500;, - 1.304100;8.392207;-0.380000;, - 1.304100;8.392207;-0.380000;, - 1.614600;8.428101;-0.460000;, - 1.614600;8.428101;-0.460000;, - 1.614600;8.428101;-0.460000;, - 1.304100;8.332384;-0.460000;, - 1.614600;8.487924;-0.380000;, - 1.614600;8.487924;-0.380000;, - 1.614600;8.487924;-0.380000;, - 1.291183;8.380595;0.035000;, - 1.291183;8.380595;0.035000;, - 1.291183;8.380595;0.035000;, - 1.206975;7.730014;-0.148713;, - 1.206975;7.730014;-0.148713;, - 1.206975;8.252790;-0.393860;, - 1.291183;8.380595;-0.380000;, - 1.291183;8.380595;-0.380000;, - 1.291183;7.708855;-0.065000;, - 1.291183;7.708855;-0.065000;, - 1.291183;7.708855;-0.065000;, - 1.291183;7.708855;-0.065000;, - 0.645840;8.299889;-0.380000;, - 0.645840;8.299889;-0.380000;, - 0.729000;8.335782;-0.250000;, - 0.621000;8.491881;-0.506934;, - 0.621000;8.491881;-0.506934;, - 0.621000;8.491881;-0.506934;, - 0.434700;8.325909;-0.320215;, - 0.434700;8.325909;-0.320215;, - 0.434700;8.325909;-0.320215;, - 0.434700;8.325909;-0.320215;, - 0.621000;8.392207;-0.380000;, - 0.621000;8.392207;-0.380000;, - 0.621000;8.392207;-0.380000;, - 0.621000;8.332384;-0.460000;, - 0.621000;8.332384;-0.460000;, - 0.701730;8.380595;0.035000;, - 0.701730;8.380595;0.035000;, - 0.701730;8.380595;0.035000;, - 0.701730;7.708855;-0.065000;, - 0.701730;7.708855;-0.065000;, - 0.701730;7.708855;-0.065000;, - 0.701730;7.708855;-0.065000;, - 0.701730;8.380595;-0.380000;, - 0.701730;8.380595;-0.380000;, - 0.785938;8.252790;-0.393860;, - 0.785938;7.730014;-0.148713;, - 0.785938;7.730014;-0.148713;, - 6.193715;8.999975;-0.085702;, - 6.193715;8.999975;-0.085702;, - 6.193715;8.999975;-0.085702;, - 6.273846;9.094374;-0.151701;, - 6.273846;9.094374;-0.151701;, - 6.273846;9.094374;-0.151701;, - 6.273846;9.094374;-0.151701;, - 6.273846;9.849567;-0.151701;, - 6.273846;9.849567;-0.151701;, - 6.273846;9.849567;-0.151701;, - 6.273846;9.849567;-0.151701;, - 6.193715;9.943968;-0.085702;, - 6.193715;9.943968;-0.085702;, - 6.193715;9.943968;-0.085702;, - 7.060897;9.725492;-0.129548;, - 7.060897;9.725492;-0.129548;, - 7.060897;9.725492;-0.129548;, - 6.982975;9.563503;-0.129548;, - 6.982975;9.563503;-0.129548;, - 6.671293;9.725492;-0.129548;, - 6.671293;9.725492;-0.129548;, - 6.671293;9.340767;-0.129548;, - 6.671293;9.340767;-0.129548;, - 6.858303;9.340767;-0.129548;, - 6.858303;9.340767;-0.129548;, - 6.858303;9.340767;-0.129548;, - 6.671293;9.563503;-0.129548;, - 6.751895;9.313591;0.542340;, - 6.751895;9.313591;0.542340;, - 6.751895;9.313591;0.542340;, - 6.912178;9.319603;0.515226;, - 6.912178;9.319603;0.515226;, - 6.912178;9.319603;0.515226;, - 6.937339;9.170279;0.515226;, - 6.937339;9.170279;0.515226;, - 6.937339;9.170279;0.515226;, - 6.916745;9.323501;0.515226;, - 6.916745;9.323501;0.515226;, - 6.916745;9.323501;0.515226;, - 7.001220;9.409288;0.515226;, - 7.001220;9.409288;0.515226;, - 7.001220;9.409288;0.515226;, - 7.095283;9.321381;0.515226;, - 7.095283;9.321381;0.515226;, - 7.095283;9.321381;0.515226;, - 6.943227;9.166967;0.515226;, - 6.943227;9.166967;0.515226;, - 6.943227;9.166967;0.515226;, - 6.993157;9.433917;0.515226;, - 6.993157;9.433917;0.515226;, - 6.993157;9.433917;0.515226;, - 7.002631;9.569713;0.515226;, - 7.002631;9.569713;0.515226;, - 7.119660;9.611607;0.515226;, - 7.119660;9.611607;0.515226;, - 7.119660;9.611607;0.515226;, - 7.100082;9.330963;0.515226;, - 7.100082;9.330963;0.515226;, - 7.100082;9.330963;0.515226;, - 5.816796;9.094374;-0.151701;, - 5.816796;9.094374;-0.151701;, - 5.781181;8.999975;-0.085701;, - 5.781181;8.999975;-0.085701;, - 5.816796;9.849567;-0.151701;, - 5.816796;9.849567;-0.151701;, - 5.781182;9.943968;-0.085701;, - 5.781182;9.943968;-0.085701;, - 5.499784;9.980371;0.045354;, - 5.499784;9.980371;0.045354;, - 5.499784;9.980371;0.045354;, - 5.499784;9.836371;0.045354;, - 5.499784;9.836371;0.045354;, - 5.499784;9.836371;0.045354;, - 5.529781;9.428371;-0.592264;, - 5.529781;9.428371;-0.592264;, - 5.729806;9.428371;-0.593574;, - 5.729806;9.428371;-0.593574;, - 5.537655;8.948371;-0.122373;, - 5.537655;8.948371;-0.122373;, - 5.737680;8.948371;-0.123683;, - 5.737680;8.948371;-0.123683;, - 5.537608;9.428371;-0.125206;, - 5.737632;9.428371;-0.126516;, - 4.021242;9.094375;0.068299;, - 4.021242;9.094375;0.068299;, - 4.021242;9.094375;0.068299;, - 4.021242;9.094375;0.068299;, - 4.326931;8.999975;-0.085701;, - 4.326931;8.999975;-0.085701;, - 4.273510;9.094375;-0.151701;, - 4.273510;9.094375;-0.151701;, - 4.439710;8.999975;-0.085701;, - 4.439710;8.999975;-0.085701;, - 5.000635;8.999975;-0.085701;, - 5.000635;9.094375;-0.151701;, - 5.000635;9.094375;-0.151701;, - 4.439710;9.094375;-0.151701;, - 4.439710;9.094375;-0.151701;, - 4.021242;9.849568;0.068299;, - 4.021242;9.849568;0.068299;, - 4.021242;9.849568;0.068299;, - 4.021242;9.849568;0.068299;, - 4.273510;9.849568;-0.151701;, - 4.273510;9.849568;-0.151701;, - 4.326931;9.943968;-0.085701;, - 4.326931;9.943968;-0.085701;, - 4.439710;9.943968;-0.085701;, - 4.439710;9.943968;-0.085701;, - 4.439710;9.849568;-0.151701;, - 4.439710;9.849568;-0.151701;, - 5.000635;9.849568;-0.151701;, - 5.000635;9.849568;-0.151701;, - 5.000635;9.943968;-0.085701;, - 4.569112;9.980371;0.038033;, - 4.569112;9.980371;0.038033;, - 4.569112;9.836371;0.038033;, - 4.569112;9.836371;0.038033;, - 4.529347;9.836371;0.038294;, - 4.529347;9.836371;0.038294;, - 4.529347;9.836371;0.038294;, - 4.529347;9.980371;0.038294;, - 4.529347;9.980371;0.038294;, - 4.529347;9.980371;0.038294;, - 3.739634;9.114357;0.049999;, - 3.739634;9.114357;0.049999;, - 3.739634;9.114357;0.049999;, - 3.739634;9.465427;0.049999;, - 3.739634;9.465427;0.049999;, - 3.739634;9.816500;0.049999;, - 3.739634;9.816500;0.049999;, - 3.739634;9.816500;0.049999;, - 6.197741;9.416677;0.121999;, - 6.197741;9.416677;0.121999;, - 6.197741;9.625625;0.121999;, - 6.197741;9.625625;0.121999;, - 6.454175;9.625625;0.121999;, - 6.454175;9.625625;0.121999;, - 6.454175;9.416677;0.121999;, - 6.454175;9.416677;0.121999;, - 3.477382;10.049524;-0.300001;, - 3.477382;10.049524;-0.300001;, - 3.477382;10.049524;0.049999;, - 3.477382;10.049524;0.049999;, - 3.477382;10.049524;0.049999;, - 3.477382;9.541996;-0.300001;, - 3.477382;9.541996;-0.300001;, - 3.477382;9.541996;0.049999;, - 3.477382;9.541996;0.049999;, - 3.308206;9.330525;-0.300001;, - 3.308206;9.330525;-0.300001;, - 3.308206;9.330525;-0.300001;, - 3.308206;9.330525;-0.300001;, - 3.308206;9.330525;0.049999;, - 3.308206;9.330525;0.049999;, - 3.308206;9.330525;0.049999;, - 3.370776;9.681329;-0.450001;, - 3.370776;9.681329;-0.450001;, - 3.308206;9.541996;0.049999;, - 3.370776;10.087790;-0.450001;, - 3.370776;10.087790;-0.450001;, - 3.308206;10.049524;0.049999;, - 3.308206;10.049524;0.049999;, - 3.347260;9.836371;0.050102;, - 3.347260;9.836371;0.050102;, - 3.347260;9.836371;0.050102;, - 3.347260;9.980371;0.050102;, - 3.347260;9.980371;0.050102;, - 3.347260;9.980371;0.050102;, - 5.498027;9.908371;-0.030170;, - 5.610232;9.972371;0.049085;, - 5.610232;9.972371;0.049085;, - 5.610232;9.972371;0.049085;, - 5.499367;10.036371;0.049811;, - 5.499367;10.036371;0.049811;, - 5.499367;10.036371;0.049811;, - 5.610232;9.844371;0.049085;, - 5.610232;9.844371;0.049085;, - 5.610232;9.844371;0.049085;, - 5.499367;9.780371;0.049811;, - 5.499367;9.780371;0.049811;, - 5.499367;9.780371;0.049811;, - 5.388502;9.844371;0.050537;, - 5.388502;9.844371;0.050537;, - 5.388502;9.844371;0.050537;, - 5.388502;9.972371;0.050537;, - 5.388502;9.972371;0.050537;, - 5.388502;9.972371;0.050537;, - 2.351901;9.114357;0.050000;, - 2.351901;9.114357;0.050000;, - 2.351901;9.114357;0.050000;, - 2.351901;9.465427;0.050000;, - 2.351901;9.465427;0.050000;, - 2.351901;9.816500;0.050000;, - 2.351901;9.816500;0.050000;, - 2.351901;9.816500;0.050000;, - 2.610355;9.541996;0.050000;, - 2.610355;9.541996;0.050000;, - 2.610355;9.541996;-0.300000;, - 2.610355;9.541996;-0.300000;, - 2.610355;9.541996;-0.300000;, - 2.737237;9.330525;-0.300000;, - 2.737237;9.330525;-0.300000;, - 2.737237;9.330525;-0.300000;, - 2.737237;9.330525;0.050000;, - 2.737237;9.330525;0.050000;, - 2.737237;9.330525;0.050000;, - 2.605451;10.087790;-0.450000;, - 2.673121;9.681329;-0.450000;, - 2.673121;9.681329;-0.450000;, - 2.610355;10.049524;0.050000;, - 2.610355;10.049524;0.050000;, - 3.221444;9.664412;-0.450001;, - 3.263738;9.504920;-0.450001;, - 3.263738;9.504920;-0.450001;, - 2.810496;9.504920;-0.450000;, - 3.221444;10.087790;-0.450001;, - 1.785622;9.541996;-0.300000;, - 1.785622;9.541996;-0.300000;, - 1.785622;9.541996;-0.300000;, - 1.785622;9.541996;0.050000;, - 1.785622;9.541996;0.050000;, - 1.574152;9.711170;-0.300000;, - 1.574152;9.711170;-0.300000;, - 1.574152;9.711170;-0.300000;, - 1.574152;9.711170;-0.300000;, - 1.574152;9.711170;0.050000;, - 1.574152;9.711170;0.050000;, - 1.574152;9.711170;0.050000;, - 1.943341;10.228918;-0.450000;, - 1.877459;9.681329;-0.450000;, - 1.877459;9.681329;-0.450000;, - 1.574152;10.218699;0.050000;, - 1.574152;10.218699;0.050000;, - 1.574152;10.218699;0.050000;, - 1.574152;10.218699;-0.300000;, - 1.574152;10.218699;-0.300000;, - 1.690794;10.228918;-0.450000;, - 1.690794;10.228918;-0.450000;, - 1.690794;9.822455;-0.450000;, - 1.690794;9.822455;-0.450000;, - 1.785622;10.218699;0.050000;, - 1.785622;10.218699;0.050000;, - 1.291183;9.629884;0.035000;, - 1.291183;9.629884;0.035000;, - 1.291183;9.629884;0.035000;, - 1.291183;9.629884;-0.380000;, - 1.291183;9.629884;-0.380000;, - 1.291183;9.629884;-0.380000;, - 1.291183;10.090521;0.035000;, - 1.291183;10.090521;0.035000;, - 1.291183;10.090521;0.035000;, - 1.206975;10.200697;-0.393860;, - 1.291183;10.090521;-0.380000;, - 1.291183;10.090521;-0.380000;, - 1.157854;9.729999;-0.357500;, - 1.304100;10.010826;-0.380000;, - 1.304100;10.010826;-0.380000;, - 1.614600;9.891180;-0.460000;, - 1.614600;9.891180;-0.460000;, - 1.614600;9.891180;-0.460000;, - 1.304100;10.010826;-0.460000;, - 1.614600;9.891180;-0.380000;, - 1.614600;9.891180;-0.380000;, - 1.614600;9.891180;-0.380000;, - 1.291183;8.914934;-0.380000;, - 1.291183;8.914934;-0.380000;, - 1.291183;8.914934;-0.380000;, - 1.291183;8.914934;0.035000;, - 1.291183;8.914934;0.035000;, - 1.291183;8.914934;0.035000;, - 0.701730;10.090521;0.035000;, - 0.701730;10.090521;0.035000;, - 0.701730;10.090521;0.035000;, - 0.701730;10.090521;-0.380000;, - 0.701730;10.090521;-0.380000;, - 0.701730;9.629884;-0.380000;, - 0.701730;9.629884;-0.380000;, - 0.701730;9.629884;-0.380000;, - 0.701730;9.629884;0.035000;, - 0.701730;9.629884;0.035000;, - 0.701730;9.629884;0.035000;, - 0.785938;10.200697;-0.393860;, - 0.324000;10.031889;0.150000;, - 0.621000;10.010826;-0.380000;, - 0.621000;10.010826;-0.380000;, - 0.621000;10.010826;-0.380000;, - 0.621000;10.010826;-0.460000;, - 0.621000;10.010826;-0.460000;, - 0.783621;10.114978;-0.154000;, - 0.701730;8.914934;-0.380000;, - 0.701730;8.914934;-0.380000;, - 0.701730;8.914934;-0.380000;, - 0.701730;8.914934;0.035000;, - 0.701730;8.914934;0.035000;, - 0.701730;8.914934;0.035000;, - 5.529781;11.108371;-0.592264;, - 5.529781;11.108371;-0.592264;, - 5.529781;11.108371;-0.592264;, - 5.729806;11.108371;-0.593574;, - 5.729806;11.108371;-0.593574;, - 5.729806;11.108371;-0.593574;, - 5.737632;11.108371;-0.126516;, - 5.737632;11.108371;-0.126516;, - 5.537608;11.108371;-0.125206;, - 5.537608;11.108371;-0.125206;, - 5.537608;10.788371;-0.125206;, - 5.537608;10.788371;-0.125206;, - 5.537608;10.788371;-0.125206;, - 5.737632;10.788371;-0.126516;, - 5.737632;10.788371;-0.126516;, - 5.737632;10.788371;-0.126516;, - 5.729806;10.788371;-0.593574;, - 5.729806;10.788371;-0.593574;, - 5.529781;10.788371;-0.592264;, - 5.529781;10.788371;-0.592264;, - 5.529781;10.948371;-0.592264;, - 5.529781;10.948371;-0.592264;, - 5.537608;10.948371;-0.125206;, - 5.537608;10.948371;-0.125206;, - 5.537608;10.948371;-0.125206;, - 5.737632;10.948371;-0.126516;, - 5.737632;10.948371;-0.126516;, - 5.737632;10.948371;-0.126516;, - 5.729806;10.948371;-0.593574;, - 5.729806;10.948371;-0.593574;, - 3.477382;10.768522;0.049999;, - 3.477382;10.768522;0.049999;, - 3.477382;10.768522;-0.300001;, - 3.477382;10.768522;-0.300001;, - 3.477382;10.768522;-0.300001;, - 3.477382;10.768522;-0.300001;, - 3.308206;10.895405;0.049999;, - 3.308206;10.895405;-0.300001;, - 3.308206;10.895405;-0.300001;, - 3.308206;10.895405;-0.300001;, - 3.370776;10.653745;-0.450001;, - 3.370776;10.653745;-0.450001;, - 2.610355;10.895405;-0.300000;, - 2.610355;10.895405;-0.300000;, - 2.610355;10.895405;0.050000;, - 2.605451;10.759588;-0.450000;, - 2.605451;10.759588;-0.450000;, - 3.221444;10.759588;-0.450001;, - 3.221444;10.759588;-0.450001;, - 1.954798;10.895405;-0.300000;, - 1.954798;10.895405;-0.300000;, - 1.954798;10.895405;-0.300000;, - 1.954798;10.895405;-0.300000;, - 1.954798;10.895405;0.050000;, - 1.954798;10.895405;0.050000;, - 1.574152;10.514757;0.050000;, - 1.574152;10.514757;-0.300000;, - 1.574152;10.514757;-0.300000;, - 1.574152;10.514757;-0.300000;, - 2.026791;10.759588;-0.450000;, - 2.026791;10.759588;-0.450000;, - 1.690794;10.442054;-0.450000;, - 1.690794;10.442054;-0.450000;, - 1.206975;10.651367;-0.148713;, - 1.206975;10.651367;-0.148713;, - 1.291183;10.669608;-0.065000;, - 1.291183;10.669608;-0.065000;, - 1.291183;10.669608;-0.065000;, - 1.291183;10.669608;-0.065000;, - 0.701730;10.669608;-0.065000;, - 0.701730;10.669608;-0.065000;, - 0.701730;10.669608;-0.065000;, - 0.701730;10.669608;-0.065000;, - 0.785938;10.651367;-0.148713;, - 0.785938;10.651367;-0.148713;, - 0.384438;10.303647;-0.092313;, - 0.384438;10.303647;-0.092313;, - 0.384438;10.303647;-0.092313;, - 0.384438;10.687464;-0.005502;, - 0.384438;10.687464;-0.005502;, - 0.384438;10.687464;-0.005502;, - 0.306190;10.687464;-0.005502;, - 0.306190;10.687464;-0.005502;, - 0.306190;10.303647;-0.092313;, - 0.306190;10.303647;-0.092313;, - 0.290080;11.185386;-0.116549;, - 0.290080;11.185386;-0.116549;, - 0.290080;11.154265;-0.116549;, - 0.290080;11.154265;-0.116549;, - 0.280074;11.060905;-0.350670;, - 0.280074;11.060905;-0.350670;, - 0.280074;11.029785;-0.350670;, - 0.280074;11.029785;-0.350670;, - 0.203526;11.460281;-0.116549;, - 0.282675;11.429161;-0.116549;, - 0.282675;11.429161;-0.116549;, - 0.282675;11.408415;-0.398685;, - 0.282675;11.408415;-0.398685;, - 0.203526;11.439535;-0.398685;, - 0.282675;10.760077;-0.398685;, - 0.282675;10.760077;-0.398685;, - 0.192219;10.728957;-0.398685;, - 0.192219;10.728957;-0.116549;, - 0.282675;10.760077;-0.116549;, - 0.282675;10.760077;-0.116549;, - 0.296411;10.604476;0.095053;, - 0.296411;10.604476;0.095053;, - 0.791490;10.604476;0.095053;, - 0.791490;10.604476;0.095053;, - 0.791490;10.604476;0.095053;, - 0.791490;10.604476;0.095053;, - 0.296411;10.977919;0.095053;, - 0.296411;10.977919;0.095053;, - 0.791490;10.977919;0.095053;, - 0.791490;10.977919;0.095053;, - 0.791490;10.977919;0.095053;, - 0.791490;10.977919;0.095053;, - 0.319025;10.666717;0.040796;, - 0.723648;10.666717;0.040796;, - 0.723648;10.915678;0.040796;, - 0.319025;10.915678;0.040796;, - 0.191908;10.391821;-0.356500;, - 0.191908;10.391821;-0.356500;, - 0.191908;10.827504;-0.458200;, - 0.191908;10.827504;-0.458200;, - 0.191908;10.827504;-0.458200;, - 0.191908;10.827504;-0.458200;, - 0.118468;10.732613;-0.538774;, - 0.118468;10.732613;-0.538774;, - 0.118468;10.732613;-0.538774;, - 0.118468;10.440549;-0.470599;, - 0.118468;10.440549;-0.470599;, - 0.118468;10.440549;-0.470599;, - 2.087155;0.022285;0.449062;, - 2.087155;0.022285;0.449062;, - 2.062198;0.686398;0.209303;, - 2.062198;0.686398;0.209303;, - 2.062198;0.686398;0.209303;, - 2.087155;0.022285;0.837000;, - 2.087155;0.022285;0.837000;, - 2.045719;1.096842;0.837000;, - 2.045719;1.096842;0.837000;, - 2.045719;1.096842;0.837000;, - 2.045719;1.096842;0.837000;, - 2.064598;0.607264;0.837000;, - 2.405000;0.645445;0.209000;, - 2.405000;0.645445;0.209000;, - 1.650000;0.686398;0.209303;, - 1.650000;0.686398;0.209303;, - 1.650000;0.022285;0.449062;, - 1.650000;0.022285;0.837000;, - 1.650000;1.096842;0.837000;, - 1.650000;0.645445;0.209000;, - 1.212845;0.022285;0.449062;, - 1.212845;0.022285;0.449062;, - 1.237802;0.686398;0.209303;, - 1.237802;0.686398;0.209303;, - 1.237802;0.686398;0.209303;, - 1.212845;0.022285;0.837000;, - 1.212845;0.022285;0.837000;, - 1.254281;1.096842;0.837000;, - 1.254281;1.096842;0.837000;, - 1.254281;1.096842;0.837000;, - 1.254281;1.096842;0.837000;, - 0.895000;0.645445;0.209000;, - 0.895000;0.645445;0.209000;, - 2.180000;2.285444;0.209000;, - 2.191610;0.736228;0.131760;, - 2.191610;0.736228;0.131760;, - 2.191610;0.736228;0.131760;, - 2.191610;0.540345;0.221912;, - 2.191610;0.540345;0.221912;, - 2.191610;0.344462;0.131760;, - 2.191610;0.344462;0.131760;, - 2.191610;0.344462;0.131760;, - 2.041625;4.121234;0.527731;, - 2.041625;4.121234;0.527731;, - 2.041625;4.121234;0.527731;, - 2.180000;3.545444;0.209000;, - 2.180000;3.545444;0.209000;, - 1.961750;4.067234;0.701854;, - 1.961750;4.067234;0.701854;, - 1.961750;3.202694;0.513641;, - 1.961750;3.202694;0.513641;, - 1.961750;3.202694;0.513641;, - 1.961750;3.608234;0.701854;, - 1.961750;3.608234;0.701854;, - 1.961750;3.608234;0.701854;, - 1.646500;0.540345;0.221912;, - 1.646500;0.736228;0.131760;, - 1.646500;0.736228;0.131760;, - 1.646500;0.344462;0.131760;, - 1.646500;0.344462;0.131760;, - 1.208000;4.121234;0.527731;, - 1.208000;4.121234;0.527731;, - 1.208000;4.121234;0.527731;, - 1.650000;3.545444;0.209000;, - 1.650000;4.067234;0.701854;, - 1.650000;3.202694;0.513641;, - 1.650000;3.202694;0.513641;, - 1.650000;3.608234;0.701854;, - 1.650000;3.608234;0.701854;, - 1.101390;0.736228;0.131760;, - 1.101390;0.736228;0.131760;, - 1.101390;0.736228;0.131760;, - 1.101390;0.540345;0.221912;, - 1.101390;0.540345;0.221912;, - 1.101390;0.344462;0.131760;, - 1.101390;0.344462;0.131760;, - 1.101390;0.344462;0.131760;, - 1.120000;3.545444;0.209000;, - 1.120000;3.545444;0.209000;, - 1.338250;4.067234;0.701854;, - 1.338250;4.067234;0.701854;, - 1.338250;3.202694;0.513641;, - 1.338250;3.202694;0.513641;, - 1.338250;3.202694;0.513641;, - 1.338250;3.608234;0.701854;, - 1.338250;3.608234;0.701854;, - 1.338250;3.608234;0.701854;, - 2.211500;4.924759;0.527731;, - 2.211500;4.924759;0.527731;, - 1.961750;4.472775;0.513641;, - 1.961750;4.472775;0.513641;, - 1.961750;4.472775;0.513641;, - 1.650000;4.924759;0.527731;, - 1.650000;4.472775;0.513641;, - 1.650000;4.472775;0.513641;, - 1.088500;4.924759;0.527731;, - 1.088500;4.924759;0.527731;, - 1.338250;4.472775;0.513641;, - 1.338250;4.472775;0.513641;, - 1.338250;4.472775;0.513641;, - 1.291183;8.380595;0.600000;, - 1.291183;8.380595;0.600000;, - 1.291183;7.708855;0.600000;, - 1.291183;7.708855;0.600000;, - 0.701730;8.380595;0.600000;, - 0.701730;8.380595;0.600000;, - 0.701730;7.708855;0.600000;, - 0.701730;7.708855;0.600000;, - 6.273846;9.094374;0.662299;, - 6.273846;9.094374;0.662299;, - 6.273846;9.094374;0.662299;, - 6.273846;9.094374;0.662299;, - 6.193715;8.999975;0.662299;, - 6.193715;8.999975;0.662299;, - 6.193715;8.999975;0.662299;, - 6.193715;8.999975;0.607299;, - 6.193715;8.999975;0.607299;, - 6.193715;8.999975;0.607299;, - 6.273846;9.094374;0.607298;, - 6.273846;9.094374;0.607298;, - 6.273846;9.094374;0.607298;, - 6.273846;9.094374;0.607298;, - 6.273846;9.849567;0.662299;, - 6.273846;9.849567;0.662299;, - 6.273846;9.849567;0.662299;, - 6.273846;9.849567;0.662299;, - 6.193715;9.943968;0.662299;, - 6.193715;9.943968;0.662299;, - 6.193715;9.943968;0.662299;, - 6.193715;9.943968;0.607299;, - 6.193715;9.943968;0.607299;, - 6.193715;9.943968;0.607299;, - 6.273846;9.849567;0.607298;, - 6.273846;9.849567;0.607298;, - 6.273846;9.849567;0.607298;, - 6.273846;9.849567;0.607298;, - 6.982975;9.563503;0.726668;, - 6.982975;9.563503;0.726668;, - 7.060897;9.725492;0.726668;, - 7.060897;9.725492;0.726668;, - 7.060897;9.725492;0.726668;, - 6.359611;9.563503;0.568268;, - 6.359611;9.563503;0.568268;, - 6.359611;9.563503;0.002452;, - 6.359611;9.563503;0.002452;, - 6.359611;9.725492;0.002452;, - 6.359611;9.725492;0.002452;, - 6.359611;9.725492;0.002452;, - 6.359611;9.725492;0.568268;, - 6.359611;9.725492;0.568268;, - 6.359611;9.725492;0.568268;, - 6.671293;9.725492;0.726668;, - 6.671293;9.725492;0.726668;, - 6.671293;9.563503;0.726668;, - 6.359611;9.340767;0.002452;, - 6.359611;9.340767;0.002452;, - 6.359611;9.340767;0.002452;, - 6.359611;9.340767;0.568268;, - 6.359611;9.340767;0.568268;, - 6.359611;9.340767;0.568268;, - 6.671293;9.340767;0.726668;, - 6.671293;9.340767;0.726668;, - 6.858303;9.340767;0.726668;, - 6.858303;9.340767;0.726668;, - 6.858303;9.340767;0.726668;, - 6.751895;9.313591;0.677907;, - 6.751895;9.313591;0.677907;, - 6.751895;9.313591;0.677907;, - 6.912178;9.319603;0.705020;, - 6.912178;9.319603;0.705020;, - 6.912178;9.319603;0.705020;, - 6.937339;9.170279;0.705020;, - 6.937339;9.170279;0.705020;, - 6.937339;9.170279;0.705020;, - 6.693048;9.269262;0.664350;, - 6.693048;9.269262;0.664350;, - 6.693048;9.269262;0.664350;, - 6.693048;9.269262;0.555896;, - 6.693048;9.269262;0.555896;, - 6.693048;9.269262;0.555896;, - 6.916745;9.323501;0.705020;, - 6.916745;9.323501;0.705020;, - 6.916745;9.323501;0.705020;, - 7.001220;9.409288;0.705020;, - 7.001220;9.409288;0.705020;, - 7.001220;9.409288;0.705020;, - 7.095283;9.321381;0.705020;, - 7.095283;9.321381;0.705020;, - 7.095283;9.321381;0.705020;, - 6.943227;9.166967;0.705020;, - 6.943227;9.166967;0.705020;, - 6.943227;9.166967;0.705020;, - 6.993157;9.433917;0.705020;, - 6.993157;9.433917;0.705020;, - 6.993157;9.433917;0.705020;, - 7.002631;9.569713;0.705020;, - 7.002631;9.569713;0.705020;, - 7.119660;9.611607;0.705020;, - 7.119660;9.611607;0.705020;, - 7.119660;9.611607;0.705020;, - 7.100082;9.330963;0.705020;, - 7.100082;9.330963;0.705020;, - 7.100082;9.330963;0.705020;, - 5.781182;8.999975;0.607299;, - 5.781182;8.999975;0.607299;, - 5.781182;8.999975;0.607299;, - 5.781182;8.999975;0.662299;, - 5.781182;8.999975;0.662299;, - 5.781182;8.999975;0.662299;, - 5.781182;9.943968;0.607299;, - 5.781182;9.943968;0.607299;, - 5.781182;9.943968;0.662299;, - 5.781182;9.943968;0.662299;, - 6.554913;9.416677;0.408793;, - 6.554913;9.416677;0.408793;, - 6.554913;9.416677;0.408793;, - 6.554913;9.625625;0.408793;, - 6.554913;9.625625;0.408793;, - 6.554913;9.625625;0.408793;, - 6.596640;9.625625;0.289999;, - 6.596640;9.625625;0.289999;, - 6.596640;9.416677;0.289999;, - 6.596640;9.416677;0.289999;, - 6.554913;9.416677;0.171205;, - 6.554913;9.416677;0.171205;, - 6.554913;9.416677;0.171205;, - 6.554913;9.625625;0.171205;, - 6.554913;9.625625;0.171205;, - 6.554913;9.625625;0.171205;, - 4.092471;8.999975;0.827299;, - 4.092471;8.999975;0.827299;, - 4.021242;9.094375;0.893299;, - 4.021242;9.094375;0.893299;, - 4.021242;9.094375;0.893299;, - 4.092471;8.999975;0.134299;, - 4.092471;8.999975;0.134299;, - 4.092471;8.999975;0.607299;, - 4.092471;8.999975;0.607299;, - 4.092471;8.999975;0.607299;, - 4.326931;8.999975;0.607299;, - 4.326931;8.999975;0.607299;, - 4.021242;9.094375;0.607299;, - 4.021242;9.094375;0.607299;, - 4.021242;9.094375;0.607299;, - 4.021242;9.094375;0.607299;, - 4.092471;8.999975;0.662299;, - 4.092471;8.999975;0.662299;, - 4.092471;8.999975;0.662299;, - 4.326931;8.999975;0.662299;, - 4.326931;8.999975;0.662299;, - 4.021242;9.094375;0.662299;, - 4.021242;9.094375;0.662299;, - 4.021242;9.094375;0.662299;, - 4.021242;9.094375;0.662299;, - 4.439710;8.999975;0.497299;, - 4.439710;8.999975;0.497299;, - 4.911600;8.999975;0.497299;, - 4.911600;8.999975;0.497299;, - 4.911600;8.999975;0.497299;, - 4.439710;8.999975;0.552299;, - 4.439710;8.999975;0.552299;, - 4.911600;8.999975;0.552299;, - 4.911600;8.999975;0.552299;, - 4.911600;8.999975;0.552299;, - 5.000635;8.999975;0.607299;, - 5.000635;8.999975;0.607299;, - 5.000635;8.999975;0.662299;, - 5.000635;8.999975;0.662299;, - 4.021242;9.849568;0.893299;, - 4.021242;9.849568;0.893299;, - 4.021242;9.849568;0.893299;, - 4.092471;9.943968;0.827299;, - 4.092471;9.943968;0.827299;, - 4.092471;9.943968;0.134299;, - 4.092471;9.943968;0.134299;, - 4.326931;9.943968;0.607299;, - 4.326931;9.943968;0.607299;, - 4.092471;9.943968;0.607299;, - 4.092471;9.943968;0.607299;, - 4.092471;9.943968;0.607299;, - 4.021242;9.849568;0.607299;, - 4.021242;9.849568;0.607299;, - 4.021242;9.849568;0.607299;, - 4.021242;9.849568;0.607299;, - 4.326931;9.943968;0.662299;, - 4.326931;9.943968;0.662299;, - 4.092471;9.943968;0.662299;, - 4.092471;9.943968;0.662299;, - 4.092471;9.943968;0.662299;, - 4.021242;9.849568;0.662299;, - 4.021242;9.849568;0.662299;, - 4.021242;9.849568;0.662299;, - 4.021242;9.849568;0.662299;, - 4.439710;9.943968;0.497299;, - 4.439710;9.943968;0.497299;, - 4.911600;9.943968;0.497299;, - 4.911600;9.943968;0.497299;, - 4.911600;9.943968;0.497299;, - 4.911600;9.943968;0.552299;, - 4.911600;9.943968;0.552299;, - 4.911600;9.943968;0.552299;, - 4.439710;9.943968;0.552299;, - 4.439710;9.943968;0.552299;, - 5.000635;9.943968;0.607299;, - 5.000635;9.943968;0.607299;, - 5.000635;9.943968;0.607299;, - 5.000635;9.943968;0.662299;, - 5.000635;9.943968;0.662299;, - 5.000635;9.943968;0.662299;, - 4.582514;9.980371;0.837847;, - 4.582514;9.980371;0.837847;, - 4.582514;9.836371;0.837847;, - 4.582514;9.836371;0.837847;, - 4.542748;9.836371;0.838107;, - 4.542748;9.836371;0.838107;, - 4.542748;9.836371;0.838107;, - 4.542748;9.980371;0.838107;, - 4.542748;9.980371;0.838107;, - 4.542748;9.980371;0.838107;, - 3.853407;9.114357;0.199999;, - 3.853407;9.114357;0.199999;, - 3.739634;9.114357;0.849999;, - 3.739634;9.114357;0.849999;, - 3.739634;9.114357;0.849999;, - 3.853407;9.114357;0.699999;, - 3.853407;9.114357;0.699999;, - 3.853407;9.465427;0.699999;, - 3.853407;9.465427;0.199999;, - 3.739634;9.465427;0.849999;, - 3.739634;9.465427;0.849999;, - 3.853407;9.816500;0.199999;, - 3.853407;9.816500;0.199999;, - 3.853407;9.816500;0.699999;, - 3.853407;9.816500;0.699999;, - 3.739634;9.816500;0.849999;, - 3.739634;9.816500;0.849999;, - 3.739634;9.816500;0.849999;, - 6.097003;9.416677;0.408793;, - 6.097003;9.416677;0.408793;, - 6.097003;9.416677;0.408793;, - 6.069272;9.416677;0.191822;, - 6.069272;9.416677;0.191822;, - 6.069272;9.625625;0.191822;, - 6.069272;9.625625;0.191822;, - 6.097003;9.625625;0.408793;, - 6.097003;9.625625;0.408793;, - 6.097003;9.625625;0.408793;, - 6.097003;9.416677;0.171205;, - 6.097003;9.416677;0.171205;, - 6.097003;9.416677;0.171205;, - 6.097003;9.625625;0.171205;, - 6.097003;9.625625;0.171205;, - 6.097003;9.625625;0.171205;, - 6.197741;9.625625;0.457999;, - 6.197741;9.625625;0.457999;, - 6.197741;9.416677;0.457999;, - 6.197741;9.416677;0.457999;, - 6.454175;9.416677;0.457999;, - 6.454175;9.416677;0.457999;, - 6.454175;9.625625;0.457999;, - 6.454175;9.625625;0.457999;, - 3.332740;9.836371;0.849896;, - 3.332740;9.836371;0.849896;, - 3.332740;9.836371;0.849896;, - 3.332740;9.980371;0.849896;, - 3.332740;9.980371;0.849896;, - 3.332740;9.980371;0.849896;, - 5.513439;10.036371;0.889615;, - 5.513439;10.036371;0.889615;, - 5.513439;10.036371;0.889615;, - 5.624304;9.972371;0.888889;, - 5.624304;9.972371;0.888889;, - 5.624304;9.972371;0.888889;, - 5.624304;9.844371;0.888889;, - 5.624304;9.844371;0.888889;, - 5.624304;9.844371;0.888889;, - 5.513439;9.780371;0.889615;, - 5.513439;9.780371;0.889615;, - 5.513439;9.780371;0.889615;, - 3.477382;10.049524;0.480000;, - 3.477382;10.049524;0.480000;, - 3.308206;10.049524;0.480000;, - 3.477382;10.049524;0.860001;, - 3.477382;10.049524;0.860001;, - 3.477382;10.049524;0.860001;, - 3.477382;9.541996;0.860001;, - 3.477382;9.541996;0.860001;, - 3.308206;9.330525;0.860001;, - 3.308206;9.330525;0.860001;, - 3.308206;9.330525;0.860001;, - 3.308206;9.541996;0.860001;, - 3.308206;10.049524;0.860001;, - 3.308206;10.049524;0.860001;, - 2.351901;9.114357;0.850000;, - 2.351901;9.114357;0.850000;, - 2.351901;9.114357;0.850000;, - 2.238127;9.114357;0.200000;, - 2.238127;9.114357;0.200000;, - 2.238127;9.114357;0.700000;, - 2.238127;9.114357;0.700000;, - 2.351901;9.465427;0.850000;, - 2.351901;9.465427;0.850000;, - 2.238127;9.465427;0.700000;, - 2.238127;9.465427;0.200000;, - 2.351901;9.816500;0.850000;, - 2.351901;9.816500;0.850000;, - 2.351901;9.816500;0.850000;, - 2.238127;9.816500;0.700000;, - 2.238127;9.816500;0.700000;, - 2.238127;9.816500;0.200000;, - 2.238127;9.816500;0.200000;, - 5.402574;9.844371;0.890341;, - 5.402574;9.844371;0.890341;, - 5.402574;9.844371;0.890341;, - 5.402574;9.972371;0.890341;, - 5.402574;9.972371;0.890341;, - 5.402574;9.972371;0.890341;, - 2.625627;9.706669;0.706400;, - 2.625627;9.706669;0.706400;, - 2.625627;9.706669;0.706400;, - 2.625627;9.706669;0.213600;, - 2.625627;9.706669;0.213600;, - 2.625627;9.706669;0.213600;, - 2.625627;9.208800;0.706400;, - 2.625627;9.208800;0.706400;, - 2.625627;9.208800;0.706400;, - 2.625627;9.208800;0.213600;, - 2.625627;9.208800;0.213600;, - 2.625627;9.208800;0.213600;, - 2.610355;10.049524;0.480000;, - 2.610355;9.541996;0.860000;, - 2.610355;9.541996;0.860000;, - 2.737237;9.330525;0.860000;, - 2.737237;9.330525;0.860000;, - 2.737237;9.330525;0.860000;, - 2.610355;10.049524;0.860000;, - 2.610355;10.049524;0.860000;, - 2.273581;10.058715;0.706400;, - 2.273581;10.058715;0.706400;, - 1.775712;10.058715;0.706400;, - 1.775712;10.058715;0.706400;, - 1.775712;10.058715;0.213600;, - 1.775712;10.058715;0.213600;, - 2.273581;10.058715;0.213600;, - 2.273581;10.058715;0.213600;, - 2.273581;8.856754;0.706400;, - 2.273581;8.856754;0.706400;, - 2.273581;8.856754;0.213600;, - 2.273581;8.856754;0.213600;, - 1.775712;8.856754;0.213600;, - 1.775712;8.856754;0.213600;, - 1.775712;8.856754;0.706400;, - 1.775712;8.856754;0.706400;, - 1.491860;10.058715;0.213600;, - 1.491860;10.058715;0.213600;, - 1.491860;10.058715;0.706400;, - 1.491860;10.058715;0.706400;, - 2.024647;9.457734;0.706400;, - 2.024647;9.457734;0.213600;, - 1.574152;10.218699;0.480000;, - 1.574152;10.218699;0.480000;, - 1.785622;10.218699;0.480000;, - 1.785622;9.541996;0.860000;, - 1.785622;9.541996;0.860000;, - 1.574152;9.711170;0.860000;, - 1.574152;9.711170;0.860000;, - 1.574152;9.711170;0.860000;, - 1.574152;10.218699;0.860000;, - 1.574152;10.218699;0.860000;, - 1.574152;10.218699;0.860000;, - 1.785622;10.218699;0.860000;, - 1.785622;10.218699;0.860000;, - 1.291183;10.090521;0.600000;, - 1.291183;10.090521;0.600000;, - 1.179814;8.968801;0.706400;, - 1.179814;8.968801;0.706400;, - 1.179814;8.968801;0.706400;, - 1.179814;8.968801;0.213600;, - 1.179814;8.968801;0.213600;, - 1.179814;8.968801;0.213600;, - 1.179814;9.706669;0.213600;, - 1.179814;9.706669;0.213600;, - 1.179814;9.706669;0.213600;, - 1.179814;9.706669;0.706400;, - 1.179814;9.706669;0.706400;, - 1.179814;9.706669;0.706400;, - 1.423666;9.208800;0.706400;, - 1.423666;9.208800;0.706400;, - 1.423666;9.208800;0.706400;, - 1.423666;9.208800;0.706400;, - 1.423666;9.706669;0.706400;, - 1.423666;9.706669;0.213600;, - 1.423666;9.208800;0.213600;, - 1.423666;9.208800;0.213600;, - 1.423666;9.208800;0.213600;, - 1.423666;9.208800;0.213600;, - 0.701730;10.090521;0.600000;, - 0.701730;10.090521;0.600000;, - 3.477382;10.768522;0.480000;, - 3.477382;10.768522;0.480000;, - 3.308206;10.895405;0.480000;, - 3.477382;10.768522;0.860001;, - 3.477382;10.768522;0.860001;, - 3.308206;10.895405;0.860001;, - 2.610355;10.895405;0.480000;, - 2.610355;10.895405;0.860000;, - 1.954798;10.895405;0.480000;, - 1.954798;10.895405;0.480000;, - 1.574152;10.514757;0.480000;, - 1.954798;10.895405;0.860000;, - 1.954798;10.895405;0.860000;, - 1.574152;10.514757;0.860000;, - 1.291183;10.669608;0.600000;, - 1.291183;10.669608;0.600000;, - 0.701730;10.669608;0.600000;, - 0.701730;10.669608;0.600000;, - 0.162000;10.592889;0.850000;, - 0.162000;10.592889;0.850000;, - 0.162000;10.592889;0.400000;, - 0.162000;10.592889;0.400000;, - 0.384438;11.237040;0.797501;, - 0.384438;11.237040;0.797501;, - 0.384438;10.687464;0.732393;, - 0.384438;10.687464;0.732393;, - 0.384438;10.687464;0.732393;, - 0.384438;10.303647;0.732393;, - 0.384438;10.303647;0.732393;, - 0.384438;11.486215;0.839315;, - 0.384438;11.486215;0.839315;, - 0.384438;11.486215;0.839315;, - 0.306190;11.559654;0.839315;, - 0.306190;11.559654;0.839315;, - 0.306190;10.687464;0.732393;, - 0.306190;10.687464;0.732393;, - 0.306190;10.303647;0.732393;, - 0.306190;10.303647;0.732393;, - 0.306190;10.303647;0.732393;, - 0.290080;11.185386;0.360912;, - 0.290080;11.185386;0.360912;, - 0.290080;11.154265;0.360912;, - 0.290080;11.154265;0.360912;, - 0.203526;11.460281;0.360912;, - 0.282675;11.429161;0.360912;, - 0.282675;11.429161;0.360912;, - 0.192219;10.728957;0.360912;, - 0.282675;10.760077;0.360912;, - 0.282675;10.760077;0.360912;, - 0.296411;10.604476;0.827522;, - 0.296411;10.604476;0.827522;, - 0.791490;10.604476;0.827522;, - 0.791490;10.604476;0.827522;, - 0.791490;10.604476;0.827522;, - 0.296411;10.977919;0.827522;, - 0.296411;10.977919;0.827522;, - 0.791490;10.977919;0.827522;, - 0.791490;10.977919;0.827522;, - 0.791490;10.977919;0.827522;, - 2.022394;0.022285;1.224938;, - 2.022394;0.022285;1.224938;, - 2.022394;0.022285;1.224938;, - 1.964576;0.527998;1.508697;, - 1.964576;0.527998;1.508697;, - 1.964576;0.527998;1.508697;, - 2.225000;1.050444;1.309000;, - 2.225000;1.050444;1.309000;, - 2.225000;1.050444;1.309000;, - 1.650000;0.022285;1.224938;, - 1.650000;0.022285;1.224938;, - 1.650000;0.527998;1.508697;, - 1.650000;0.527998;1.508697;, - 1.650000;1.050444;1.309000;, - 1.650000;1.050444;1.309000;, - 1.277606;0.022285;1.224938;, - 1.277606;0.022285;1.224938;, - 1.277606;0.022285;1.224938;, - 1.335424;0.527998;1.508697;, - 1.335424;0.527998;1.508697;, - 1.335424;0.527998;1.508697;, - 1.075000;1.050444;1.309000;, - 1.075000;1.050444;1.309000;, - 1.075000;1.050444;1.309000;, - 2.180000;2.735444;1.009000;, - 2.180000;2.735444;1.009000;, - 2.180000;2.735444;1.009000;, - 2.630000;2.735444;1.009000;, - 2.630000;2.735444;1.009000;, - 2.630000;2.735444;1.009000;, - 2.180000;2.465444;1.009000;, - 2.180000;2.465444;1.009000;, - 1.650000;2.465444;1.009000;, - 1.120000;2.735444;1.009000;, - 1.120000;2.735444;1.009000;, - 1.120000;2.735444;1.009000;, - 1.120000;2.465444;1.009000;, - 1.120000;2.465444;1.009000;, - 0.670000;2.735444;1.009000;, - 0.670000;2.735444;1.009000;, - 0.670000;2.735444;1.009000;, - 2.180000;4.040444;1.009000;, - 2.180000;4.040444;1.009000;, - 2.180000;4.040444;1.009000;, - 2.630000;4.040444;1.009000;, - 2.630000;4.040444;1.009000;, - 2.630000;4.040444;1.009000;, - 2.180000;3.545444;1.009000;, - 2.180000;3.545444;1.009000;, - 2.180000;3.545444;1.009000;, - 1.650000;3.545444;1.009000;, - 1.650000;3.545444;1.009000;, - 1.120000;4.040444;1.009000;, - 1.120000;4.040444;1.009000;, - 1.120000;4.040444;1.009000;, - 1.120000;3.545444;1.009000;, - 1.120000;3.545444;1.009000;, - 1.120000;3.545444;1.009000;, - 0.670000;4.040444;1.009000;, - 0.670000;4.040444;1.009000;, - 0.670000;4.040444;1.009000;, - 2.211500;4.924759;0.955231;, - 2.211500;4.924759;0.955231;, - 2.211500;4.924759;0.955231;, - 2.183926;5.309234;0.907731;, - 2.183926;5.309234;0.907731;, - 1.650000;4.924759;0.955231;, - 1.650000;4.924759;0.955231;, - 1.108550;5.309234;0.907731;, - 1.108550;5.309234;0.907731;, - 1.088500;4.924759;0.955231;, - 1.088500;4.924759;0.955231;, - 1.088500;4.924759;0.955231;, - 0.864000;5.747889;1.400000;, - 0.864000;5.747889;1.400000;, - 0.864000;5.747889;1.400000;, - 0.270000;5.747889;1.400000;, - 0.270000;5.747889;1.400000;, - 0.270000;5.747889;1.400000;, - 0.270000;5.747889;1.400000;, - 0.270000;4.472888;1.400000;, - 0.270000;4.472888;1.400000;, - 0.344000;4.439500;1.395000;, - 0.344000;4.439500;1.395000;, - 0.344000;4.439500;1.395000;, - 0.434000;5.122600;1.395000;, - 0.434000;5.122600;1.395000;, - 0.434000;5.122600;1.395000;, - 5.557411;7.308371;1.056685;, - 5.557411;7.308371;1.056685;, - 5.757436;7.308371;1.055375;, - 5.757436;7.308371;1.055375;, - 5.564542;7.308371;1.482253;, - 5.564542;7.308371;1.482253;, - 5.564542;7.308371;1.482253;, - 5.764566;7.308371;1.480943;, - 5.764566;7.308371;1.480943;, - 5.764566;7.308371;1.480943;, - 2.211500;6.391939;1.240231;, - 2.211500;6.391939;1.240231;, - 2.211500;6.899809;1.050231;, - 2.211500;6.899809;1.050231;, - 2.211500;6.899809;1.050231;, - 1.650000;6.391939;1.240231;, - 1.650000;6.899809;1.050231;, - 1.650000;6.899809;1.050231;, - 1.088500;6.391939;1.240231;, - 1.088500;6.391939;1.240231;, - 1.088500;6.899809;1.050231;, - 1.088500;6.899809;1.050231;, - 1.088500;6.899809;1.050231;, - 0.621000;6.553689;1.368093;, - 0.621000;6.553689;1.368093;, - 0.621000;6.553689;1.368093;, - 0.864000;6.512889;1.400000;, - 0.864000;6.512889;1.400000;, - 0.864000;6.512889;1.400000;, - 0.270000;6.512889;1.400000;, - 0.270000;6.512889;1.400000;, - 0.270000;6.512889;1.400000;, - 0.270000;6.512889;1.400000;, - 0.474000;6.505000;1.395000;, - 0.474000;6.505000;1.395000;, - 0.474000;6.505000;1.395000;, - 1.157854;8.456665;1.570000;, - 1.144800;8.335900;1.292500;, - 1.144800;8.335900;1.292500;, - 1.144800;8.417500;1.427500;, - 1.001073;8.438701;1.587800;, - 1.001073;8.438701;1.587800;, - 1.295585;8.438701;1.587800;, - 1.295585;8.438701;1.587800;, - 1.295585;8.438701;1.587800;, - 1.295585;8.438701;1.587800;, - 1.291183;8.380595;1.165000;, - 1.291183;8.380595;1.165000;, - 1.291183;8.380595;1.165000;, - 1.206975;8.252790;1.593860;, - 1.206975;7.730014;1.348713;, - 1.206975;7.730014;1.348713;, - 1.291183;8.380595;1.580000;, - 1.291183;8.380595;1.580000;, - 1.291183;7.708855;1.265000;, - 1.291183;7.708855;1.265000;, - 1.291183;7.708855;1.265000;, - 1.291183;7.708855;1.265000;, - 0.729000;8.335782;1.300000;, - 0.729000;8.335782;1.300000;, - 0.621000;7.481889;1.150000;, - 0.621000;7.481889;1.150000;, - 0.712800;8.335900;1.292500;, - 0.712800;8.335900;1.292500;, - 0.712800;8.417500;1.427500;, - 0.701730;8.380595;1.165000;, - 0.701730;8.380595;1.165000;, - 0.701730;8.380595;1.165000;, - 0.701730;8.380595;1.580000;, - 0.701730;8.380595;1.580000;, - 0.701730;7.708855;1.265000;, - 0.701730;7.708855;1.265000;, - 0.701730;7.708855;1.265000;, - 0.701730;7.708855;1.265000;, - 0.785938;8.252790;1.593860;, - 0.785938;7.730014;1.348713;, - 0.785938;7.730014;1.348713;, - 5.781182;8.999975;1.102299;, - 5.781182;8.999975;1.102299;, - 5.781182;8.999975;1.102299;, - 5.816796;9.094374;1.168299;, - 5.816796;9.094374;1.168299;, - 5.816796;9.094374;1.168299;, - 5.816796;9.094374;1.168299;, - 5.816796;9.849567;1.168299;, - 5.816796;9.849567;1.168299;, - 5.816796;9.849567;1.168299;, - 5.816796;9.849567;1.168299;, - 5.781182;9.943968;1.102299;, - 5.781182;9.943968;1.102299;, - 5.781182;9.943968;1.102299;, - 5.513186;9.980371;0.845168;, - 5.513186;9.980371;0.845168;, - 5.513186;9.980371;0.845168;, - 5.513186;9.836371;0.845168;, - 5.513186;9.836371;0.845168;, - 5.513186;9.836371;0.845168;, - 5.557411;9.428371;1.056685;, - 5.557411;8.948371;1.056685;, - 5.757436;9.428371;1.055375;, - 5.757436;8.948371;1.055375;, - 5.564542;9.428371;1.482253;, - 5.564542;9.428371;1.482253;, - 5.564542;8.948371;1.482253;, - 5.564542;8.948371;1.482253;, - 5.764566;9.428371;1.480943;, - 5.764566;9.428371;1.480943;, - 5.764566;8.948371;1.480943;, - 5.764566;8.948371;1.480943;, - 4.273510;9.094375;1.168299;, - 4.273510;9.094375;1.168299;, - 4.273510;9.094375;1.168299;, - 4.273510;9.094375;1.168299;, - 4.326932;8.999975;1.102299;, - 4.439710;9.094375;1.168299;, - 4.439710;9.094375;1.168299;, - 5.000635;9.094375;1.168299;, - 5.000635;9.094375;1.168299;, - 5.000635;8.999975;1.102299;, - 5.000635;8.999975;1.102299;, - 4.439710;8.999975;1.102299;, - 4.439710;8.999975;1.102299;, - 4.273510;9.849568;1.168299;, - 4.273510;9.849568;1.168299;, - 4.273510;9.849568;1.168299;, - 4.326932;9.943968;1.102299;, - 4.439710;9.849568;1.168299;, - 4.439710;9.849568;1.168299;, - 4.439710;9.943968;1.102299;, - 4.439710;9.943968;1.102299;, - 5.000635;9.943968;1.102299;, - 5.000635;9.943968;1.102299;, - 5.000635;9.849568;1.168299;, - 5.000635;9.849568;1.168299;, - 5.514779;9.908371;0.969597;, - 3.477382;10.049524;1.210001;, - 3.477382;10.049524;1.210001;, - 3.477382;9.541996;1.210001;, - 3.477382;9.541996;1.210001;, - 3.308206;9.330525;1.210001;, - 3.308206;9.330525;1.210001;, - 3.308206;9.330525;1.210001;, - 3.308206;9.330525;1.210001;, - 3.370776;9.681329;1.360001;, - 3.370776;9.681329;1.360001;, - 3.370776;10.087790;1.360001;, - 3.370776;10.087790;1.360001;, - 2.610355;9.541996;1.210000;, - 2.610355;9.541996;1.210000;, - 2.610355;9.541996;1.210000;, - 2.737237;9.330525;1.210000;, - 2.737237;9.330525;1.210000;, - 2.737237;9.330525;1.210000;, - 2.605451;10.087790;1.360000;, - 2.673121;9.681329;1.360000;, - 2.673121;9.681329;1.360000;, - 3.263738;9.504920;1.360001;, - 3.263738;9.504920;1.360001;, - 3.221444;9.664412;1.360001;, - 2.810496;9.504920;1.360000;, - 3.221444;10.087790;1.360001;, - 1.785622;9.541996;1.210000;, - 1.785622;9.541996;1.210000;, - 1.785622;9.541996;1.210000;, - 1.574152;9.711170;1.210000;, - 1.574152;9.711170;1.210000;, - 1.574152;9.711170;1.210000;, - 1.574152;9.711170;1.210000;, - 1.943341;10.228918;1.360000;, - 1.877459;9.681329;1.360000;, - 1.877459;9.681329;1.360000;, - 1.574152;10.218699;1.210000;, - 1.574152;10.218699;1.210000;, - 1.690794;10.228918;1.360000;, - 1.690794;10.228918;1.360000;, - 1.690794;9.822455;1.360000;, - 1.690794;9.822455;1.360000;, - 1.144800;10.003599;1.427500;, - 1.144800;10.105600;1.292500;, - 1.144800;10.105600;1.292500;, - 1.295585;9.903199;1.587800;, - 1.295585;9.903199;1.587800;, - 1.295585;9.903199;1.587800;, - 1.295585;9.903199;1.587800;, - 1.001073;9.903199;1.587800;, - 1.001073;9.903199;1.587800;, - 1.291183;9.629884;2.100000;, - 1.291183;9.629884;2.100000;, - 1.291183;9.629884;2.100000;, - 1.291183;9.629884;1.165000;, - 1.291183;9.629884;1.165000;, - 1.291183;9.629884;1.165000;, - 1.291183;10.090521;1.165000;, - 1.291183;10.090521;1.165000;, - 1.291183;10.090521;1.165000;, - 1.206975;10.200697;2.113860;, - 1.291183;10.090521;2.100000;, - 1.291183;10.090521;2.100000;, - 1.291183;8.914934;1.165000;, - 1.291183;8.914934;1.165000;, - 1.291183;8.914934;1.165000;, - 1.291183;8.914934;1.580000;, - 1.291183;8.914934;1.580000;, - 1.291183;8.914934;1.580000;, - 0.324000;10.031889;1.000000;, - 0.712800;10.003599;1.427500;, - 0.712800;10.105600;1.292500;, - 0.712800;10.105600;1.292500;, - 0.473000;7.990001;1.320000;, - 0.473000;7.990001;1.320000;, - 0.473000;7.990001;1.320000;, - 0.350000;7.990001;1.320000;, - 0.350000;7.990001;1.320000;, - 0.350000;7.990001;1.580000;, - 0.350000;7.990001;1.580000;, - 0.473000;7.990001;1.580000;, - 0.473000;7.990001;1.580000;, - 0.473000;9.840000;1.400000;, - 0.473000;9.840000;1.400000;, - 0.350000;9.840000;1.400000;, - 0.602000;8.120901;1.438300;, - 0.602000;9.824600;1.518300;, - 0.350000;9.716153;1.400000;, - 0.350000;9.716153;1.400000;, - 0.602000;9.714376;1.518300;, - 0.602000;9.714376;1.518300;, - 0.473000;9.716153;1.400000;, - 0.701730;10.090521;1.165000;, - 0.701730;10.090521;1.165000;, - 0.701730;10.090521;1.165000;, - 0.701730;10.090521;2.100000;, - 0.701730;10.090521;2.100000;, - 0.701730;9.629884;2.100000;, - 0.701730;9.629884;2.100000;, - 0.701730;9.629884;2.100000;, - 0.701730;9.629884;1.165000;, - 0.701730;9.629884;1.165000;, - 0.701730;9.629884;1.165000;, - 0.785938;10.200697;2.113860;, - 0.701730;8.914934;1.580000;, - 0.701730;8.914934;1.580000;, - 0.701730;8.914934;1.580000;, - 0.701730;8.914934;1.165000;, - 0.701730;8.914934;1.165000;, - 0.701730;8.914934;1.165000;, - 5.757436;10.788371;1.055375;, - 5.757436;10.788371;1.055375;, - 5.757436;10.788371;1.055375;, - 5.557411;10.788371;1.056685;, - 5.557411;10.788371;1.056685;, - 5.557411;10.788371;1.056685;, - 5.557411;11.108371;1.056685;, - 5.557411;11.108371;1.056685;, - 5.757436;11.108371;1.055375;, - 5.757436;11.108371;1.055375;, - 5.764566;11.108371;1.480943;, - 5.764566;11.108371;1.480943;, - 5.764566;11.108371;1.480943;, - 5.564542;11.108371;1.482253;, - 5.564542;11.108371;1.482253;, - 5.564542;11.108371;1.482253;, - 5.564542;10.788371;1.482253;, - 5.564542;10.788371;1.482253;, - 5.764566;10.788371;1.480943;, - 5.764566;10.788371;1.480943;, - 5.557411;10.948371;1.056685;, - 5.557411;10.948371;1.056685;, - 5.557411;10.948371;1.056685;, - 5.564542;10.948371;1.482253;, - 5.564542;10.948371;1.482253;, - 5.764566;10.948371;1.480943;, - 5.764566;10.948371;1.480943;, - 5.757436;10.948371;1.055375;, - 5.757436;10.948371;1.055375;, - 5.757436;10.948371;1.055375;, - 3.477382;10.768522;1.210001;, - 3.477382;10.768522;1.210001;, - 3.477382;10.768522;1.210001;, - 3.477382;10.768522;1.210001;, - 3.308206;10.895405;1.210001;, - 3.308206;10.895405;1.210001;, - 3.308206;10.895405;1.210001;, - 3.370776;10.653745;1.360001;, - 3.370776;10.653745;1.360001;, - 2.610355;10.895405;1.210000;, - 2.610355;10.895405;1.210000;, - 2.605451;10.759588;1.360000;, - 2.605451;10.759588;1.360000;, - 3.221444;10.759588;1.360001;, - 3.221444;10.759588;1.360001;, - 1.954798;10.895405;1.210000;, - 1.954798;10.895405;1.210000;, - 1.954798;10.895405;1.210000;, - 1.954798;10.895405;1.210000;, - 1.574152;10.514757;1.210000;, - 1.574152;10.514757;1.210000;, - 1.574152;10.514757;1.210000;, - 2.026791;10.759588;1.360000;, - 2.026791;10.759588;1.360000;, - 1.690794;10.442054;1.360000;, - 1.690794;10.442054;1.360000;, - 1.206975;10.651367;1.868713;, - 1.206975;10.651367;1.868713;, - 1.291183;10.669608;1.785000;, - 1.291183;10.669608;1.785000;, - 1.291183;10.669608;1.785000;, - 1.291183;10.669608;1.785000;, - 0.384438;11.348052;1.336887;, - 0.384438;10.811944;1.336887;, - 0.384438;10.811944;1.336887;, - 0.384438;10.811944;1.336887;, - 0.384438;11.621069;1.336887;, - 0.384438;11.621069;1.336887;, - 0.384438;10.303647;1.119859;, - 0.384438;10.303647;1.119859;, - 0.306190;11.694510;1.336887;, - 0.306190;10.811944;1.336887;, - 0.306190;10.811944;1.336887;, - 0.306190;10.811944;1.336887;, - 0.306190;10.303647;1.119859;, - 0.306190;10.303647;1.119859;, - 0.290080;11.185386;0.922292;, - 0.290080;11.185386;0.922292;, - 0.290080;11.154265;0.922292;, - 0.290080;11.154265;0.922292;, - 0.203526;11.460281;0.922292;, - 0.282675;11.429161;0.922292;, - 0.282675;11.429161;0.922292;, - 0.192219;10.728957;0.922292;, - 0.282675;10.760077;0.922292;, - 0.282675;10.760077;0.922292;, - 0.191908;10.391821;0.997700;, - 0.191908;10.391821;0.997700;, - 0.191908;10.827504;0.997700;, - 0.191908;10.827504;0.997700;, - 0.320198;10.370019;1.071678;, - 0.320198;10.370019;1.071678;, - 0.701730;10.669608;1.785000;, - 0.701730;10.669608;1.785000;, - 0.701730;10.669608;1.785000;, - 0.701730;10.669608;1.785000;, - 0.785938;10.651367;1.868713;, - 0.785938;10.651367;1.868713;, - 0.434000;5.117500;1.770000;, - 0.434000;5.117500;1.770000;, - 0.434000;5.117500;1.770000;, - 0.434000;5.117500;1.770000;, - 0.474000;6.403000;1.770000;, - 0.474000;6.403000;1.770000;, - 1.380187;8.442361;1.740032;, - 1.380187;8.442361;1.740032;, - 1.380187;8.442361;1.881088;, - 1.380187;8.442361;1.881088;, - 1.380187;8.442361;1.881088;, - 1.375398;8.500993;1.659580;, - 1.375398;8.500993;1.659580;, - 1.300374;8.378100;1.690000;, - 1.300374;8.378100;1.690000;, - 1.001073;8.378100;1.690000;, - 1.001073;8.378100;1.920000;, - 1.001073;8.378100;1.920000;, - 1.300374;8.378100;1.920000;, - 1.300374;8.378100;1.920000;, - 1.300374;8.378100;1.920000;, - 1.157854;9.729999;1.670000;, - 1.380187;9.932087;2.125760;, - 1.380187;9.932087;1.740032;, - 1.380187;9.932087;1.740032;, - 1.380187;9.193751;2.311072;, - 1.380187;9.193751;2.311072;, - 1.380187;9.786242;2.311072;, - 1.380187;9.786242;2.311072;, - 1.375398;9.853255;1.659580;, - 1.375398;9.853255;1.659580;, - 1.001073;9.165900;2.390000;, - 1.300374;9.165900;2.390000;, - 1.300374;9.165900;2.390000;, - 1.001073;9.822401;2.390000;, - 1.001073;9.822401;2.390000;, - 1.300374;9.822401;2.390000;, - 1.300374;9.822401;2.390000;, - 1.300374;9.822401;2.390000;, - 1.300374;9.822401;2.390000;, - 1.001073;9.984000;2.180000;, - 1.300374;9.984000;2.180000;, - 1.300374;9.984000;2.180000;, - 1.001073;9.984000;1.690000;, - 1.300374;9.984000;1.690000;, - 1.300374;9.984000;1.690000;, - 0.602000;8.120901;1.664500;, - 0.602000;8.120901;1.664500;, - 0.350000;9.731160;1.943483;, - 0.350000;9.731160;1.943483;, - 0.602000;9.727733;1.991131;, - 0.310000;9.017695;1.730000;, - 0.350000;8.980601;1.730000;, - 0.350000;8.980601;1.730000;, - 0.350000;8.266534;1.730000;, - 0.350000;8.266534;1.730000;, - 0.310000;8.229440;1.730000;, - 0.384438;10.811944;1.906371;, - 0.384438;10.811944;1.906371;, - 0.384438;10.811944;1.906371;, - 0.384438;11.434348;2.052865;, - 0.384438;11.434348;2.052865;, - 0.384438;11.434348;2.052865;, - 0.306190;10.811944;1.983195;, - 0.306190;10.811944;1.983195;, - 0.306190;11.507788;2.129689;, - 0.306190;11.507788;2.129689;, - 0.306190;11.507788;2.129689;, - 0.306190;11.507788;2.129689;, - 0.300186;10.544438;1.851922;, - 0.300186;10.544438;1.851922;, - 0.300186;10.957540;1.928746;, - 0.300186;10.957540;1.928746;, - 0.473000;10.370001;2.115000;, - 0.473000;10.370001;2.115000;, - 0.350000;10.370001;2.115000;, - 0.602000;10.285300;2.140350;, - 0.602000;10.285300;2.140350;, - 0.350000;8.929999;2.830000;, - 0.350000;8.929999;2.830000;, - 0.350000;8.929999;2.830000;, - 0.473000;8.929999;2.830000;, - 0.473000;8.929999;2.830000;, - 0.473000;8.929999;2.830000;, - 0.473000;8.929999;2.830000;, - 0.473000;9.770000;3.220000;, - 0.473000;9.770000;3.220000;, - 0.350000;9.770000;3.220000;, - 0.350000;9.770000;3.220000;, - 0.350000;9.770000;3.220000;, - 0.350000;9.770000;3.220000;, - 0.602000;9.014699;2.762400;, - 0.602000;9.014699;2.762400;, - 0.602000;9.014699;2.762400;, - 0.602000;9.762300;3.101700;, - 0.350000;9.755640;2.960000;, - 0.350000;9.755640;2.960000;, - 0.602000;9.749520;2.875500;, - 0.210000;8.377817;2.627000;, - 0.210000;8.377817;2.627000;, - 0.170000;8.452005;2.965000;, - 0.170000;8.452005;2.965000;, - 0.170000;8.452005;2.965000;, - 0.170000;8.804401;2.965000;, - 0.170000;8.804401;2.965000;, - 0.170000;8.804401;2.965000;, - 0.210000;8.860044;2.627000;, - 0.210000;8.860044;2.627000;, - 0.308518;9.017695;2.354001;, - 0.208518;8.924960;2.705000;, - 0.208518;8.924960;2.705000;, - 0.350000;8.979228;2.354001;, - 0.350000;8.979228;2.354001;, - 0.250000;8.886491;2.705000;, - 0.250000;8.886491;2.705000;, - 0.250000;8.886491;2.705000;, - 0.350000;8.267908;2.354001;, - 0.350000;8.267908;2.354001;, - 0.250000;8.360644;2.705000;, - 0.250000;8.360644;2.705000;, - 0.250000;8.360644;2.705000;, - 0.308518;8.229440;2.354001;, - 0.208518;8.322174;2.705000;, - 0.208518;8.322174;2.705000;, - 0.350000;10.300000;3.220000;, - 0.350000;10.300000;3.220000;, - 0.473000;10.300000;3.220000;, - 0.473000;10.300000;3.220000;, - 0.473000;10.300000;3.220000;, - 0.473000;10.300000;3.220000;, - 0.473000;10.370001;3.103000;, - 0.473000;10.370001;3.103000;, - 0.350000;10.370001;3.103000;, - 0.602000;10.285300;2.999910;, - 0.602000;10.285300;2.999910;, - 0.602000;10.223000;3.101700;, - 1.108750;4.035734;0.052731;, - 2.148500;4.277565;-0.215970;, - 2.148500;4.277565;-0.215970;, - 2.148500;4.277565;-0.215970;, - 2.148500;4.035734;-0.327269;, - 2.148500;4.035734;-0.327269;, - 2.148500;3.793904;-0.215970;, - 2.148500;3.793904;-0.215970;, - 2.148500;3.793904;-0.215970;, - 2.148500;3.693734;0.052731;, - 2.148500;3.693734;0.052731;, - 2.191250;4.035734;0.052731;, - 1.650000;4.277565;-0.215970;, - 1.650000;4.277565;-0.215970;, - 1.650000;4.035734;-0.327269;, - 1.650000;3.793904;-0.215970;, - 1.650000;3.793904;-0.215970;, - 1.650000;3.693734;0.052731;, - 1.151500;4.277565;-0.215970;, - 1.151500;4.277565;-0.215970;, - 1.151500;4.277565;-0.215970;, - 1.151500;4.035734;-0.327269;, - 1.151500;4.035734;-0.327269;, - 1.151500;3.793904;-0.215970;, - 1.151500;3.793904;-0.215970;, - 1.151500;3.793904;-0.215970;, - 1.151500;3.693734;0.052731;, - 1.151500;3.693734;0.052731;, - 2.148500;4.377734;0.052731;, - 2.148500;4.377734;0.052731;, - 1.650000;4.377734;0.052731;, - 1.151500;4.377734;0.052731;, - 1.151500;4.377734;0.052731;, - 2.148500;4.277565;0.321432;, - 2.148500;4.277565;0.321432;, - 2.148500;4.277565;0.321432;, - 2.148500;4.035734;0.432731;, - 2.148500;4.035734;0.432731;, - 2.148500;3.793904;0.321432;, - 2.148500;3.793904;0.321432;, - 2.148500;3.793904;0.321432;, - 1.650000;4.035734;0.432731;, - 1.650000;4.277565;0.321432;, - 1.650000;4.277565;0.321432;, - 1.650000;3.793904;0.321432;, - 1.650000;3.793904;0.321432;, - 1.151500;4.277565;0.321432;, - 1.151500;4.277565;0.321432;, - 1.151500;4.277565;0.321432;, - 1.151500;4.035734;0.432731;, - 1.151500;4.035734;0.432731;, - 1.151500;3.793904;0.321432;, - 1.151500;3.793904;0.321432;, - 1.151500;3.793904;0.321432;, - 0.310000;9.735457;2.260000;, - 0.350000;9.698363;2.260000;, - 0.350000;9.698363;2.260000;, - 0.350000;8.984295;2.260000;, - 0.350000;8.984295;2.260000;, - 0.310000;8.947201;2.260000;, - 0.210000;9.095578;3.157000;, - 0.210000;9.095578;3.157000;, - 0.170000;9.169767;3.495000;, - 0.170000;9.169767;3.495000;, - 0.170000;9.169767;3.495000;, - 0.170000;9.522163;3.495000;, - 0.170000;9.522163;3.495000;, - 0.170000;9.522163;3.495000;, - 0.210000;9.577806;3.157000;, - 0.210000;9.577806;3.157000;, - 0.308518;9.735457;2.884000;, - 0.208518;9.642721;3.235000;, - 0.208518;9.642721;3.235000;, - 0.350000;9.696989;2.884000;, - 0.350000;9.696989;2.884000;, - 0.250000;9.604253;3.235000;, - 0.250000;9.604253;3.235000;, - 0.250000;9.604253;3.235000;, - 0.350000;8.985670;2.884000;, - 0.350000;8.985670;2.884000;, - 0.250000;9.078405;3.235000;, - 0.250000;9.078405;3.235000;, - 0.250000;9.078405;3.235000;, - 0.308518;8.947201;2.884000;, - 0.208518;9.039936;3.235000;, - 0.208518;9.039936;3.235000;, - 0.706562;8.438701;1.587800;, - 0.706562;8.438701;1.587800;, - 0.706562;8.438701;1.587800;, - 0.706562;8.438701;1.587800;, - 0.706562;9.903199;1.587800;, - 0.706562;9.903199;1.587800;, - 0.706562;9.903199;1.587800;, - 0.706562;9.903199;1.587800;, - 0.621959;8.442361;1.740032;, - 0.621959;8.442361;1.740032;, - 0.621959;8.442361;1.881088;, - 0.621959;8.442361;1.881088;, - 0.621959;8.442361;1.881088;, - 0.626748;8.500993;1.659580;, - 0.626748;8.500993;1.659580;, - 0.701773;8.378100;1.690000;, - 0.701773;8.378100;1.690000;, - 0.701773;8.378100;1.920000;, - 0.701773;8.378100;1.920000;, - 0.701773;8.378100;1.920000;, - 0.621959;9.932087;2.125760;, - 0.621959;9.932087;1.740032;, - 0.621959;9.932087;1.740032;, - 0.621959;9.193751;2.311072;, - 0.621959;9.193751;2.311072;, - 0.621959;9.786242;2.311072;, - 0.621959;9.786242;2.311072;, - 0.626748;9.853255;1.659580;, - 0.626748;9.853255;1.659580;, - 0.701773;9.165900;2.390000;, - 0.701773;9.165900;2.390000;, - 0.701773;9.822401;2.390000;, - 0.701773;9.822401;2.390000;, - 0.701773;9.822401;2.390000;, - 0.701773;9.822401;2.390000;, - 0.701773;9.984000;2.180000;, - 0.701773;9.984000;2.180000;, - 0.701773;9.984000;1.690000;, - 0.701773;9.984000;1.690000;, - 6.594306;9.104997;0.024595;, - 6.594306;9.104997;0.024595;, - 6.594306;9.104997;0.024595;, - 6.561830;9.228369;-0.117754;, - 6.561830;9.228369;-0.117754;, - 6.561830;9.228369;-0.117754;, - 6.561830;9.093629;-0.249652;, - 6.561830;9.093629;-0.249652;, - 6.561830;9.093629;-0.249652;, - 6.561830;9.235703;-0.119092;, - 6.561830;9.235703;-0.119092;, - 6.561830;9.235703;-0.119092;, - 6.561830;9.385450;-0.133884;, - 6.561830;9.385450;-0.133884;, - 6.561830;9.385450;-0.133884;, - 6.561830;9.364082;-0.284082;, - 6.561830;9.364082;-0.284082;, - 6.561830;9.364082;-0.284082;, - 6.561830;9.094540;-0.257456;, - 6.561830;9.094540;-0.257456;, - 6.561830;9.094540;-0.257456;, - 6.561830;9.404812;-0.108547;, - 6.561830;9.404812;-0.108547;, - 6.561830;9.404812;-0.108547;, - 6.561830;9.551003;-0.018219;, - 6.561830;9.551003;-0.018219;, - 6.561830;9.679543;-0.094811;, - 6.561830;9.679543;-0.094811;, - 6.561830;9.679543;-0.094811;, - 6.561830;9.377419;-0.281490;, - 6.561830;9.377419;-0.281490;, - 6.561830;9.377419;-0.281490;, - 6.756689;9.104997;0.024595;, - 6.756689;9.104997;0.024595;, - 6.756689;9.104997;0.024595;, - 6.789165;9.228369;-0.117754;, - 6.789165;9.228369;-0.117754;, - 6.789165;9.228369;-0.117754;, - 6.789165;9.093629;-0.249652;, - 6.789165;9.093629;-0.249652;, - 6.789165;9.093629;-0.249652;, - 6.740450;9.016507;0.046151;, - 6.740450;9.016507;0.046151;, - 6.740450;9.016507;0.046151;, - 6.610544;9.016507;0.046151;, - 6.610544;9.016507;0.046151;, - 6.610544;9.016507;0.046151;, - 6.789165;9.235703;-0.119092;, - 6.789165;9.235703;-0.119092;, - 6.789165;9.235703;-0.119092;, - 6.789165;9.385450;-0.133884;, - 6.789165;9.385450;-0.133884;, - 6.789165;9.385450;-0.133884;, - 6.789165;9.364082;-0.284082;, - 6.789165;9.364082;-0.284082;, - 6.789165;9.364082;-0.284082;, - 6.789165;9.094540;-0.257456;, - 6.789165;9.094540;-0.257456;, - 6.789165;9.094540;-0.257456;, - 6.789165;9.404812;-0.108547;, - 6.789165;9.404812;-0.108547;, - 6.789165;9.404812;-0.108547;, - 6.789165;9.551003;-0.018219;, - 6.789165;9.551003;-0.018219;, - 6.789165;9.679543;-0.094811;, - 6.789165;9.679543;-0.094811;, - 6.789165;9.679543;-0.094811;, - 6.789165;9.377419;-0.281490;, - 6.789165;9.377419;-0.281490;, - 6.789165;9.377419;-0.281490;, - 6.728245;9.275375;0.120996;, - 6.728245;9.275375;0.120996;, - 6.728245;9.275375;0.120996;, - 6.900592;9.282207;0.093882;, - 6.900592;9.282207;0.093882;, - 6.900592;9.282207;0.093882;, - 6.927647;9.112520;0.093882;, - 6.927647;9.112520;0.093882;, - 6.927647;9.112520;0.093882;, - 6.905502;9.286638;0.093882;, - 6.905502;9.286638;0.093882;, - 6.905502;9.286638;0.093882;, - 6.996336;9.384120;0.093882;, - 6.996336;9.384120;0.093882;, - 6.996336;9.384120;0.093882;, - 7.097478;9.284227;0.093882;, - 7.097478;9.284227;0.093882;, - 7.097478;9.284227;0.093882;, - 6.933978;9.108757;0.093882;, - 6.933978;9.108757;0.093882;, - 6.933978;9.108757;0.093882;, - 6.987667;9.412109;0.093882;, - 6.987667;9.412109;0.093882;, - 6.987667;9.412109;0.093882;, - 6.997853;9.566422;0.093882;, - 6.997853;9.566422;0.093882;, - 7.123692;9.614031;0.093882;, - 7.123692;9.614031;0.093882;, - 7.123692;9.614031;0.093882;, - 7.102638;9.295116;0.093882;, - 7.102638;9.295116;0.093882;, - 7.102638;9.295116;0.093882;, - 6.728245;9.275375;0.256563;, - 6.728245;9.275375;0.256563;, - 6.728245;9.275375;0.256563;, - 6.900592;9.282207;0.283676;, - 6.900592;9.282207;0.283676;, - 6.900592;9.282207;0.283676;, - 6.927647;9.112520;0.283676;, - 6.927647;9.112520;0.283676;, - 6.927647;9.112520;0.283676;, - 6.664969;9.225002;0.243006;, - 6.664969;9.225002;0.243006;, - 6.664969;9.225002;0.243006;, - 6.664969;9.225002;0.134552;, - 6.664969;9.225002;0.134552;, - 6.664969;9.225002;0.134552;, - 6.905502;9.286638;0.283676;, - 6.905502;9.286638;0.283676;, - 6.905502;9.286638;0.283676;, - 6.996336;9.384120;0.283676;, - 6.996336;9.384120;0.283676;, - 6.996336;9.384120;0.283676;, - 7.097478;9.284227;0.283676;, - 7.097478;9.284227;0.283676;, - 7.097478;9.284227;0.283676;, - 6.933978;9.108757;0.283676;, - 6.933978;9.108757;0.283676;, - 6.933978;9.108757;0.283676;, - 6.987667;9.412109;0.283676;, - 6.987667;9.412109;0.283676;, - 6.987667;9.412109;0.283676;, - 6.997853;9.566422;0.283676;, - 6.997853;9.566422;0.283676;, - 7.123692;9.614031;0.283676;, - 7.123692;9.614031;0.283676;, - 7.123692;9.614031;0.283676;, - 7.102638;9.295116;0.283676;, - 7.102638;9.295116;0.283676;, - 7.102638;9.295116;0.283676;, - 6.751895;9.313591;0.331667;, - 6.751895;9.313591;0.331667;, - 6.751895;9.313591;0.331667;, - 6.912178;9.319603;0.304554;, - 6.912178;9.319603;0.304554;, - 6.912178;9.319603;0.304554;, - 6.937339;9.170279;0.304554;, - 6.937339;9.170279;0.304554;, - 6.937339;9.170279;0.304554;, - 6.916745;9.323501;0.304554;, - 6.916745;9.323501;0.304554;, - 6.916745;9.323501;0.304554;, - 7.001220;9.409288;0.304554;, - 7.001220;9.409288;0.304554;, - 7.001220;9.409288;0.304554;, - 7.095283;9.321381;0.304554;, - 7.095283;9.321381;0.304554;, - 7.095283;9.321381;0.304554;, - 6.943227;9.166967;0.304554;, - 6.943227;9.166967;0.304554;, - 6.943227;9.166967;0.304554;, - 6.993157;9.433917;0.304554;, - 6.993157;9.433917;0.304554;, - 6.993157;9.433917;0.304554;, - 7.002631;9.569713;0.304554;, - 7.002631;9.569713;0.304554;, - 7.119660;9.611607;0.304554;, - 7.119660;9.611607;0.304554;, - 7.119660;9.611607;0.304554;, - 7.100082;9.330963;0.304554;, - 7.100082;9.330963;0.304554;, - 7.100082;9.330963;0.304554;, - 6.751895;9.313591;0.467235;, - 6.751895;9.313591;0.467235;, - 6.751895;9.313591;0.467235;, - 6.912178;9.319603;0.494348;, - 6.912178;9.319603;0.494348;, - 6.912178;9.319603;0.494348;, - 6.937339;9.170279;0.494348;, - 6.937339;9.170279;0.494348;, - 6.937339;9.170279;0.494348;, - 6.693048;9.269262;0.453678;, - 6.693048;9.269262;0.453678;, - 6.693048;9.269262;0.453678;, - 6.693048;9.269262;0.345224;, - 6.693048;9.269262;0.345224;, - 6.693048;9.269262;0.345224;, - 6.916745;9.323501;0.494348;, - 6.916745;9.323501;0.494348;, - 6.916745;9.323501;0.494348;, - 7.001220;9.409288;0.494348;, - 7.001220;9.409288;0.494348;, - 7.001220;9.409288;0.494348;, - 7.095283;9.321381;0.494348;, - 7.095283;9.321381;0.494348;, - 7.095283;9.321381;0.494348;, - 6.943227;9.166967;0.494348;, - 6.943227;9.166967;0.494348;, - 6.943227;9.166967;0.494348;, - 6.993157;9.433917;0.494348;, - 6.993157;9.433917;0.494348;, - 6.993157;9.433917;0.494348;, - 7.002631;9.569713;0.494348;, - 7.002631;9.569713;0.494348;, - 7.119660;9.611607;0.494348;, - 7.119660;9.611607;0.494348;, - 7.119660;9.611607;0.494348;, - 7.100082;9.330963;0.494348;, - 7.100082;9.330963;0.494348;, - 7.100082;9.330963;0.494348;, - 6.728245;9.275375;-0.089676;, - 6.728245;9.275375;-0.089676;, - 6.728245;9.275375;-0.089676;, - 6.900592;9.282207;-0.116790;, - 6.900592;9.282207;-0.116790;, - 6.900592;9.282207;-0.116790;, - 6.927647;9.112520;-0.116790;, - 6.927647;9.112520;-0.116790;, - 6.927647;9.112520;-0.116790;, - 6.905502;9.286638;-0.116790;, - 6.905502;9.286638;-0.116790;, - 6.905502;9.286638;-0.116790;, - 6.996336;9.384120;-0.116790;, - 6.996336;9.384120;-0.116790;, - 6.996336;9.384120;-0.116790;, - 7.097478;9.284227;-0.116790;, - 7.097478;9.284227;-0.116790;, - 7.097478;9.284227;-0.116790;, - 6.933978;9.108757;-0.116790;, - 6.933978;9.108757;-0.116790;, - 6.933978;9.108757;-0.116790;, - 6.987667;9.412109;-0.116790;, - 6.987667;9.412109;-0.116790;, - 6.987667;9.412109;-0.116790;, - 6.997853;9.566422;-0.116790;, - 6.997853;9.566422;-0.116790;, - 7.123692;9.614031;-0.116790;, - 7.123692;9.614031;-0.116790;, - 7.123692;9.614031;-0.116790;, - 7.102638;9.295116;-0.116790;, - 7.102638;9.295116;-0.116790;, - 7.102638;9.295116;-0.116790;, - 6.728245;9.275375;0.045891;, - 6.728245;9.275375;0.045891;, - 6.728245;9.275375;0.045891;, - 6.900592;9.282207;0.073004;, - 6.900592;9.282207;0.073004;, - 6.900592;9.282207;0.073004;, - 6.927647;9.112520;0.073004;, - 6.927647;9.112520;0.073004;, - 6.927647;9.112520;0.073004;, - 6.664969;9.225002;0.032334;, - 6.664969;9.225002;0.032334;, - 6.664969;9.225002;0.032334;, - 6.664969;9.225002;-0.076120;, - 6.664969;9.225002;-0.076120;, - 6.664969;9.225002;-0.076120;, - 6.905502;9.286638;0.073004;, - 6.905502;9.286638;0.073004;, - 6.905502;9.286638;0.073004;, - 6.996336;9.384120;0.073004;, - 6.996336;9.384120;0.073004;, - 6.996336;9.384120;0.073004;, - 7.097478;9.284227;0.073004;, - 7.097478;9.284227;0.073004;, - 7.097478;9.284227;0.073004;, - 6.933978;9.108757;0.073004;, - 6.933978;9.108757;0.073004;, - 6.933978;9.108757;0.073004;, - 6.987667;9.412109;0.073004;, - 6.987667;9.412109;0.073004;, - 6.987667;9.412109;0.073004;, - 6.997853;9.566422;0.073004;, - 6.997853;9.566422;0.073004;, - 7.123692;9.614031;0.073004;, - 7.123692;9.614031;0.073004;, - 7.123692;9.614031;0.073004;, - 7.102638;9.295116;0.073004;, - 7.102638;9.295116;0.073004;, - 7.102638;9.295116;0.073004;, - 1.567670;5.483616;0.004405;, - 1.567670;5.483616;0.004405;, - 1.567670;5.404343;-0.032080;, - 1.567670;5.325069;0.004405;, - 1.567670;5.325069;0.004405;, - 1.567670;5.292233;0.092487;, - 0.832316;5.483616;0.004405;, - 0.832316;5.483616;0.004405;, - 0.832316;5.404343;-0.032080;, - 0.832316;5.325069;0.004405;, - 0.832316;5.325069;0.004405;, - 0.832316;5.292233;0.092487;, - 0.096963;5.483616;0.004405;, - 0.096963;5.483616;0.004405;, - 0.096963;5.404343;-0.032080;, - 0.096963;5.325069;0.004405;, - 0.096963;5.325069;0.004405;, - 0.096963;5.292233;0.092487;, - 1.567670;5.516453;0.092487;, - 0.832316;5.516453;0.092487;, - 0.096963;5.516453;0.092487;, - 1.567670;5.483616;0.180569;, - 1.567670;5.483616;0.180569;, - 1.567670;5.404343;0.217054;, - 1.567670;5.325069;0.180569;, - 1.567670;5.325069;0.180569;, - 0.832316;5.404343;0.217054;, - 0.832316;5.483616;0.180569;, - 0.832316;5.483616;0.180569;, - 0.832316;5.325069;0.180569;, - 0.832316;5.325069;0.180569;, - 0.096963;5.483616;0.180569;, - 0.096963;5.483616;0.180569;, - 0.096963;5.404343;0.217054;, - 0.096963;5.325069;0.180569;, - 0.096963;5.325069;0.180569;, - 1.567670;6.178721;-0.218650;, - 1.567670;6.178721;-0.218650;, - 1.567670;5.914475;-0.340266;, - 1.567670;5.650230;-0.218650;, - 1.567670;5.650230;-0.218650;, - 1.567670;5.540776;0.074957;, - 0.832316;6.178721;-0.218650;, - 0.832316;6.178721;-0.218650;, - 0.832316;5.914475;-0.340266;, - 0.832316;5.650230;-0.218650;, - 0.832316;5.650230;-0.218650;, - 0.832316;5.540776;0.074957;, - 0.096963;6.178721;-0.218650;, - 0.096963;6.178721;-0.218650;, - 0.096963;5.914475;-0.340266;, - 0.096963;5.650230;-0.218650;, - 0.096963;5.650230;-0.218650;, - 0.096963;5.540776;0.074957;, - 1.567670;6.288176;0.074957;, - 0.832316;6.288176;0.074957;, - 0.096963;6.288176;0.074957;, - 1.567670;6.178721;0.368563;, - 1.567670;6.178721;0.368563;, - 1.567670;5.914475;0.490179;, - 1.567670;5.650230;0.368563;, - 1.567670;5.650230;0.368563;, - 0.832316;5.914475;0.490179;, - 0.832316;6.178721;0.368563;, - 0.832316;6.178721;0.368563;, - 0.832316;5.650230;0.368563;, - 0.832316;5.650230;0.368563;, - 0.096963;6.178721;0.368563;, - 0.096963;6.178721;0.368563;, - 0.096963;5.914475;0.490179;, - 0.096963;5.650230;0.368563;, - 0.096963;5.650230;0.368563;, - 3.694536;9.277638;0.149999;, - 3.694536;9.277638;0.149999;, - 3.694536;9.650759;0.149999;, - 3.694536;9.650759;0.149999;, - 4.152457;9.650759;0.149999;, - 4.152457;9.650759;0.149999;, - 4.152457;9.277638;0.149999;, - 4.152457;9.277638;0.149999;, - 4.332345;9.277638;0.662131;, - 4.332345;9.277638;0.662131;, - 4.332345;9.277638;0.662131;, - 4.332345;9.650759;0.662131;, - 4.332345;9.650759;0.662131;, - 4.332345;9.650759;0.662131;, - 4.406857;9.650759;0.449999;, - 4.406857;9.650759;0.449999;, - 4.406857;9.277638;0.449999;, - 4.406857;9.277638;0.449999;, - 4.332345;9.277638;0.237867;, - 4.332345;9.277638;0.237867;, - 4.332345;9.277638;0.237867;, - 4.332345;9.650759;0.237867;, - 4.332345;9.650759;0.237867;, - 4.332345;9.650759;0.237867;, - 3.514649;9.277638;0.662131;, - 3.514649;9.277638;0.662131;, - 3.514649;9.277638;0.662131;, - 3.440137;9.277638;0.449999;, - 3.440137;9.277638;0.449999;, - 3.440137;9.650759;0.449999;, - 3.440137;9.650759;0.449999;, - 3.514649;9.650759;0.662131;, - 3.514649;9.650759;0.662131;, - 3.514649;9.650759;0.662131;, - 3.514649;9.277638;0.237867;, - 3.514649;9.277638;0.237867;, - 3.514649;9.277638;0.237867;, - 3.514649;9.650759;0.237867;, - 3.514649;9.650759;0.237867;, - 3.514649;9.650759;0.237867;, - 3.694537;9.650759;0.749999;, - 3.694537;9.650759;0.749999;, - 3.694537;9.277638;0.749999;, - 3.694537;9.277638;0.749999;, - 4.152457;9.277638;0.749999;, - 4.152457;9.277638;0.749999;, - 4.152457;9.650759;0.749999;, - 4.152457;9.650759;0.749999;, - 3.348027;9.908371;-0.050170;, - 3.460232;9.972371;0.029085;, - 3.460232;9.972371;0.029085;, - 3.460232;9.972371;0.029085;, - 3.349367;10.036371;0.029811;, - 3.349367;10.036371;0.029811;, - 3.349367;10.036371;0.029811;, - 3.460232;9.844371;0.029085;, - 3.460232;9.844371;0.029085;, - 3.460232;9.844371;0.029085;, - 3.349367;9.780371;0.029811;, - 3.349367;9.780371;0.029811;, - 3.349367;9.780371;0.029811;, - 3.238502;9.844371;0.030537;, - 3.238502;9.844371;0.030537;, - 3.238502;9.844371;0.030537;, - 3.238502;9.972371;0.030537;, - 3.238502;9.972371;0.030537;, - 3.238502;9.972371;0.030537;, - 3.363439;10.036371;0.869615;, - 3.363439;10.036371;0.869615;, - 3.363439;10.036371;0.869615;, - 3.474304;9.972371;0.868889;, - 3.474304;9.972371;0.868889;, - 3.474304;9.972371;0.868889;, - 3.474304;9.844371;0.868889;, - 3.474304;9.844371;0.868889;, - 3.474304;9.844371;0.868889;, - 3.363439;9.780371;0.869615;, - 3.363439;9.780371;0.869615;, - 3.363439;9.780371;0.869615;, - 3.252574;9.844371;0.870341;, - 3.252574;9.844371;0.870341;, - 3.252574;9.844371;0.870341;, - 3.252574;9.972371;0.870341;, - 3.252574;9.972371;0.870341;, - 3.252574;9.972371;0.870341;, - 3.364779;9.908371;0.949597;, - 4.548027;9.908371;-0.030170;, - 4.660232;9.972371;0.049085;, - 4.660232;9.972371;0.049085;, - 4.660232;9.972371;0.049085;, - 4.549367;10.036371;0.049811;, - 4.549367;10.036371;0.049811;, - 4.549367;10.036371;0.049811;, - 4.660232;9.844371;0.049085;, - 4.660232;9.844371;0.049085;, - 4.660232;9.844371;0.049085;, - 4.549367;9.780371;0.049811;, - 4.549367;9.780371;0.049811;, - 4.549367;9.780371;0.049811;, - 4.438502;9.844371;0.050537;, - 4.438502;9.844371;0.050537;, - 4.438502;9.844371;0.050537;, - 4.438502;9.972371;0.050537;, - 4.438502;9.972371;0.050537;, - 4.438502;9.972371;0.050537;, - 4.563439;10.036371;0.889615;, - 4.563439;10.036371;0.889615;, - 4.563439;10.036371;0.889615;, - 4.674304;9.972371;0.888889;, - 4.674304;9.972371;0.888889;, - 4.674304;9.972371;0.888889;, - 4.674304;9.844371;0.888889;, - 4.674304;9.844371;0.888889;, - 4.674304;9.844371;0.888889;, - 4.563439;9.780371;0.889615;, - 4.563439;9.780371;0.889615;, - 4.563439;9.780371;0.889615;, - 4.452574;9.844371;0.890341;, - 4.452574;9.844371;0.890341;, - 4.452574;9.844371;0.890341;, - 4.452574;9.972371;0.890341;, - 4.452574;9.972371;0.890341;, - 4.452574;9.972371;0.890341;, - 4.564779;9.908371;0.969597;, - -2.707828;4.823319;-0.707269;, - -2.707828;4.823319;-0.707269;, - -2.707828;5.246544;-1.134769;, - -2.707828;5.246544;-1.134769;, - -2.873270;4.936180;-0.707269;, - -2.873270;4.936180;-0.707269;, - -2.873270;4.936180;-0.707269;, - -2.873270;5.246544;-1.030269;, - -2.873270;5.246544;-1.030269;, - -2.873270;5.246544;-1.030269;, - -2.211500;4.823319;-0.707269;, - -2.211500;4.823319;-0.707269;, - -2.211500;4.823319;-0.707269;, - -2.211500;5.246544;-1.134769;, - -2.211500;5.246544;-1.134769;, - -2.211500;5.246544;-1.134769;, - -2.707828;6.629079;-0.659769;, - -2.707828;6.629079;-0.659769;, - -2.873270;6.516219;-0.612269;, - -2.873270;6.516219;-0.612269;, - -2.873270;6.516219;-0.612269;, - -2.211500;6.629079;-0.659769;, - -2.211500;6.629079;-0.659769;, - -2.211500;6.629079;-0.659769;, - -2.707828;4.823319;1.192731;, - -2.707828;4.823319;1.192731;, - -2.707828;5.133684;1.430231;, - -2.707828;5.133684;1.430231;, - -2.873270;5.133684;1.335231;, - -2.873270;5.133684;1.335231;, - -2.873270;4.936180;1.192731;, - -2.873270;4.936180;1.192731;, - -2.873270;4.936180;1.192731;, - -2.873270;4.936180;1.192731;, - -2.211500;5.133684;1.430231;, - -2.211500;5.133684;1.430231;, - -2.211500;5.133684;1.430231;, - -2.211500;4.823319;1.192731;, - -2.211500;4.823319;1.192731;, - -2.211500;4.823319;1.192731;, - -2.654750;5.518734;1.240231;, - -2.654750;5.518734;1.591731;, - -2.654750;5.518734;1.591731;, - -2.707828;6.629079;1.430231;, - -2.707828;6.629079;1.430231;, - -2.707828;6.629079;1.430231;, - -2.707828;6.629079;1.430231;, - -2.873270;6.516219;1.335231;, - -2.873270;6.516219;1.335231;, - -2.873270;6.516219;1.335231;, - -2.604665;5.639649;1.240231;, - -2.604665;5.639649;1.240231;, - -2.604665;5.639649;1.591731;, - -2.604665;5.639649;1.591731;, - -2.604665;5.639649;1.591731;, - -2.483750;5.689734;1.591731;, - -2.483750;5.689734;1.591731;, - -2.483750;5.689734;1.240231;, - -2.604665;5.397819;1.240231;, - -2.604665;5.397819;1.240231;, - -2.604665;5.397819;1.591731;, - -2.604665;5.397819;1.591731;, - -2.604665;5.397819;1.591731;, - -2.483750;5.347734;1.240231;, - -2.483750;5.347734;1.591731;, - -2.483750;5.347734;1.591731;, - -2.362835;5.397819;1.240231;, - -2.362835;5.397819;1.240231;, - -2.362835;5.397819;1.591731;, - -2.362835;5.397819;1.591731;, - -2.362835;5.397819;1.591731;, - -2.312750;5.518734;1.240231;, - -2.312750;5.518734;1.591731;, - -2.312750;5.518734;1.591731;, - -2.362835;5.639649;1.240231;, - -2.362835;5.639649;1.240231;, - -2.362835;5.639649;1.591731;, - -2.362835;5.639649;1.591731;, - -2.362835;5.639649;1.591731;, - -2.483750;5.518734;1.591731;, - -2.211500;6.629079;1.430231;, - -2.211500;6.629079;1.430231;, - -2.211500;6.629079;1.430231;, - -2.654750;6.378734;1.240231;, - -2.654750;6.378734;1.591731;, - -2.654750;6.378734;1.591731;, - -2.604665;6.499649;1.240231;, - -2.604665;6.499649;1.240231;, - -2.604665;6.499649;1.591731;, - -2.604665;6.499649;1.591731;, - -2.604665;6.499649;1.591731;, - -2.483750;6.549734;1.591731;, - -2.483750;6.549734;1.591731;, - -2.483750;6.549734;1.240231;, - -2.604665;6.257819;1.240231;, - -2.604665;6.257819;1.240231;, - -2.604665;6.257819;1.591731;, - -2.604665;6.257819;1.591731;, - -2.604665;6.257819;1.591731;, - -2.483750;6.207734;1.240231;, - -2.483750;6.207734;1.591731;, - -2.483750;6.207734;1.591731;, - -2.362835;6.257819;1.240231;, - -2.362835;6.257819;1.240231;, - -2.362835;6.257819;1.591731;, - -2.362835;6.257819;1.591731;, - -2.362835;6.257819;1.591731;, - -2.312750;6.378734;1.240231;, - -2.312750;6.378734;1.591731;, - -2.312750;6.378734;1.591731;, - -2.362835;6.499649;1.240231;, - -2.362835;6.499649;1.240231;, - -2.362835;6.499649;1.591731;, - -2.362835;6.499649;1.591731;, - -2.362835;6.499649;1.591731;, - -2.483750;6.378734;1.591731;, - -2.654750;5.948734;1.240231;, - -2.654750;5.948734;1.591731;, - -2.654750;5.948734;1.591731;, - -2.604665;6.069649;1.240231;, - -2.604665;6.069649;1.240231;, - -2.604665;6.069649;1.591731;, - -2.604665;6.069649;1.591731;, - -2.604665;6.069649;1.591731;, - -2.483750;6.119734;1.591731;, - -2.483750;6.119734;1.591731;, - -2.483750;6.119734;1.240231;, - -2.604665;5.827818;1.240231;, - -2.604665;5.827818;1.240231;, - -2.604665;5.827818;1.591731;, - -2.604665;5.827818;1.591731;, - -2.604665;5.827818;1.591731;, - -2.483750;5.777734;1.240231;, - -2.483750;5.777734;1.591731;, - -2.483750;5.777734;1.591731;, - -2.362835;5.827818;1.240231;, - -2.362835;5.827818;1.240231;, - -2.362835;5.827818;1.591731;, - -2.362835;5.827818;1.591731;, - -2.362835;5.827818;1.591731;, - -2.312750;5.948734;1.240231;, - -2.312750;5.948734;1.591731;, - -2.312750;5.948734;1.591731;, - -2.362835;6.069649;1.240231;, - -2.362835;6.069649;1.240231;, - -2.362835;6.069649;1.591731;, - -2.362835;6.069649;1.591731;, - -2.362835;6.069649;1.591731;, - -2.483750;5.948734;1.591731;, - 2.707828;4.823319;-0.707269;, - 2.707828;4.823319;-0.707269;, - 2.707828;5.246544;-1.134769;, - 2.707828;5.246544;-1.134769;, - 2.873270;4.936180;-0.707269;, - 2.873270;4.936180;-0.707269;, - 2.873270;4.936180;-0.707269;, - 2.873270;5.246544;-1.030269;, - 2.873270;5.246544;-1.030269;, - 2.873270;5.246544;-1.030269;, - 2.211500;4.823319;-0.707269;, - 2.211500;4.823319;-0.707269;, - 2.211500;4.823319;-0.707269;, - 2.211500;5.246544;-1.134769;, - 2.211500;5.246544;-1.134769;, - 2.211500;5.246544;-1.134769;, - 2.707828;6.629079;-0.659769;, - 2.707828;6.629079;-0.659769;, - 2.873270;6.516219;-0.612269;, - 2.873270;6.516219;-0.612269;, - 2.873270;6.516219;-0.612269;, - 2.211500;6.629079;-0.659769;, - 2.211500;6.629079;-0.659769;, - 2.211500;6.629079;-0.659769;, - 2.707828;4.823319;1.192731;, - 2.707828;4.823319;1.192731;, - 2.707828;5.133684;1.430231;, - 2.707828;5.133684;1.430231;, - 2.873270;5.133684;1.335231;, - 2.873270;5.133684;1.335231;, - 2.873270;4.936180;1.192731;, - 2.873270;4.936180;1.192731;, - 2.873270;4.936180;1.192731;, - 2.873270;4.936180;1.192731;, - 2.211500;5.133684;1.430231;, - 2.211500;5.133684;1.430231;, - 2.211500;5.133684;1.430231;, - 2.211500;4.823319;1.192731;, - 2.211500;4.823319;1.192731;, - 2.211500;4.823319;1.192731;, - 2.654750;5.518734;1.240231;, - 2.654750;5.518734;1.591731;, - 2.654750;5.518734;1.591731;, - 2.707828;6.629079;1.430231;, - 2.707828;6.629079;1.430231;, - 2.707828;6.629079;1.430231;, - 2.707828;6.629079;1.430231;, - 2.873270;6.516219;1.335231;, - 2.873270;6.516219;1.335231;, - 2.873270;6.516219;1.335231;, - 2.604665;5.639649;1.240231;, - 2.604665;5.639649;1.240231;, - 2.604665;5.639649;1.591731;, - 2.604665;5.639649;1.591731;, - 2.604665;5.639649;1.591731;, - 2.483750;5.689734;1.591731;, - 2.483750;5.689734;1.591731;, - 2.483750;5.689734;1.240231;, - 2.604665;5.397819;1.240231;, - 2.604665;5.397819;1.240231;, - 2.604665;5.397819;1.591731;, - 2.604665;5.397819;1.591731;, - 2.604665;5.397819;1.591731;, - 2.483750;5.347734;1.240231;, - 2.483750;5.347734;1.591731;, - 2.483750;5.347734;1.591731;, - 2.362835;5.397819;1.240231;, - 2.362835;5.397819;1.240231;, - 2.362835;5.397819;1.591731;, - 2.362835;5.397819;1.591731;, - 2.362835;5.397819;1.591731;, - 2.312750;5.518734;1.240231;, - 2.312750;5.518734;1.591731;, - 2.312750;5.518734;1.591731;, - 2.362835;5.639649;1.240231;, - 2.362835;5.639649;1.240231;, - 2.362835;5.639649;1.591731;, - 2.362835;5.639649;1.591731;, - 2.362835;5.639649;1.591731;, - 2.483750;5.518734;1.591731;, - 2.211500;6.629079;1.430231;, - 2.211500;6.629079;1.430231;, - 2.211500;6.629079;1.430231;, - 2.654750;6.378734;1.240231;, - 2.654750;6.378734;1.591731;, - 2.654750;6.378734;1.591731;, - 2.604665;6.499649;1.240231;, - 2.604665;6.499649;1.240231;, - 2.604665;6.499649;1.591731;, - 2.604665;6.499649;1.591731;, - 2.604665;6.499649;1.591731;, - 2.483750;6.549734;1.591731;, - 2.483750;6.549734;1.591731;, - 2.483750;6.549734;1.240231;, - 2.604665;6.257819;1.240231;, - 2.604665;6.257819;1.240231;, - 2.604665;6.257819;1.591731;, - 2.604665;6.257819;1.591731;, - 2.604665;6.257819;1.591731;, - 2.483750;6.207734;1.240231;, - 2.483750;6.207734;1.591731;, - 2.483750;6.207734;1.591731;, - 2.362835;6.257819;1.240231;, - 2.362835;6.257819;1.240231;, - 2.362835;6.257819;1.591731;, - 2.362835;6.257819;1.591731;, - 2.362835;6.257819;1.591731;, - 2.312750;6.378734;1.240231;, - 2.312750;6.378734;1.591731;, - 2.312750;6.378734;1.591731;, - 2.362835;6.499649;1.240231;, - 2.362835;6.499649;1.240231;, - 2.362835;6.499649;1.591731;, - 2.362835;6.499649;1.591731;, - 2.362835;6.499649;1.591731;, - 2.483750;6.378734;1.591731;, - 2.654750;5.948734;1.240231;, - 2.654750;5.948734;1.591731;, - 2.654750;5.948734;1.591731;, - 2.604665;6.069649;1.240231;, - 2.604665;6.069649;1.240231;, - 2.604665;6.069649;1.591731;, - 2.604665;6.069649;1.591731;, - 2.604665;6.069649;1.591731;, - 2.483750;6.119734;1.591731;, - 2.483750;6.119734;1.591731;, - 2.483750;6.119734;1.240231;, - 2.604665;5.827818;1.240231;, - 2.604665;5.827818;1.240231;, - 2.604665;5.827818;1.591731;, - 2.604665;5.827818;1.591731;, - 2.604665;5.827818;1.591731;, - 2.483750;5.777734;1.240231;, - 2.483750;5.777734;1.591731;, - 2.483750;5.777734;1.591731;, - 2.362835;5.827818;1.240231;, - 2.362835;5.827818;1.240231;, - 2.362835;5.827818;1.591731;, - 2.362835;5.827818;1.591731;, - 2.362835;5.827818;1.591731;, - 2.312750;5.948734;1.240231;, - 2.312750;5.948734;1.591731;, - 2.312750;5.948734;1.591731;, - 2.362835;6.069649;1.240231;, - 2.362835;6.069649;1.240231;, - 2.362835;6.069649;1.591731;, - 2.362835;6.069649;1.591731;, - 2.362835;6.069649;1.591731;, - 2.483750;5.948734;1.591731;, - 0.000000;9.716153;1.400000;, - 0.000000;9.840000;1.400000;, - -0.306190;11.237254;0.797501;, - 0.000000;11.237254;0.797501;, - 0.306190;11.237254;0.797501;, - 0.000000;9.731160;1.943483;, - 0.000000;9.755640;2.960000;, - 0.000000;9.770000;3.220000;, - 0.000000;9.770000;3.220000;, - 0.000000;10.370001;2.115000;, - 0.000000;10.370001;3.103000;, - 0.000000;10.300000;3.220000;, - 0.000000;10.300000;3.220000;; - 4816; - 3;5614,5579,5576;, - 3;1063,1747,1729;, - 3;1068,1035,1038;, - 3;1064,1705,1041;, - 3;1074,1152,1162;, - 3;1045,1042,1154;, - 3;1042,1745,1154;, - 3;1069,1046,1066;, - 3;1039,1042,1045;, - 3;1071,1043,1036;, - 3;1070,1063,1072;, - 3;1066,1044,1074;, - 3;1066,1162,1158;, - 3;1163,1155,1159;, - 3;1046,1152,1044;, - 3;1746,1160,1156;, - 3;1047,0,1;, - 3;740,2279,1047;, - 3;2,1936,740;, - 3;446,764,447;, - 3;762,5,765;, - 3;446,6,7;, - 3;420,737,422;, - 3;1958,1959,1961;, - 3;425,193,9;, - 3;426,766,194;, - 3;1917,737,736;, - 3;1962,766,739;, - 3;421,427,425;, - 3;738,426,423;, - 3;738,1962,739;, - 3;1918,1961,1919;, - 3;1075,1749,1751;, - 3;90,195,234;, - 3;90,234,92;, - 3;196,94,198;, - 3;91,96,95;, - 3;767,463,465;, - 3;466,468,470;, - 3;93,97,96;, - 3;470,478,472;, - 3;467,448,768;, - 3;237,195,448;, - 3;471,237,467;, - 3;238,234,237;, - 3;471,239,238;, - 3;238,235,92;, - 3;770,449,450;, - 3;199,449,197;, - 3;478,240,472;, - 3;241,236,240;, - 3;452,201,454;, - 3;202,454,201;, - 3;242,201,452;, - 3;84,201,204;, - 3;242,99,204;, - 3;204,99,84;, - 3;455,459,453;, - 3;456,205,457;, - 3;452,243,242;, - 3;202,86,206;, - 3;99,243,100;, - 3;84,100,87;, - 3;178,244,209;, - 3;180,227,184;, - 3;229,248,231;, - 3;245,214,249;, - 3;211,189,215;, - 3;185,187,181;, - 3;192,222,178;, - 3;228,229,231;, - 3;210,190,179;, - 3;209,250,216;, - 3;244,232,251;, - 3;178,186,192;, - 3;233,232,222;, - 3;192,227,233;, - 3;774,1048,741;, - 3;743,223,182;, - 3;1053,246,230;, - 3;1079,212,245;, - 3;777,188,213;, - 3;744,188,746;, - 3;224,1053,230;, - 3;747,1048,1054;, - 3;775,746,777;, - 3;1076,1053,1049;, - 3;776,1079,1077;, - 3;748,1050,745;, - 3;1055,1053,1051;, - 3;742,744,746;, - 3;72,163,166;, - 3;61,385,63;, - 3;65,137,61;, - 3;386,76,63;, - 3;431,73,77;, - 3;144,169,172;, - 3;173,434,10;, - 3;146,435,170;, - 3;145,389,147;, - 3;391,1922,436;, - 3;1874,394,1877;, - 3;1923,1878,1925;, - 3;1881,1926,1879;, - 3;1924,439,437;, - 3;1929,440,1927;, - 3;438,395,392;, - 3;442,395,441;, - 3;12,151,154;, - 3;400,1880,396;, - 3;13,1879,1882;, - 3;155,397,398;, - 3;149,396,152;, - 3;2214,2315,2318;, - 3;2218,2214,2318;, - 3;2214,1755,2215;, - 3;1758,2215,1755;, - 3;2218,1753,2214;, - 3;1164,1755,1167;, - 3;1760,6191,1754;, - 3;1765,6191,1763;, - 3;2219,1764,1761;, - 3;2223,1764,2222;, - 3;2319,2321,2323;, - 3;2327,2324,2321;, - 3;2224,2322,2226;, - 3;2316,2226,2322;, - 3;1754,1767,1756;, - 3;6192,1767,6191;, - 3;2329,2222,2325;, - 3;2219,2326,2222;, - 3;1770,2230,1772;, - 3;2220,1773,2231;, - 3;2216,2231,2227;, - 3;2229,2228,2230;, - 3;1168,1172,1165;, - 3;1757,1170,1169;, - 3;1759,1173,1773;, - 3;1767,1771,1774;, - 3;479,485,489;, - 3;1775,1176,1777;, - 3;2232,1777,2234;, - 3;1176,1178,1180;, - 3;479,1180,1178;, - 3;1182,1779,1780;, - 3;1184,1779,1183;, - 3;1780,2236,14;, - 3;1781,2236,1779;, - 3;15,1783,1784;, - 3;2240,1783,2239;, - 3;491,495,496;, - 3;495,497,500;, - 3;502,505,506;, - 3;508,506,505;, - 3;513,515,517;, - 3;514,519,515;, - 3;486,521,524;, - 3;527,519,518;, - 3;1186,495,500;, - 3;1189,495,1188;, - 3;1189,1183,1182;, - 3;1186,1183,1188;, - 3;1190,1193,1194;, - 3;1196,1193,1192;, - 3;1196,505,504;, - 3;1190,505,1192;, - 3;1197,1783,1193;, - 3;1785,1193,1783;, - 3;513,493,492;, - 3;520,522,516;, - 3;503,528,527;, - 3;1179,501,480;, - 3;480,498,481;, - 3;482,493,523;, - 3;523,517,515;, - 3;1174,1187,1179;, - 3;1776,1185,1174;, - 3;2233,1782,1776;, - 3;1181,1195,1177;, - 3;1177,1786,1778;, - 3;1778,2241,2235;, - 3;490,1191,1181;, - 3;487,509,490;, - 3;525,510,488;, - 3;519,507,525;, - 3;1198,1789,1200;, - 3;1787,1794,1790;, - 3;1204,1795,1792;, - 3;1210,1212,1213;, - 3;1201,1796,1206;, - 3;1199,1211,1210;, - 3;1199,1213,1205;, - 3;1213,1207,1205;, - 3;1202,1212,1211;, - 3;1214,2244,1216;, - 3;1214,1220,1223;, - 3;1221,1228,1224;, - 3;2245,1230,1217;, - 3;2242,1232,2247;, - 3;1217,2246,1230;, - 3;2242,1232,2247;, - 3;1215,1229,1232;, - 3;1231,1222,1218;, - 3;2248,2333,16;, - 3;2331,17,2334;, - 3;2249,2335,2331;, - 3;78,68,64;, - 3;82,167,174;, - 3;164,175,168;, - 3;428,176,165;, - 3;387,445,432;, - 3;401,138,156;, - 3;156,141,157;, - 3;158,66,69;, - 3;62,70,67;, - 3;64,71,62;, - 3;74,80,79;, - 3;432,444,428;, - 3;1081,19,20;, - 3;21,1082,1081;, - 3;2108,1797,1749;, - 3;24,1751,1799;, - 3;469,529,478;, - 3;771,476,463;, - 3;94,218,198;, - 3;96,102,95;, - 3;241,529,252;, - 3;458,25,459;, - 3;207,461,458;, - 3;88,220,208;, - 3;101,89,88;, - 3;464,474,468;, - 3;97,104,96;, - 3;241,105,98;, - 3;1750,1800,1752;, - 3;451,219,462;, - 3;451,779,772;, - 3;1963,1967,1968;, - 3;1968,2109,2110;, - 3;2111,2109,2113;, - 3;1964,2114,1965;, - 3;1937,1968,1939;, - 3;1939,2110,2081;, - 3;2081,2111,2082;, - 3;1938,2112,1964;, - 3;1884,2256,2257;, - 3;1931,2263,1934;, - 3;1932,2258,2261;, - 3;1889,1885,2259;, - 3;2263,2260,2256;, - 3;1935,1890,1933;, - 3;159,1889,161;, - 3;27,1891,1892;, - 3;28,1886,160;, - 3;1552,1554,1557;, - 3;916,1626,1554;, - 3;980,1631,1626;, - 3;1558,1560,1553;, - 3;1555,1559,1558;, - 3;1627,1561,1556;, - 3;1632,1633,1628;, - 3;1632,1636,1635;, - 3;1629,983,1636;, - 3;981,919,984;, - 3;917,1560,920;, - 3;1563,1567,921;, - 3;921,1637,985;, - 3;985,1640,1642;, - 3;1565,1560,1559;, - 3;1568,1559,1562;, - 3;1638,1561,1634;, - 3;1641,1633,1635;, - 3;1641,1636,1643;, - 3;1643,983,986;, - 3;987,919,922;, - 3;923,1560,1564;, - 3;1570,1575,1577;, - 3;1580,1575,1573;, - 3;1578,1588,1571;, - 3;1583,924,926;, - 3;1446,1452,1454;, - 3;1456,1452,1459;, - 3;1449,1590,1592;, - 3;1460,930,1457;, - 3;925,1591,931;, - 3;1588,1592,1590;, - 3;1586,928,1593;, - 3;926,930,929;, - 3;852,793,796;, - 3;1341,1981,1984;, - 3;2013,1462,1464;, - 3;876,880,882;, - 3;880,1469,1472;, - 3;794,1436,1348;, - 3;1351,795,1349;, - 3;877,1470,1467;, - 3;1471,1481,1473;, - 3;2017,1478,1462;, - 3;1439,1982,1345;, - 3;1437,1346,1350;, - 3;1350,1342,1352;, - 3;1483,1463,1479;, - 3;1474,1480,1471;, - 3;884,887,889;, - 3;2018,2022,2024;, - 3;1487,886,885;, - 3;1488,1494,1489;, - 3;2025,1495,1492;, - 3;852,886,854;, - 3;2020,1983,2022;, - 3;1490,1497,886;, - 3;855,1497,1436;, - 3;1496,1498,1491;, - 3;1438,1499,1440;, - 3;2023,1500,1495;, - 3;1439,2023,1982;, - 3;882,884,889;, - 3;880,1487,885;, - 3;1473,1493,1488;, - 3;1482,2025,1492;, - 3;2017,2018,2024;, - 3;856,804,858;, - 3;1355,1992,1359;, - 3;2026,1504,2029;, - 3;891,897,1506;, - 3;897,1510,1506;, - 3;805,1442,859;, - 3;1365,806,800;, - 3;892,1511,1513;, - 3;1512,1517,1519;, - 3;2029,1520,1518;, - 3;1444,1360,1993;, - 3;1443,1361,1445;, - 3;1362,1356,1361;, - 3;1522,1505,1501;, - 3;1514,1519,1523;, - 3;899,903,905;, - 3;2030,2034,2036;, - 3;1526,905,1528;, - 3;1527,1531,1534;, - 3;2032,1532,2035;, - 3;856,905,903;, - 3;2036,1994,1988;, - 3;1528,905,1536;, - 3;859,1536,905;, - 3;1533,1537,1539;, - 3;1443,1540,1538;, - 3;2035,1532,1541;, - 3;1444,2035,1541;, - 3;895,899,898;, - 3;897,1526,1508;, - 3;1509,1534,1517;, - 3;1518,2032,2029;, - 3;2029,2030,2026;, - 3;904,890,888;, - 3;901,883,890;, - 3;896,878,883;, - 3;893,1475,879;, - 3;1515,1484,1476;, - 3;1524,1465,1485;, - 3;1502,2014,1465;, - 3;2027,2019,2015;, - 3;2031,2021,2019;, - 3;2037,1985,2021;, - 3;1989,1343,1986;, - 3;1357,1353,1344;, - 3;1366,797,1354;, - 3;801,853,798;, - 3;857,888,853;, - 3;1138,1133,1142;, - 3;1009,988,990;, - 3;1009,1018,1012;, - 3;1139,1144,1145;, - 3;993,988,996;, - 3;999,1148,1021;, - 3;1022,999,1021;, - 3;1144,1027,1145;, - 3;1019,1027,1024;, - 3;1119,932,934;, - 3;937,934,932;, - 3;1148,1029,1021;, - 3;1021,1031,1022;, - 3;1033,989,1013;, - 3;1033,1020,1025;, - 3;1120,1126,1121;, - 3;1133,1126,1125;, - 3;939,941,945;, - 3;994,946,942;, - 3;948,1004,1005;, - 3;1000,1005,1004;, - 3;950,940,947;, - 3;997,950,947;, - 3;999,1136,1134;, - 3;951,1136,1008;, - 3;951,1004,948;, - 3;999,1004,1008;, - 3;940,953,935;, - 3;989,953,950;, - 3;1149,1131,1140;, - 3;1023,991,1001;, - 3;1030,1146,1028;, - 3;1150,1141,1147;, - 3;1022,1014,1010;, - 3;1032,1028,1015;, - 3;1006,938,949;, - 3;1007,943,1005;, - 3;1007,992,995;, - 3;1135,1127,1131;, - 3;1129,1128,1136;, - 3;952,1122,1130;, - 3;949,933,952;, - 3;1267,1288,1289;, - 3;711,1290,718;, - 3;589,718,641;, - 3;592,642,643;, - 3;594,643,644;, - 3;597,645,646;, - 3;1272,646,1291;, - 3;1270,1292,1288;, - 3;1273,1271,599;, - 3;598,1273,599;, - 3;598,599,595;, - 3;595,599,593;, - 3;593,599,590;, - 3;590,599,712;, - 3;1268,712,599;, - 3;1271,1268,599;, - 3;1320,735,402;, - 3;735,404,402;, - 3;1320,1904,735;, - 3;1320,1862,1904;, - 3;735,1906,404;, - 3;735,1904,1906;, - 3;358,402,129;, - 3;358,1320,402;, - 3;129,402,407;, - 3;369,359,130;, - 3;369,130,132;, - 3;1321,1867,1863;, - 3;1325,1867,1321;, - 3;1864,1909,1905;, - 3;1868,1909,1864;, - 3;1905,1910,1907;, - 3;1909,1910,1905;, - 3;405,1908,1911;, - 3;409,405,1911;, - 3;403,406,410;, - 3;411,403,410;, - 3;131,408,412;, - 3;133,131,412;, - 3;360,1325,1321;, - 3;370,1325,360;, - 3;412,408,403;, - 3;412,403,411;, - 3;1293,1869,1275;, - 3;1275,1869,1865;, - 3;647,600,371;, - 3;600,361,371;, - 3;648,372,1294;, - 3;1294,372,1870;, - 3;649,1295,601;, - 3;601,1295,1276;, - 3;602,1277,362;, - 3;1277,1866,362;, - 3;304,318,334;, - 3;373,365,374;, - 3;293,322,319;, - 3;304,295,294;, - 3;374,367,375;, - 3;296,603,322;, - 3;305,561,297;, - 3;573,604,562;, - 3;335,374,336;, - 3;320,366,363;, - 3;335,364,373;, - 3;336,375,650;, - 3;650,367,605;, - 3;323,368,366;, - 3;564,298,301;, - 3;302,324,327;, - 3;565,303,570;, - 3;303,607,570;, - 3;328,587,608;, - 3;299,588,325;, - 3;299,567,560;, - 3;565,570,1825;, - 3;570,1842,1825;, - 3;608,1845,1843;, - 3;560,1846,588;, - 3;560,567,1828;, - 3;566,1829,568;, - 3;1826,1847,1830;, - 3;1233,1247,1249;, - 3;1238,1249,1250;, - 3;1238,1810,1801;, - 3;1240,1812,1251;, - 3;1244,1234,1239;, - 3;1241,1235,1244;, - 3;1244,1802,1804;, - 3;1242,1244,1804;, - 3;1236,1251,1248;, - 3;1803,1813,1805;, - 3;107,253,255;, - 3;253,532,255;, - 3;254,110,257;, - 3;116,257,110;, - 3;535,260,538;, - 3;30,538,260;, - 3;533,540,541;, - 3;545,541,540;, - 3;534,261,256;, - 3;546,261,542;, - 3;256,111,108;, - 3;271,111,261;, - 3;539,530,536;, - 3;258,531,253;, - 3;543,540,539;, - 3;53,112,48;, - 3;53,50,54;, - 3;55,114,119;, - 3;118,262,112;, - 3;119,265,274;, - 3;272,266,263;, - 3;49,115,51;, - 3;113,267,115;, - 3;1594,1542,1544;, - 3;1595,958,1597;, - 3;1598,906,1543;, - 3;1596,908,955;, - 3;956,907,959;, - 3;2038,1600,1603;, - 3;2038,1603,1606;, - 3;2038,1606,1609;, - 3;1609,1644,2038;, - 3;1644,1647,2038;, - 3;1647,1600,2038;, - 3;961,962,965;, - 3;961,968,962;, - 3;961,971,968;, - 3;971,961,974;, - 3;974,961,977;, - 3;977,961,965;, - 3;963,1607,1604;, - 3;969,1610,1608;, - 3;972,1645,1611;, - 3;975,1648,1646;, - 3;978,1601,1649;, - 3;966,1605,1602;, - 3;1546,1995,1998;, - 3;1547,913,1549;, - 3;1550,860,1996;, - 3;1999,861,863;, - 3;1548,864,910;, - 3;911,862,914;, - 3;1089,1095,1097;, - 3;1099,2152,2155;, - 3;729,1896,732;, - 3;2158,2162,2165;, - 3;1894,1901,1896;, - 3;1105,866,868;, - 3;870,868,866;, - 3;1100,867,1107;, - 3;874,871,867;, - 3;1102,869,875;, - 3;869,872,875;, - 3;2156,874,1100;, - 3;2002,874,2001;, - 3;2153,875,2003;, - 3;872,2003,875;, - 3;2168,2001,2156;, - 3;2007,2001,2005;, - 3;2170,2003,2009;, - 3;2004,2009,2003;, - 3;2171,2006,2169;, - 3;2011,2006,2010;, - 3;730,873,870;, - 3;733,2004,872;, - 3;731,2002,1895;, - 3;1897,2012,2004;, - 3;1898,2011,1902;, - 3;1895,2007,1899;, - 3;1107,1111,1100;, - 3;1101,1114,1103;, - 3;1106,1115,1117;, - 3;1108,1118,1109;, - 3;2156,2175,2168;, - 3;2169,2177,2171;, - 3;2153,2178,2179;, - 3;2157,2180,2172;, - 3;1110,1098,1111;, - 3;1117,1096,1092;, - 3;1109,1093,1090;, - 3;2173,2166,2175;, - 3;2176,2163,2177;, - 3;2179,2164,2160;, - 3;1112,2181,1116;, - 3;1115,2160,1096;, - 3;1097,2161,2158;, - 3;1111,2159,2173;, - 3;1369,807,810;, - 3;1374,1378,1381;, - 3;1382,1386,1375;, - 3;1371,1386,1384;, - 3;1379,1385,1383;, - 3;808,1385,812;, - 3;1387,1393,814;, - 3;1395,814,1393;, - 3;1380,819,813;, - 3;811,813,819;, - 3;815,1376,1388;, - 3;1394,1375,1386;, - 3;1389,1374,1390;, - 3;1396,1386,1370;, - 3;816,819,815;, - 3;1397,810,817;, - 3;1398,823,1401;, - 3;1399,1404,1407;, - 3;1402,826,1405;, - 3;820,827,824;, - 3;1400,1410,821;, - 3;1408,828,1411;, - 3;1413,832,1416;, - 3;1414,1419,1422;, - 3;1417,835,1420;, - 3;829,836,833;, - 3;1415,838,830;, - 3;1423,837,839;, - 3;1425,844,1428;, - 3;1426,1430,1433;, - 3;1428,846,1431;, - 3;841,847,845;, - 3;1427,849,842;, - 3;1434,848,850;, - 3;927,1586,1584;, - 3;1576,1586,1579;, - 3;1584,1586,1576;, - 3;925,1581,1589;, - 3;1581,1574,1589;, - 3;1574,1572,1589;, - 3;928,1450,1593;, - 3;928,1461,1453;, - 3;928,1453,1450;, - 3;931,1591,1458;, - 3;1455,1591,1447;, - 3;1458,1591,1455;, - 3;1670,1674,1676;, - 3;1650,1676,1653;, - 3;1656,1654,1659;, - 3;1678,1660,1680;, - 3;1678,1682,1684;, - 3;1707,1713,1716;, - 3;1717,1686,1688;, - 3;1690,1672,1671;, - 3;1690,1671,1651;, - 3;1690,1651,1657;, - 3;1690,1657,1679;, - 3;1679,1685,1690;, - 3;1685,1719,1690;, - 3;1719,1723,1690;, - 3;1723,1672,1690;, - 3;1691,1675,1724;, - 3;1691,1724,1725;, - 3;1691,1725,1683;, - 3;1691,1683,1681;, - 3;1681,1661,1691;, - 3;1661,1655,1691;, - 3;1655,1677,1691;, - 3;1677,1675,1691;, - 3;1708,1726,1710;, - 3;1711,1724,1714;, - 3;1709,1723,1719;, - 3;1714,1675,1687;, - 3;1688,1674,1673;, - 3;1718,1672,1723;, - 3;2264,2280,2281;, - 3;2266,2285,2280;, - 3;2264,2287,2269;, - 3;2271,2274,2276;, - 3;2277,2289,2290;, - 3;2290,2292,2294;, - 3;2295,2298,2299;, - 3;2299,2301,2302;, - 3;2084,1940,1942;, - 3;2273,1943,1941;, - 3;2302,2088,2085;, - 3;2265,2276,2267;, - 3;2282,2300,2303;, - 3;2268,2291,2283;, - 3;2283,2296,2286;, - 3;2285,2300,2280;, - 3;2287,2303,2086;, - 3;2270,2087,1944;, - 3;2264,1945,2272;, - 3;571,1278,609;, - 3;268,1266,571;, - 3;1266,1848,1278;, - 3;1245,1831,1266;, - 3;610,575,572;, - 3;1279,652,611;, - 3;1849,1296,1279;, - 3;1832,1851,1850;, - 3;1807,1833,1832;, - 3;1246,1814,1808;, - 3;1252,269,276;, - 3;277,572,575;, - 3;612,715,615;, - 3;612,1322,713;, - 3;618,1282,1285;, - 3;618,626,621;, - 3;1285,612,618;, - 3;629,635,638;, - 3;330,639,332;, - 3;623,632,630;, - 3;619,636,633;, - 3;616,637,613;, - 3;616,333,640;, - 3;623,630,331;, - 3;714,720,716;, - 3;1280,1326,1323;, - 3;717,654,617;, - 3;622,656,658;, - 3;1283,1300,1286;, - 3;624,657,627;, - 3;332,340,330;, - 3;1287,1297,1280;, - 3;1324,719,714;, - 3;622,1298,1284;, - 3;331,659,623;, - 3;616,338,333;, - 3;1712,1720,1707;, - 3;1727,1684,1682;, - 3;2115,2120,2122;, - 3;2122,2341,2344;, - 3;2348,2399,2401;, - 3;2124,2338,2126;, - 3;2336,2407,2338;, - 3;2400,2405,2402;, - 3;2304,2345,2354;, - 3;2339,2406,2337;, - 3;2127,2123,2304;, - 3;2128,2337,2125;, - 3;2357,2403,2410;, - 3;2408,2404,2406;, - 3;2306,2118,2129;, - 3;2121,2358,2342;, - 3;2308,2409,2340;, - 3;2305,2360,2308;, - 3;2340,2131,2308;, - 3;2308,2127,2305;, - 3;2346,2350,2348;, - 3;2342,2358,2351;, - 3;2409,2357,2410;, - 3;2355,2357,2360;, - 3;2125,2132,2128;, - 3;2127,2133,2116;, - 3;2347,2357,2356;, - 3;6189,2307,2130;, - 3;6190,2338,6198;, - 3;6198,2407,6199;, - 3;6194,2359,2307;, - 3;6199,2400,6200;, - 3;6196,2399,2352;, - 3;6195,2353,2359;, - 3;2361,2366,2369;, - 3;2362,2371,2363;, - 3;2364,2373,2367;, - 3;2370,2374,32;, - 3;2375,2378,2380;, - 3;2376,2381,2383;, - 3;2309,2380,33;, - 3;2310,2375,2309;, - 3;2386,2384,2382;, - 3;2391,2393,2395;, - 3;2391,2388,2387;, - 3;2312,2382,2311;, - 3;2314,2392,2391;, - 3;2314,2387,2313;, - 3;2385,2379,2377;, - 3;2398,2396,2394;, - 3;2398,2385,2389;, - 3;934,1731,1119;, - 3;1120,1733,1125;, - 3;1125,1737,1133;, - 3;1133,1739,1142;, - 3;1143,1741,1144;, - 3;1144,1692,1024;, - 3;1694,1026,1693;, - 3;1002,1694,1662;, - 3;954,1662,1614;, - 3;936,1614,1612;, - 3;2197,1738,2191;, - 3;2065,1663,1695;, - 3;2065,1697,2068;, - 3;2198,1744,1742;, - 3;2054,1663,2051;, - 3;2057,2204,2193;, - 3;2073,2057,2058;, - 3;1744,2075,1700;, - 3;1698,2075,2069;, - 3;1734,2039,2182;, - 3;2041,1615,1618;, - 3;2204,2077,2206;, - 3;2072,2079,2077;, - 3;1703,1664,1668;, - 3;1703,1699,1696;, - 3;1735,2186,1736;, - 3;1738,2186,2191;, - 3;1618,2043,2041;, - 3;2055,1620,1665;, - 3;2047,2060,2062;, - 3;2058,2060,2063;, - 3;1623,1621,1619;, - 3;1666,1623,1664;, - 3;2057,2195,2064;, - 3;2049,2195,2189;, - 3;2049,2062,2064;, - 3;2057,2062,2058;, - 3;1619,1624,1623;, - 3;1664,1624,1668;, - 3;2205,2192,2194;, - 3;2074,2052,2066;, - 3;2078,2201,2207;, - 3;2206,2199,2204;, - 3;2073,2070,2079;, - 3;2080,2076,2078;, - 3;2061,2042,2044;, - 3;2063,2045,2056;, - 3;2063,2053,2058;, - 3;2194,2187,2196;, - 3;2189,2188,2183;, - 3;2050,2184,2040;, - 3;2048,2040,2042;, - 3;1615,1731,1613;, - 3;1735,1733,1732;, - 3;1736,1737,1733;, - 3;1738,1739,1737;, - 3;1742,1741,1740;, - 3;1744,1692,1741;, - 3;1694,1701,1704;, - 3;1669,1694,1704;, - 3;1625,1662,1669;, - 3;1616,1614,1625;, - 3;2134,2250,2137;, - 3;2134,1747,2250;, - 3;2139,2093,2142;, - 3;2135,1705,1730;, - 3;2145,2208,2099;, - 3;2100,2210,2096;, - 3;2096,1745,1706;, - 3;2140,2101,2090;, - 3;2091,2096,2094;, - 3;2143,2097,2136;, - 3;2141,2134,2137;, - 3;2138,2099,2101;, - 3;2138,2254,2145;, - 3;2255,2211,2209;, - 3;2101,2208,2212;, - 3;1746,2251,1748;, - 3;781,784,788;, - 3;781,1339,784;, - 3;1083,1060,1086;, - 3;782,1333,1337;, - 3;790,753,755;, - 3;756,758,750;, - 3;750,1335,1334;, - 3;1084,757,1057;, - 3;1058,750,1061;, - 3;1087,751,783;, - 3;1085,781,788;, - 3;789,755,757;, - 3;789,791,790;, - 3;792,759,754;, - 3;757,753,760;, - 3;1336,785,1340;, - 3;1969,1972,1974;, - 3;1969,1339,1338;, - 3;2146,2102,2105;, - 3;1970,1333,1946;, - 3;1978,1950,1979;, - 3;1952,1947,1954;, - 3;1947,1335,1954;, - 3;2147,1953,1973;, - 3;2106,1947,1952;, - 3;2149,1948,2103;, - 3;2148,1969,2150;, - 3;1973,1949,1978;, - 3;1973,1979,1975;, - 3;1980,1955,1976;, - 3;1953,1950,1949;, - 3;1336,1977,1956;, - 3;1302,1288,1305;, - 3;722,1290,1303;, - 3;661,718,722;, - 3;664,642,662;, - 3;666,643,664;, - 3;669,645,667;, - 3;1307,646,669;, - 3;1305,1292,1308;, - 3;1309,35,1306;, - 3;670,35,1309;, - 3;670,668,35;, - 3;668,665,35;, - 3;665,663,35;, - 3;663,723,35;, - 3;1304,35,723;, - 3;1306,35,1304;, - 3;1328,413,36;, - 3;36,413,415;, - 3;1328,36,1912;, - 3;1328,1912,1871;, - 3;36,415,1914;, - 3;36,1914,1912;, - 3;376,134,413;, - 3;376,413,1328;, - 3;134,418,413;, - 3;369,135,377;, - 3;369,132,135;, - 3;1329,1872,1867;, - 3;1325,1329,1867;, - 3;1873,1913,1909;, - 3;1868,1873,1909;, - 3;1913,1915,1910;, - 3;1909,1913,1910;, - 3;416,1911,1916;, - 3;409,1911,416;, - 3;414,410,417;, - 3;411,410,414;, - 3;136,412,419;, - 3;133,412,136;, - 3;378,1329,1325;, - 3;370,378,1325;, - 3;412,414,419;, - 3;412,411,414;, - 3;304,342,307;, - 3;37,381,379;, - 3;308,346,309;, - 3;304,310,306;, - 3;38,383,381;, - 3;309,671,576;, - 3;305,577,574;, - 3;573,672,651;, - 3;335,38,37;, - 3;343,382,347;, - 3;335,379,344;, - 3;337,39,38;, - 3;650,383,39;, - 3;347,384,673;, - 3;579,315,584;, - 3;312,355,316;, - 3;580,40,313;, - 3;313,675,348;, - 3;349,709,356;, - 3;317,710,41;, - 3;317,41,585;, - 3;580,1834,40;, - 3;40,1853,675;, - 3;676,1859,709;, - 3;41,1860,1839;, - 3;41,1839,585;, - 3;581,1840,1835;, - 3;1836,1861,1854;, - 3;1253,1247,1255;, - 3;1258,1249,1253;, - 3;1258,1810,1250;, - 3;1260,1812,1819;, - 3;42,1254,1256;, - 3;1261,42,1256;, - 3;42,1816,1259;, - 3;1262,1820,42;, - 3;1257,1251,1263;, - 3;1817,1813,1811;, - 3;120,280,278;, - 3;278,550,548;, - 3;279,123,121;, - 3;116,43,29;, - 3;553,44,282;, - 3;30,556,544;, - 3;551,45,549;, - 3;545,558,547;, - 3;552,46,559;, - 3;546,46,271;, - 3;281,124,46;, - 3;271,124,117;, - 3;557,549,45;, - 3;283,548,554;, - 3;543,45,545;, - 3;53,125,118;, - 3;53,58,56;, - 3;55,127,59;, - 3;118,284,273;, - 3;119,287,127;, - 3;272,288,275;, - 3;57,128,126;, - 3;126,289,285;, - 3;582,1310,47;, - 3;290,47,1264;, - 3;47,1856,1837;, - 3;1264,1837,1822;, - 3;677,575,653;, - 3;1311,652,1296;, - 3;1857,1296,1852;, - 3;1838,1851,1833;, - 3;1823,1833,1815;, - 3;1265,1814,1252;, - 3;1252,291,1265;, - 3;277,583,292;, - 3;680,726,724;, - 3;680,1330,1312;, - 3;686,1314,689;, - 3;686,694,691;, - 3;1317,680,1312;, - 3;697,703,700;, - 3;351,706,698;, - 3;692,701,687;, - 3;688,704,681;, - 3;683,705,707;, - 3;683,707,353;, - 3;692,352,699;, - 3;725,720,719;, - 3;1313,1326,1297;, - 3;727,654,721;, - 3;690,656,695;, - 3;1315,1300,1299;, - 3;693,657,660;, - 3;354,340,339;, - 3;1318,1297,1301;, - 3;1331,719,1327;, - 3;690,1298,658;, - 3;352,659,341;, - 3;683,338,655;, - 3;2444,2452,2453;, - 3;2439,2454,2441;, - 3;2412,2441,2423;, - 3;2415,2424,2425;, - 3;2417,2425,2426;, - 3;2420,2427,2428;, - 3;2449,2428,2455;, - 3;2447,2456,2452;, - 3;2450,2448,2422;, - 3;2421,2450,2422;, - 3;2421,2422,2418;, - 3;2418,2422,2416;, - 3;2416,2422,2413;, - 3;2413,2422,2440;, - 3;2445,2440,2422;, - 3;2448,2445,2422;, - 3;2457,2452,2460;, - 3;2442,2454,2458;, - 3;2429,2441,2442;, - 3;2432,2424,2430;, - 3;2434,2425,2432;, - 3;2437,2427,2435;, - 3;2462,2428,2437;, - 3;2460,2456,2463;, - 3;2464,2411,2461;, - 3;2438,2411,2464;, - 3;2438,2436,2411;, - 3;2436,2433,2411;, - 3;2433,2431,2411;, - 3;2431,2443,2411;, - 3;2459,2411,2443;, - 3;2461,2411,2459;, - 3;2475,2480,2483;, - 3;2476,2485,2477;, - 3;2478,2487,2481;, - 3;2484,2488,2466;, - 3;2489,2492,2494;, - 3;2490,2495,2497;, - 3;2469,2494,2467;, - 3;2470,2489,2469;, - 3;2500,2498,2496;, - 3;2505,2507,2509;, - 3;2505,2502,2501;, - 3;2472,2496,2471;, - 3;2474,2506,2505;, - 3;2474,2501,2473;, - 3;2499,2493,2491;, - 3;2512,2510,2508;, - 3;2512,2499,2503;, - 3;2521,2533,2523;, - 3;2523,2538,2536;, - 3;2521,2540,2534;, - 3;2528,2274,2273;, - 3;2530,2289,2275;, - 3;2542,2292,2289;, - 3;2544,2298,2293;, - 3;2548,2301,2298;, - 3;2517,1940,2089;, - 3;2273,2513,2528;, - 3;2550,2088,2301;, - 3;2522,2531,2528;, - 3;2535,2549,2533;, - 3;2524,2543,2532;, - 3;2537,2545,2543;, - 3;2538,2549,2546;, - 3;2540,2551,2534;, - 3;2526,2518,2541;, - 3;2521,2514,2527;, - 3;2584,2555,2587;, - 3;2585,2590,2593;, - 3;2588,2558,2591;, - 3;2552,2559,2556;, - 3;2586,2596,2553;, - 3;2594,2560,2597;, - 3;2599,2564,2602;, - 3;2600,2605,2608;, - 3;2603,2567,2606;, - 3;2561,2568,2565;, - 3;2601,2570,2562;, - 3;2609,2569,2571;, - 3;2611,2576,2614;, - 3;2612,2616,2619;, - 3;2614,2578,2617;, - 3;2573,2579,2577;, - 3;2613,2581,2574;, - 3;2620,2580,2582;, - 3;2654,2625,2657;, - 3;2655,2660,2663;, - 3;2658,2628,2661;, - 3;2622,2629,2626;, - 3;2656,2666,2623;, - 3;2664,2630,2667;, - 3;2669,2634,2672;, - 3;2670,2675,2678;, - 3;2673,2637,2676;, - 3;2631,2638,2635;, - 3;2671,2640,2632;, - 3;2679,2639,2641;, - 3;2681,2646,2684;, - 3;2682,2686,2689;, - 3;2684,2648,2687;, - 3;2643,2649,2647;, - 3;2683,2651,2644;, - 3;2690,2650,2652;, - 3;2724,2695,2727;, - 3;2725,2730,2733;, - 3;2728,2698,2731;, - 3;2692,2699,2696;, - 3;2726,2736,2693;, - 3;2734,2700,2737;, - 3;2739,2704,2742;, - 3;2740,2745,2748;, - 3;2743,2707,2746;, - 3;2701,2708,2705;, - 3;2741,2710,2702;, - 3;2749,2709,2711;, - 3;2751,2716,2754;, - 3;2752,2756,2759;, - 3;2754,2718,2757;, - 3;2713,2719,2717;, - 3;2753,2721,2714;, - 3;2760,2720,2722;, - 3;2794,2765,2797;, - 3;2795,2800,2803;, - 3;2798,2768,2801;, - 3;2762,2769,2766;, - 3;2796,2806,2763;, - 3;2804,2770,2807;, - 3;2809,2774,2812;, - 3;2810,2815,2818;, - 3;2813,2777,2816;, - 3;2771,2778,2775;, - 3;2811,2780,2772;, - 3;2819,2779,2781;, - 3;2821,2786,2824;, - 3;2822,2826,2829;, - 3;2824,2788,2827;, - 3;2783,2789,2787;, - 3;2823,2791,2784;, - 3;2830,2790,2792;, - 3;2853,2858,2859;, - 3;2850,2860,2851;, - 3;2832,2851,2838;, - 3;2834,2839,2840;, - 3;2835,2840,2841;, - 3;2837,2842,2843;, - 3;2856,2843,2861;, - 3;2855,2862,2858;, - 3;2863,2858,2865;, - 3;2852,2860,2864;, - 3;2844,2851,2852;, - 3;2846,2839,2845;, - 3;2847,2840,2846;, - 3;2849,2842,2848;, - 3;2866,2843,2849;, - 3;2865,2862,2867;, - 3;2889,2894,2895;, - 3;2886,2896,2887;, - 3;2868,2887,2874;, - 3;2870,2875,2876;, - 3;2871,2876,2877;, - 3;2873,2878,2879;, - 3;2892,2879,2897;, - 3;2891,2898,2894;, - 3;2899,2894,2901;, - 3;2888,2896,2900;, - 3;2880,2887,2888;, - 3;2882,2875,2881;, - 3;2883,2876,2882;, - 3;2885,2878,2884;, - 3;2902,2879,2885;, - 3;2901,2898,2903;, - 3;2928,2933,2935;, - 3;2938,2933,2931;, - 3;2936,2946,2929;, - 3;2941,2904,2906;, - 3;2912,2918,2920;, - 3;2922,2918,2925;, - 3;2915,2948,2950;, - 3;2926,2910,2923;, - 3;2905,2949,2911;, - 3;2946,2950,2948;, - 3;2944,2908,2951;, - 3;2906,2910,2909;, - 3;2907,2944,2942;, - 3;2934,2944,2937;, - 3;2942,2944,2934;, - 3;2905,2939,2947;, - 3;2939,2932,2947;, - 3;2932,2930,2947;, - 3;2908,2916,2951;, - 3;2908,2927,2919;, - 3;2908,2919,2916;, - 3;2911,2949,2924;, - 3;2921,2949,2913;, - 3;2924,2949,2921;, - 3;2989,2971,2974;, - 3;2989,2974,2977;, - 3;2989,2977,2980;, - 3;2980,2983,2989;, - 3;2983,2986,2989;, - 3;2986,2971,2989;, - 3;2952,2953,2956;, - 3;2952,2959,2953;, - 3;2952,2962,2959;, - 3;2962,2952,2965;, - 3;2965,2952,2968;, - 3;2968,2952,2956;, - 3;2954,2978,2975;, - 3;2960,2981,2979;, - 3;2963,2984,2982;, - 3;2966,2987,2985;, - 3;2969,2972,2988;, - 3;2957,2976,2973;, - 3;3027,3009,3012;, - 3;3027,3012,3015;, - 3;3027,3015,3018;, - 3;3018,3021,3027;, - 3;3021,3024,3027;, - 3;3024,3009,3027;, - 3;2990,2991,2994;, - 3;2990,2997,2991;, - 3;2990,3000,2997;, - 3;3000,2990,3003;, - 3;3003,2990,3006;, - 3;3006,2990,2994;, - 3;2992,3016,3013;, - 3;2998,3019,3017;, - 3;3001,3022,3020;, - 3;3004,3025,3023;, - 3;3007,3010,3026;, - 3;2995,3014,3011;, - 3;4008,4102,4011;, - 3;4008,4680,4102;, - 3;4013,3980,4016;, - 3;4009,4638,4662;, - 3;4019,4096,3989;, - 3;3990,4098,3986;, - 3;3986,4678,4639;, - 3;4014,3991,3983;, - 3;3984,3986,3981;, - 3;4017,3987,4010;, - 3;4015,4008,4011;, - 3;4012,3989,3991;, - 3;4012,4106,4019;, - 3;4107,4099,4097;, - 3;3991,4096,4100;, - 3;4679,4103,4681;, - 3;3992,3028,5175;, - 3;3689,5175,4847;, - 3;3030,4847,3031;, - 3;446,3711,763;, - 3;762,3032,4;, - 3;446,3033,3414;, - 3;420,3686,736;, - 3;1958,4869,8;, - 3;425,3176,3398;, - 3;3399,3713,3688;, - 3;1917,3686,4834;, - 3;4871,3713,4870;, - 3;421,3398,3395;, - 3;3687,3399,3688;, - 3;3687,4871,4835;, - 3;1918,4872,1958;, - 3;4020,4682,5015;, - 3;3087,3213,3178;, - 3;3087,3089,3213;, - 3;3179,3091,3088;, - 3;3088,3093,3090;, - 3;3714,3428,3717;, - 3;3430,3433,3429;, - 3;3090,3094,3214;, - 3;3435,3439,3434;, - 3;3431,3415,3216;, - 3;3216,3178,3213;, - 3;3436,3216,3217;, - 3;3217,3213,3089;, - 3;3436,3218,3437;, - 3;3217,3215,3218;, - 3;3718,3416,3715;, - 3;3181,3416,3417;, - 3;3439,3219,3220;, - 3;3220,3214,3095;, - 3;3419,3421,3184;, - 3;3185,3184,3421;, - 3;3221,3184,3187;, - 3;3082,3184,3185;, - 3;3221,3187,3096;, - 3;3187,3082,3096;, - 3;3422,3426,3424;, - 3;3423,3188,3186;, - 3;3419,3222,3427;, - 3;3185,3084,3083;, - 3;3096,3222,3221;, - 3;3082,3097,3096;, - 3;3161,3223,3201;, - 3;3163,3206,3202;, - 3;3208,3227,3224;, - 3;3225,3197,3194;, - 3;3195,3172,3170;, - 3;3167,3170,3172;, - 3;3175,3201,3212;, - 3;3207,3208,3203;, - 3;3192,3173,3198;, - 3;3193,3228,3223;, - 3;3223,3210,3201;, - 3;3161,3168,3174;, - 3;3212,3210,3206;, - 3;3175,3206,3168;, - 3;3721,3993,4021;, - 3;3692,3204,3995;, - 3;3998,3226,4024;, - 3;4025,3194,3724;, - 3;3725,3171,3695;, - 3;3693,3171,3164;, - 3;3205,3998,3996;, - 3;3696,3993,3690;, - 3;3722,3695,3691;, - 3;4022,3998,4024;, - 3;3723,4025,3724;, - 3;3697,3997,3999;, - 3;4000,3998,3994;, - 3;3691,3693,3698;, - 3;3074,3150,3400;, - 3;3067,3363,3129;, - 3;3071,3130,3133;, - 3;3364,3078,3403;, - 3;3404,3075,3401;, - 3;3136,3156,3138;, - 3;3159,3406,3157;, - 3;3139,3407,3367;, - 3;3137,3368,3035;, - 3;3369,4837,4796;, - 3;4797,3372,3370;, - 3;4838,4799,4798;, - 3;1881,4840,1930;, - 3;4839,3411,4841;, - 3;1929,3412,443;, - 3;3408,3373,3413;, - 3;442,3373,399;, - 3;12,3143,3141;, - 3;3376,4800,4803;, - 3;13,4801,1881;, - 3;155,3374,3144;, - 3;3142,3375,3376;, - 3;5118,5211,5119;, - 3;5122,5214,5118;, - 3;5118,4688,4686;, - 3;4691,5119,5124;, - 3;5122,4686,4693;, - 3;4108,4688,4691;, - 3;4694,6193,4696;, - 3;1765,6193,6192;, - 3;5123,4697,5126;, - 3;2223,4697,1766;, - 3;5215,5217,5212;, - 3;2327,5219,2330;, - 3;2224,5218,2328;, - 3;5213,5127,5120;, - 3;4687,4698,6193;, - 3;6192,4698,1769;, - 3;2329,5126,2223;, - 3;5123,5220,5216;, - 3;1770,5130,2229;, - 3;5125,4700,4692;, - 3;5121,5131,5125;, - 3;2229,5128,2225;, - 3;4111,4116,4114;, - 3;4689,4115,4699;, - 3;4692,4117,4109;, - 3;4698,1771,1769;, - 3;3440,3446,3442;, - 3;4703,4120,4118;, - 3;5132,4705,4703;, - 3;4120,4122,4118;, - 3;3440,4124,3450;, - 3;1182,4707,4126;, - 3;4127,4707,4708;, - 3;1780,5136,4707;, - 3;4708,5136,5137;, - 3;15,4710,5139;, - 3;5140,4710,4711;, - 3;491,3454,3452;, - 3;3454,3455,3452;, - 3;502,3460,504;, - 3;3463,3461,3465;, - 3;513,3468,514;, - 3;514,3471,518;, - 3;3447,3473,3443;, - 3;527,3471,3479;, - 3;4129,3454,4131;, - 3;1189,3454,496;, - 3;1189,4126,4131;, - 3;4129,4126,4127;, - 3;4132,4135,4134;, - 3;1196,4135,1197;, - 3;1196,3460,4134;, - 3;4132,3460,3463;, - 3;1197,4710,1784;, - 3;4711,4135,4136;, - 3;513,3453,3470;, - 3;3472,3474,3476;, - 3;503,3479,3462;, - 3;4123,3458,4130;, - 3;3441,3456,3458;, - 3;3444,3453,3457;, - 3;3475,3470,3453;, - 3;4119,4130,4128;, - 3;4704,4128,4709;, - 3;5133,4709,5138;, - 3;4125,4137,4133;, - 3;4121,4712,4137;, - 3;4706,5141,4712;, - 3;3451,4133,3464;, - 3;3448,3464,3466;, - 3;3477,3467,3462;, - 3;3471,3462,3479;, - 3;4138,4715,4713;, - 3;4714,4720,4718;, - 3;4144,4721,4146;, - 3;4150,4152,4151;, - 3;4140,4722,4716;, - 3;4139,4151,4141;, - 3;4139,4153,4150;, - 3;4153,4147,4152;, - 3;4142,4152,4148;, - 3;4154,5144,5142;, - 3;4154,4160,4156;, - 3;4161,1228,1226;, - 3;5145,1230,2246;, - 3;5143,1232,4155;, - 3;4157,2246,5145;, - 3;5143,1232,4155;, - 3;4155,1229,4163;, - 3;1231,4162,1227;, - 3;5146,5225,5223;, - 3;5224,17,2335;, - 3;5147,2335,18;, - 3;3079,68,81;, - 3;82,3153,3076;, - 3;3151,175,177;, - 3;3402,176,444;, - 3;3365,445,401;, - 3;401,3131,3366;, - 3;156,3134,3132;, - 3;158,3072,3135;, - 3;3068,70,71;, - 3;3069,71,68;, - 3;3077,80,83;, - 3;3405,444,445;, - 3;4026,19,1082;, - 3;3038,1082,22;, - 3;5015,1797,23;, - 3;24,4684,4020;, - 3;3434,529,475;, - 3;3719,476,780;, - 3;3091,218,103;, - 3;3093,102,104;, - 3;3220,529,3439;, - 3;3424,25,461;, - 3;3189,461,221;, - 3;3085,220,89;, - 3;3098,89,26;, - 3;3429,474,477;, - 3;3094,104,106;, - 3;3220,105,252;, - 3;4683,1800,1798;, - 3;3418,219,3182;, - 3;3418,779,462;, - 3;4873,1967,1966;, - 3;4875,2109,1967;, - 3;5017,2109,5016;, - 3;4874,2114,5018;, - 3;4848,4875,4873;, - 3;4850,5016,4875;, - 3;4988,5017,5016;, - 3;4849,5018,4989;, - 3;4805,2256,1887;, - 3;4844,2263,5158;, - 3;4845,5154,4808;, - 3;4808,5155,4806;, - 3;2263,5156,5158;, - 3;1935,4809,1893;, - 3;3146,4808,4806;, - 3;27,4810,3148;, - 3;28,4807,1888;, - 3;4485,4487,3861;, - 3;3861,4559,3925;, - 3;3925,4564,4562;, - 3;4490,4493,4492;, - 3;4488,4492,4494;, - 3;4560,4495,4566;, - 3;4565,4567,4568;, - 3;4565,4569,4563;, - 3;4563,3928,3926;, - 3;3927,3864,3862;, - 3;3863,4493,4486;, - 3;4496,4500,4498;, - 3;3866,4570,4500;, - 3;3930,4573,4570;, - 3;4499,4493,4497;, - 3;4501,4492,4499;, - 3;4571,4495,4502;, - 3;4574,4567,4572;, - 3;4574,4569,4568;, - 3;4575,3928,4569;, - 3;3931,3864,3929;, - 3;3867,4493,3865;, - 3;4503,4508,4506;, - 3;4513,4508,4516;, - 3;4510,4521,4519;, - 3;4517,3869,4514;, - 3;4379,4385,4382;, - 3;4389,4385,4387;, - 3;4383,4523,4380;, - 3;4392,3875,3873;, - 3;3870,4524,4522;, - 3;4521,4525,4519;, - 3;4520,3874,3871;, - 3;3872,3875,3869;, - 3;3797,3738,3799;, - 3;4274,4888,4278;, - 3;4920,4395,4924;, - 3;3821,3825,4400;, - 3;3825,4402,4400;, - 3;3739,4369,3800;, - 3;4284,3740,3741;, - 3;3822,4403,4407;, - 3;4404,4414,4411;, - 3;4924,4412,4415;, - 3;4372,4279,4889;, - 3;4370,4280,4373;, - 3;4281,4275,4280;, - 3;4416,4396,4397;, - 3;4408,4411,4417;, - 3;3829,3832,3831;, - 3;4925,4929,4927;, - 3;4420,3831,4422;, - 3;4421,4427,4425;, - 3;4931,4428,4930;, - 3;3797,3831,3832;, - 3;4927,4890,4891;, - 3;4422,3831,4430;, - 3;3800,4430,3831;, - 3;4429,4431,4432;, - 3;4371,4432,4431;, - 3;4930,4428,4433;, - 3;4372,4930,4433;, - 3;3827,3829,3826;, - 3;3825,4420,4405;, - 3;4406,4425,4414;, - 3;4415,4931,4924;, - 3;4924,4925,4921;, - 3;3801,3749,3745;, - 3;4288,4899,4895;, - 3;4933,4437,4434;, - 3;3836,3842,3840;, - 3;3842,4443,4441;, - 3;3750,4375,4295;, - 3;4298,3751,4296;, - 3;3837,4444,4439;, - 3;4445,4450,4442;, - 3;4936,4452,4437;, - 3;4377,4900,4292;, - 3;4376,4293,4297;, - 3;4297,4289,4299;, - 3;4455,4438,4453;, - 3;4446,4454,4445;, - 3;3844,3848,3846;, - 3;4937,4941,4939;, - 3;4459,3850,3845;, - 3;4460,4464,4461;, - 3;4940,4465,4467;, - 3;3801,3850,3803;, - 3;4943,4901,4941;, - 3;4462,4469,3850;, - 3;3804,4469,4375;, - 3;4466,4470,4463;, - 3;4376,4472,4378;, - 3;4942,4473,4465;, - 3;4377,4942,4900;, - 3;3840,3844,3846;, - 3;3842,4459,3845;, - 3;4442,4468,4460;, - 3;4451,4940,4467;, - 3;4936,4937,4939;, - 3;3849,3834,3847;, - 3;3847,3828,3841;, - 3;3841,3823,3838;, - 3;3839,4409,4447;, - 3;4448,4418,4456;, - 3;4457,4398,4435;, - 3;4435,4922,4934;, - 3;4935,4926,4938;, - 3;4938,4928,4944;, - 3;4944,4892,4896;, - 3;4897,4276,4290;, - 3;4291,4285,4300;, - 3;4301,3742,3746;, - 3;3747,3798,3802;, - 3;3802,3833,3849;, - 3;4082,4077,4075;, - 3;3954,3933,3957;, - 3;3954,3963,3959;, - 3;4083,4088,4086;, - 3;3938,3933,3935;, - 3;3944,4092,4078;, - 3;3967,3944,3945;, - 3;4088,3972,3969;, - 3;3964,3972,3960;, - 3;4063,3877,4065;, - 3;3882,3879,3884;, - 3;4092,3974,4094;, - 3;3966,3976,3974;, - 3;3978,3934,3947;, - 3;3978,3965,3958;, - 3;4064,4070,4069;, - 3;4077,4070,4075;, - 3;3884,3886,3882;, - 3;3939,3890,3941;, - 3;3893,3950,3949;, - 3;3945,3950,3952;, - 3;3895,3891,3885;, - 3;3942,3895,3934;, - 3;3944,4080,3953;, - 3;3896,4080,4073;, - 3;3896,3949,3953;, - 3;3944,3949,3945;, - 3;3885,3898,3895;, - 3;3934,3898,3947;, - 3;4093,4076,4079;, - 3;3968,3936,3955;, - 3;3975,4089,4095;, - 3;4094,4084,4092;, - 3;3967,3961,3976;, - 3;3977,3973,3975;, - 3;3951,3883,3887;, - 3;3952,3888,3940;, - 3;3952,3937,3945;, - 3;4079,4071,4081;, - 3;4073,4072,4066;, - 3;3897,4067,3878;, - 3;3894,3878,3883;, - 3;4200,4221,4203;, - 3;3661,4222,4201;, - 3;3539,3668,3661;, - 3;3542,3591,3540;, - 3;3544,3593,3542;, - 3;3547,3594,3545;, - 3;4205,3596,3547;, - 3;4203,4224,4206;, - 3;4207,3549,4204;, - 3;3548,3549,4207;, - 3;3548,3546,3549;, - 3;3546,3543,3549;, - 3;3543,3541,3549;, - 3;3541,3662,3549;, - 3;4202,3549,3662;, - 3;4204,3549,4202;, - 3;4253,3377,3685;, - 3;3685,3377,3379;, - 3;4253,3685,4821;, - 3;4253,4821,4784;, - 3;3685,3379,4823;, - 3;3685,4823,4821;, - 3;3336,3121,3377;, - 3;3336,3377,4253;, - 3;3121,3382,3377;, - 3;3347,3122,3337;, - 3;3347,3124,3122;, - 3;4254,4785,4789;, - 3;4258,4254,4789;, - 3;4786,4822,4826;, - 3;4790,4786,4826;, - 3;4822,4824,4827;, - 3;4826,4822,4827;, - 3;3380,4828,4825;, - 3;3384,4828,3380;, - 3;3378,3385,3381;, - 3;3386,3385,3378;, - 3;3123,3387,3383;, - 3;3125,3387,3123;, - 3;3338,4254,4258;, - 3;3348,3338,4258;, - 3;3387,3378,3383;, - 3;3387,3386,3378;, - 3;4226,4208,4791;, - 3;4208,4787,4791;, - 3;3597,3349,3550;, - 3;3550,3349,3339;, - 3;3598,4227,3350;, - 3;4227,4792,3350;, - 3;3599,3551,4228;, - 3;3551,4209,4228;, - 3;3552,3340,4210;, - 3;4210,3340,4788;, - 3;3282,3296,3271;, - 3;3351,3343,3341;, - 3;3272,3300,3273;, - 3;3282,3274,3283;, - 3;3352,3345,3343;, - 3;3273,3553,3511;, - 3;3284,3512,3523;, - 3;3524,3554,3600;, - 3;3312,3352,3351;, - 3;3297,3344,3301;, - 3;3312,3341,3298;, - 3;3314,3353,3352;, - 3;3601,3345,3353;, - 3;3301,3346,3555;, - 3;3514,3276,3517;, - 3;3279,3302,3277;, - 3;3515,3520,3280;, - 3;3280,3557,3305;, - 3;3306,3537,3303;, - 3;3278,3538,3510;, - 3;3278,3510,3518;, - 3;3515,4747,3520;, - 3;3520,4764,3557;, - 3;3558,4767,3537;, - 3;3510,4768,4750;, - 3;3510,4750,3518;, - 3;3516,4751,4748;, - 3;4749,4769,4765;, - 3;4166,4180,4168;, - 3;4171,4182,4166;, - 3;4171,4732,4183;, - 3;4173,4734,4726;, - 3;4177,4167,4169;, - 3;4174,4177,4169;, - 3;4177,4723,4172;, - 3;4175,4727,4177;, - 3;4170,4184,4176;, - 3;4724,4735,4733;, - 3;3099,3233,3231;, - 3;3231,3482,3480;, - 3;3232,3102,3100;, - 3;3108,3235,3039;, - 3;3485,3238,3236;, - 3;3040,3488,3493;, - 3;3483,3490,3481;, - 3;3495,3491,3496;, - 3;3484,3239,3492;, - 3;3497,3239,3249;, - 3;3234,3103,3239;, - 3;3249,3103,3109;, - 3;3489,3481,3490;, - 3;3237,3480,3486;, - 3;3494,3490,3495;, - 3;3059,3104,3110;, - 3;3059,3056,3054;, - 3;3060,3106,3057;, - 3;3110,3240,3250;, - 3;3111,3243,3106;, - 3;3251,3244,3252;, - 3;3055,3107,3105;, - 3;3105,3245,3241;, - 3;4527,4475,4530;, - 3;4528,3903,3900;, - 3;4531,3851,3904;, - 3;4529,3853,4477;, - 3;3901,3852,3854;, - 3;4945,4536,4533;, - 3;4945,4539,4536;, - 3;4945,4542,4539;, - 3;4542,4945,4577;, - 3;4577,4945,4580;, - 3;4580,4945,4533;, - 3;3906,3910,3907;, - 3;3906,3907,3913;, - 3;3906,3913,3916;, - 3;3916,3919,3906;, - 3;3919,3922,3906;, - 3;3922,3910,3906;, - 3;3908,4540,3914;, - 3;3915,4543,3917;, - 3;3918,4578,3920;, - 3;3921,4581,3923;, - 3;3924,4534,3911;, - 3;3912,4537,3909;, - 3;4479,4902,4482;, - 3;4480,3858,3855;, - 3;4483,3805,3859;, - 3;4905,3806,4903;, - 3;4481,3808,4906;, - 3;3856,3807,3809;, - 3;4033,4039,4036;, - 3;4043,5056,4046;, - 3;3679,4813,4811;, - 3;5062,5066,5064;, - 3;4811,4818,4815;, - 3;4049,3811,4051;, - 3;3815,3813,3817;, - 3;4044,3812,3819;, - 3;3819,3812,3816;, - 3;4047,3814,4050;, - 3;3814,3820,3818;, - 3;5059,3819,4908;, - 3;4909,3819,3816;, - 3;5057,3820,4047;, - 3;3818,4910,4911;, - 3;5072,4908,4912;, - 3;4914,4908,4909;, - 3;5074,4910,5057;, - 3;4911,4916,4918;, - 3;5075,4913,4917;, - 3;4919,4913,4915;, - 3;3680,3817,3682;, - 3;3683,4911,4814;, - 3;3681,4909,3816;, - 3;4814,4918,4819;, - 3;4816,4919,4915;, - 3;4812,4914,4909;, - 3;4052,4055,4053;, - 3;4045,4058,4056;, - 3;4050,4059,4047;, - 3;4051,4061,4049;, - 3;5059,5079,5076;, - 3;5073,5081,5080;, - 3;5057,5082,5074;, - 3;5060,5083,5058;, - 3;4053,4041,4034;, - 3;4062,4040,4059;, - 3;4054,4037,4061;, - 3;5076,5069,5063;, - 3;5080,5067,5070;, - 3;5084,5068,5082;, - 3;4057,5085,5077;, - 3;4059,5065,5084;, - 3;4042,5064,4039;, - 3;4055,5063,4041;, - 3;4302,3752,4304;, - 3;4307,4311,4309;, - 3;4314,4319,4317;, - 3;4305,4319,4303;, - 3;4312,4318,3757;, - 3;3753,4318,4306;, - 3;4320,4326,4323;, - 3;4328,3759,3761;, - 3;4313,3764,4310;, - 3;3755,3758,3754;, - 3;3760,4310,3764;, - 3;4327,4308,4324;, - 3;4321,4307,4309;, - 3;4329,4319,4327;, - 3;3762,3764,3755;, - 3;4330,3756,4302;, - 3;4331,3768,3765;, - 3;4332,4337,4334;, - 3;4335,3771,3769;, - 3;3766,3772,4343;, - 3;4333,4344,4340;, - 3;4341,3773,4338;, - 3;4346,3777,3774;, - 3;4347,4352,4349;, - 3;4350,3780,3778;, - 3;3775,3781,3783;, - 3;4348,3784,4355;, - 3;4356,3782,4353;, - 3;4358,3789,3786;, - 3;4359,4363,4361;, - 3;4362,3791,3789;, - 3;3787,3792,3794;, - 3;4360,3795,4366;, - 3;4367,3793,4364;, - 3;3871,4518,4520;, - 3;4509,4511,4520;, - 3;4518,4509,4520;, - 3;3870,4522,4515;, - 3;4515,4522,4507;, - 3;4507,4522,4504;, - 3;3874,4526,4384;, - 3;3874,4386,4393;, - 3;3874,4384,4386;, - 3;3876,4390,4524;, - 3;4388,4381,4524;, - 3;4390,4388,4524;, - 3;4603,4607,4605;, - 3;4583,4609,4603;, - 3;4589,4586,4584;, - 3;4611,4592,4590;, - 3;4611,4615,4613;, - 3;4640,4646,4643;, - 3;4649,4619,4647;, - 3;4623,4604,4606;, - 3;4623,4585,4604;, - 3;4623,4591,4585;, - 3;4623,4612,4591;, - 3;4612,4623,4617;, - 3;4617,4623,4652;, - 3;4652,4623,4656;, - 3;4656,4623,4606;, - 3;4624,4657,4608;, - 3;4624,4658,4657;, - 3;4624,4616,4658;, - 3;4624,4614,4616;, - 3;4614,4624,4593;, - 3;4593,4624,4587;, - 3;4587,4624,4610;, - 3;4610,4624,4608;, - 3;4641,4659,4653;, - 3;4644,4657,4658;, - 3;4642,4656,4650;, - 3;4648,4608,4657;, - 3;4621,4607,4619;, - 3;4650,4606,4622;, - 3;5160,5176,5162;, - 3;5162,5181,5179;, - 3;5160,5183,5177;, - 3;5167,5170,5169;, - 3;5172,5185,5171;, - 3;5186,5188,5185;, - 3;5190,5194,5189;, - 3;5195,5197,5194;, - 3;4991,4851,4995;, - 3;5169,4853,5167;, - 3;5198,4996,5197;, - 3;5161,5173,5167;, - 3;5178,5196,5176;, - 3;5163,5187,5174;, - 3;5180,5191,5187;, - 3;5181,5196,5192;, - 3;5183,5199,5177;, - 3;5165,4992,5184;, - 3;5160,4854,5166;, - 3;3521,4211,4199;, - 3;3246,4199,4178;, - 3;4199,4770,4753;, - 3;4178,4753,4729;, - 3;3559,3525,3602;, - 3;4212,3603,4229;, - 3;4771,4229,4773;, - 3;4754,4774,4755;, - 3;4730,4755,4736;, - 3;4179,4737,4185;, - 3;4185,3247,4179;, - 3;3254,3522,3248;, - 3;3562,3665,3663;, - 3;3562,4255,4213;, - 3;3568,4215,3571;, - 3;3568,3576,3573;, - 3;4218,3562,4213;, - 3;3579,3585,3582;, - 3;3308,3588,3580;, - 3;3574,3583,3569;, - 3;3570,3586,3563;, - 3;3565,3587,3589;, - 3;3565,3589,3310;, - 3;3574,3309,3581;, - 3;3664,3670,3669;, - 3;4214,4259,4230;, - 3;3666,3604,3671;, - 3;3572,3606,3577;, - 3;4216,4233,4231;, - 3;3575,3607,3609;, - 3;3311,3318,3316;, - 3;4219,4230,4234;, - 3;4256,3669,4260;, - 3;3572,4232,3608;, - 3;3309,3610,3319;, - 3;3565,3317,3605;, - 3;4643,4654,4660;, - 3;4661,4618,4655;, - 3;5019,5024,5022;, - 3;5026,5232,5024;, - 3;5239,5278,5241;, - 3;5028,5229,5227;, - 3;5227,5286,5284;, - 3;5279,5284,5286;, - 3;5200,5235,5027;, - 3;5230,5285,5287;, - 3;5031,5027,5020;, - 3;5032,5228,5230;, - 3;5248,5280,5240;, - 3;5287,5281,5289;, - 3;5202,5023,5025;, - 3;5025,5249,5202;, - 3;5204,5288,5251;, - 3;5201,5251,5245;, - 3;5231,5035,5032;, - 3;5204,5031,5035;, - 3;5236,5242,5233;, - 3;5234,5243,5249;, - 3;5288,5248,5251;, - 3;5245,5251,5248;, - 3;5029,5036,5037;, - 3;5031,5037,5036;, - 3;5237,5248,5240;, - 3;6189,5203,6194;, - 3;6190,5229,5030;, - 3;6198,5286,5229;, - 3;6194,5250,6195;, - 3;6199,5279,5286;, - 3;6196,5278,6201;, - 3;6195,5244,6197;, - 3;5252,5257,5254;, - 3;5253,2371,31;, - 3;5255,2373,2372;, - 3;5260,2374,5258;, - 3;5262,2378,5263;, - 3;5263,5265,5262;, - 3;5205,2380,5262;, - 3;5206,5262,5265;, - 3;5270,5267,5272;, - 3;5275,2393,2392;, - 3;5275,5273,5276;, - 3;5208,5266,5270;, - 3;5210,2392,34;, - 3;5210,5271,5275;, - 3;5268,2379,2397;, - 3;2398,5277,5274;, - 3;2398,5268,2397;, - 3;3879,4664,4545;, - 3;4064,4666,4665;, - 3;4069,4670,4666;, - 3;4077,4672,4670;, - 3;4086,4674,4673;, - 3;4088,4625,4674;, - 3;4627,3970,3979;, - 3;3948,4627,3979;, - 3;3899,4595,3948;, - 3;3880,4547,3899;, - 3;5101,4671,4675;, - 3;4972,4596,4958;, - 3;4972,4630,4628;, - 3;5102,4677,5105;, - 3;4961,4596,4598;, - 3;4964,5108,4979;, - 3;4980,4964,4979;, - 3;4677,4982,5105;, - 3;4631,4982,4633;, - 3;4667,4946,4548;, - 3;4948,4548,4946;, - 3;5108,4984,4979;, - 3;4979,4986,4980;, - 3;4636,4597,4629;, - 3;4636,4632,4634;, - 3;4668,5090,5086;, - 3;4671,5090,4669;, - 3;4551,4950,4553;, - 3;4962,4554,4951;, - 3;4954,4969,4967;, - 3;4965,4967,4969;, - 3;4556,4552,4555;, - 3;4599,4556,4555;, - 3;4964,5099,5097;, - 3;4956,5099,4971;, - 3;4956,4969,4954;, - 3;4964,4969,4971;, - 3;4552,4557,4549;, - 3;4597,4557,4556;, - 3;5109,5095,5103;, - 3;4981,4959,4966;, - 3;4985,5106,4983;, - 3;5110,5104,5107;, - 3;4980,4975,4973;, - 3;4987,4983,4976;, - 3;4968,4949,4955;, - 3;4970,4952,4967;, - 3;4970,4960,4963;, - 3;5098,5091,5095;, - 3;5093,5092,5099;, - 3;4957,5087,5094;, - 3;4955,4947,4957;, - 3;4548,4664,4667;, - 3;4668,4666,4669;, - 3;4669,4670,4671;, - 3;4671,4672,4675;, - 3;4676,4674,4677;, - 3;4677,4625,4633;, - 3;4627,4635,4626;, - 3;4601,4627,4595;, - 3;4558,4595,4547;, - 3;4550,4547,4546;, - 3;5038,5041,5148;, - 3;5038,4680,4663;, - 3;5043,5000,4997;, - 3;5039,4638,5003;, - 3;5049,5112,5152;, - 3;5007,5004,5114;, - 3;5004,4678,5114;, - 3;5044,5008,5042;, - 3;4998,5004,5007;, - 3;5046,5005,5001;, - 3;5045,5038,5047;, - 3;5042,5006,5049;, - 3;5042,5152,5149;, - 3;5153,5115,5150;, - 3;5008,5112,5006;, - 3;4679,5151,5116;, - 3;3726,3733,3729;, - 3;3726,4272,4270;, - 3;4027,4005,4002;, - 3;3727,4266,3699;, - 3;3735,3702,3736;, - 3;3705,3700,3707;, - 3;3700,4268,3707;, - 3;4028,3706,3734;, - 3;4003,3700,3705;, - 3;4030,3701,4006;, - 3;4029,3726,4031;, - 3;3734,3704,3735;, - 3;3734,3736,3730;, - 3;3737,3708,3731;, - 3;3706,3702,3704;, - 3;4269,3732,3709;, - 3;4876,4881,4879;, - 3;4876,4272,4881;, - 3;5050,5009,5053;, - 3;4877,4266,4271;, - 3;4885,4861,4860;, - 3;4863,4865,4857;, - 3;4857,4268,4267;, - 3;5051,4864,5012;, - 3;5013,4857,5010;, - 3;5054,4858,4878;, - 3;5052,4876,4879;, - 3;4880,4860,4864;, - 3;4880,4886,4885;, - 3;4887,4866,4862;, - 3;4864,4861,4867;, - 3;4269,4882,4273;, - 3;4235,4221,4223;, - 3;3672,4222,3668;, - 3;3611,3668,3592;, - 3;3614,3591,3593;, - 3;3616,3593,3595;, - 3;3619,3594,3596;, - 3;4240,3596,4225;, - 3;4238,4224,4221;, - 3;4241,4239,3041;, - 3;3620,4241,3041;, - 3;3620,3041,3617;, - 3;3617,3041,3615;, - 3;3615,3041,3612;, - 3;3612,3041,3673;, - 3;4236,3673,3041;, - 3;4239,4236,3041;, - 3;4261,3042,3388;, - 3;3042,3390,3388;, - 3;4261,4829,3042;, - 3;4261,4793,4829;, - 3;3042,4831,3390;, - 3;3042,4829,4831;, - 3;3354,3388,3126;, - 3;3354,4261,3388;, - 3;3126,3388,3393;, - 3;3347,3355,3127;, - 3;3347,3127,3124;, - 3;4262,4789,4794;, - 3;4258,4789,4262;, - 3;4795,4826,4830;, - 3;4790,4826,4795;, - 3;4830,4827,4832;, - 3;4826,4827,4830;, - 3;3391,4833,4828;, - 3;3384,3391,4828;, - 3;3389,3392,3385;, - 3;3386,3389,3385;, - 3;3128,3394,3387;, - 3;3125,3128,3387;, - 3;3356,4258,4262;, - 3;3348,4258,3356;, - 3;3387,3394,3389;, - 3;3387,3389,3386;, - 3;3282,3320,3313;, - 3;3043,3359,3044;, - 3;3285,3324,3321;, - 3;3282,3287,3286;, - 3;3044,3361,3045;, - 3;3288,3621,3324;, - 3;3284,3526,3289;, - 3;3524,3622,3527;, - 3;3312,3044,3315;, - 3;3322,3360,3357;, - 3;3312,3358,3043;, - 3;3315,3045,3601;, - 3;3601,3361,3623;, - 3;3325,3362,3360;, - 3;3529,3293,3290;, - 3;3291,3333,3326;, - 3;3530,3292,3046;, - 3;3292,3625,3046;, - 3;3327,3659,3626;, - 3;3294,3660,3334;, - 3;3294,3534,3047;, - 3;3530,3046,4756;, - 3;3046,4775,4756;, - 3;3626,4781,4776;, - 3;3047,4782,3660;, - 3;3047,3534,4761;, - 3;3531,4762,3535;, - 3;4757,4783,4763;, - 3;4186,4180,4182;, - 3;4191,4182,4183;, - 3;4191,4732,4738;, - 3;4193,4734,4184;, - 3;3048,4187,4192;, - 3;4194,4188,3048;, - 3;3048,4739,4741;, - 3;4195,3048,4741;, - 3;4189,4184,4181;, - 3;4740,4735,4742;, - 3;3112,3256,3258;, - 3;3256,3500,3258;, - 3;3257,3115,3049;, - 3;3108,3049,3115;, - 3;3503,3050,3506;, - 3;3040,3506,3050;, - 3;3501,3051,3508;, - 3;3495,3508,3051;, - 3;3502,3052,3259;, - 3;3497,3052,3509;, - 3;3259,3116,3113;, - 3;3249,3116,3052;, - 3;3507,3498,3504;, - 3;3260,3499,3256;, - 3;3494,3051,3507;, - 3;3059,3117,3062;, - 3;3059,3064,3061;, - 3;3060,3119,3111;, - 3;3110,3262,3117;, - 3;3111,3265,3253;, - 3;3251,3266,3263;, - 3;3063,3120,3065;, - 3;3118,3267,3120;, - 3;3532,4243,3627;, - 3;3268,3053,3532;, - 3;3053,4778,4243;, - 3;4197,4759,3053;, - 3;3628,3525,3533;, - 3;4244,3603,3629;, - 3;4779,4229,4244;, - 3;4760,4774,4780;, - 3;4744,4755,4760;, - 3;4198,4737,4745;, - 3;4185,3269,3255;, - 3;3254,3533,3525;, - 3;3630,3676,3633;, - 3;3630,4263,3674;, - 3;3636,4247,4250;, - 3;3636,3644,3639;, - 3;4250,3630,3636;, - 3;3647,3653,3656;, - 3;3329,3657,3331;, - 3;3641,3650,3648;, - 3;3637,3654,3651;, - 3;3634,3655,3631;, - 3;3634,3332,3658;, - 3;3641,3648,3330;, - 3;3675,3670,3677;, - 3;4245,4259,4264;, - 3;3678,3604,3635;, - 3;3640,3606,3608;, - 3;4248,4233,4251;, - 3;3642,3607,3645;, - 3;3331,3318,3329;, - 3;4252,4230,4245;, - 3;4265,3669,3675;, - 3;3640,4232,4249;, - 3;3330,3610,3641;, - 3;3634,3317,3332;, - 3;5323,5331,5326;, - 3;5318,5332,5324;, - 3;5291,5320,5318;, - 3;5294,5302,5292;, - 3;5296,5304,5294;, - 3;5299,5305,5297;, - 3;5328,5307,5299;, - 3;5326,5334,5329;, - 3;5330,5301,5327;, - 3;5300,5301,5330;, - 3;5300,5298,5301;, - 3;5298,5295,5301;, - 3;5295,5293,5301;, - 3;5293,5319,5301;, - 3;5325,5301,5319;, - 3;5327,5301,5325;, - 3;5336,5331,5333;, - 3;5321,5332,5320;, - 3;5308,5320,5303;, - 3;5311,5302,5304;, - 3;5313,5304,5306;, - 3;5316,5305,5307;, - 3;5341,5307,5335;, - 3;5339,5334,5331;, - 3;5342,5340,5290;, - 3;5317,5342,5290;, - 3;5317,5290,5314;, - 3;5314,5290,5312;, - 3;5312,5290,5309;, - 3;5309,5290,5322;, - 3;5337,5322,5290;, - 3;5340,5337,5290;, - 3;5350,5355,5352;, - 3;5351,2485,2465;, - 3;5353,2487,2486;, - 3;5358,2488,5356;, - 3;5360,2492,5361;, - 3;5361,5363,5360;, - 3;5344,2494,5360;, - 3;5345,5360,5363;, - 3;5368,5365,5370;, - 3;5373,2507,2506;, - 3;5373,5371,5374;, - 3;5347,5364,5368;, - 3;5349,2506,2468;, - 3;5349,5369,5373;, - 3;5366,2493,2511;, - 3;2512,5375,5372;, - 3;2512,5366,2511;, - 3;5384,5396,5397;, - 3;5386,5401,5396;, - 3;5384,5403,5389;, - 3;5391,5170,5393;, - 3;5394,5185,5405;, - 3;5405,5188,5407;, - 3;5408,5194,5411;, - 3;5411,5197,5413;, - 3;5380,4851,5376;, - 3;5169,5377,4852;, - 3;5413,4996,5381;, - 3;5385,5393,5387;, - 3;5398,5412,5414;, - 3;5388,5406,5399;, - 3;5399,5409,5402;, - 3;5401,5412,5396;, - 3;5403,5414,5382;, - 3;5390,5383,5378;, - 3;5384,5379,5392;, - 3;5447,5418,5415;, - 3;5448,5453,5450;, - 3;5451,5421,5419;, - 3;5416,5422,5459;, - 3;5449,5460,5456;, - 3;5457,5423,5454;, - 3;5462,5427,5424;, - 3;5463,5468,5465;, - 3;5466,5430,5428;, - 3;5425,5431,5433;, - 3;5464,5434,5471;, - 3;5472,5432,5469;, - 3;5474,5439,5436;, - 3;5475,5479,5477;, - 3;5478,5441,5439;, - 3;5437,5442,5444;, - 3;5476,5445,5482;, - 3;5483,5443,5480;, - 3;5517,5488,5485;, - 3;5518,5523,5520;, - 3;5521,5491,5489;, - 3;5486,5492,5529;, - 3;5519,5530,5526;, - 3;5527,5493,5524;, - 3;5532,5497,5494;, - 3;5533,5538,5535;, - 3;5536,5500,5498;, - 3;5495,5501,5503;, - 3;5534,5504,5541;, - 3;5542,5502,5539;, - 3;5544,5509,5506;, - 3;5545,5549,5547;, - 3;5548,5511,5509;, - 3;5507,5512,5514;, - 3;5546,5515,5552;, - 3;5553,5513,5550;, - 3;5587,5558,5555;, - 3;5588,5593,5590;, - 3;5591,5561,5559;, - 3;5556,5562,5599;, - 3;5589,5600,5596;, - 3;5597,5563,5594;, - 3;5602,5567,5564;, - 3;5603,5608,5605;, - 3;5606,5570,5568;, - 3;5565,5571,5573;, - 3;5604,5574,5611;, - 3;5612,5572,5609;, - 3;1063,1067,1161;, - 3;5615,5619,5617;, - 3;5618,5581,5579;, - 3;5577,5582,5584;, - 3;5616,5585,5622;, - 3;5623,5583,5620;, - 3;5657,5628,5625;, - 3;5658,5663,5660;, - 3;5661,5631,5629;, - 3;5626,5632,5669;, - 3;5659,5670,5666;, - 3;5667,5633,5664;, - 3;5672,5637,5634;, - 3;5673,5678,5675;, - 3;5676,5640,5638;, - 3;5635,5641,5643;, - 3;5674,5644,5681;, - 3;5682,5642,5679;, - 3;5684,5649,5646;, - 3;5685,5689,5687;, - 3;5688,5651,5649;, - 3;5647,5652,5654;, - 3;5686,5655,5692;, - 3;5693,5653,5690;, - 3;5716,5721,5718;, - 3;5713,5722,5717;, - 3;5695,5714,5713;, - 3;5697,5701,5696;, - 3;5698,5703,5697;, - 3;5700,5704,5699;, - 3;5719,5706,5700;, - 3;5718,5724,5720;, - 3;5726,5721,5723;, - 3;5715,5722,5714;, - 3;5707,5714,5702;, - 3;5709,5701,5703;, - 3;5710,5703,5705;, - 3;5712,5704,5706;, - 3;5729,5706,5725;, - 3;5728,5724,5721;, - 3;5752,5757,5754;, - 3;5749,5758,5753;, - 3;5731,5750,5749;, - 3;5733,5737,5732;, - 3;5734,5739,5733;, - 3;5736,5740,5735;, - 3;5755,5742,5736;, - 3;5754,5760,5756;, - 3;5762,5757,5759;, - 3;5751,5758,5750;, - 3;5743,5750,5738;, - 3;5745,5737,5739;, - 3;5746,5739,5741;, - 3;5748,5740,5742;, - 3;5765,5742,5761;, - 3;5764,5760,5757;, - 3;5791,5796,5794;, - 3;5801,5796,5804;, - 3;5798,5809,5807;, - 3;5805,5767,5802;, - 3;5775,5781,5778;, - 3;5785,5781,5783;, - 3;5779,5811,5776;, - 3;5788,5773,5771;, - 3;5768,5812,5810;, - 3;5809,5813,5807;, - 3;5808,5772,5769;, - 3;5770,5773,5767;, - 3;5769,5806,5808;, - 3;5797,5799,5808;, - 3;5806,5797,5808;, - 3;5768,5810,5803;, - 3;5803,5810,5795;, - 3;5795,5810,5792;, - 3;5772,5814,5780;, - 3;5772,5782,5789;, - 3;5772,5780,5782;, - 3;5774,5786,5812;, - 3;5784,5777,5812;, - 3;5786,5784,5812;, - 3;5852,5837,5834;, - 3;5852,5840,5837;, - 3;5852,5843,5840;, - 3;5843,5852,5846;, - 3;5846,5852,5849;, - 3;5849,5852,5834;, - 3;5815,5819,5816;, - 3;5815,5816,5822;, - 3;5815,5822,5825;, - 3;5825,5828,5815;, - 3;5828,5831,5815;, - 3;5831,5819,5815;, - 3;5817,5841,5823;, - 3;5824,5844,5826;, - 3;5827,5847,5829;, - 3;5830,5850,5832;, - 3;5833,5835,5820;, - 3;5821,5838,5818;, - 3;5890,5875,5872;, - 3;5890,5878,5875;, - 3;5890,5881,5878;, - 3;5881,5890,5884;, - 3;5884,5890,5887;, - 3;5887,5890,5872;, - 3;5853,5857,5854;, - 3;5853,5854,5860;, - 3;5853,5860,5863;, - 3;5863,5866,5853;, - 3;5866,5869,5853;, - 3;5869,5857,5853;, - 3;5855,5879,5861;, - 3;5862,5882,5864;, - 3;5865,5885,5867;, - 3;5868,5888,5870;, - 3;5871,5873,5858;, - 3;5859,5876,5856;, - 3;5941,5946,5948;, - 3;5931,5943,5942;, - 3;5949,5932,5931;, - 3;5954,5951,5950;, - 3;5954,5959,5955;, - 3;5957,5963,5960;, - 3;5962,5967,5963;, - 3;5965,5946,5968;, - 3;5969,5947,5970;, - 3;5964,5969,5970;, - 3;5961,5964,5970;, - 3;5956,5961,5970;, - 3;5956,5970,5952;, - 3;5952,5970,5933;, - 3;5933,5970,5944;, - 3;5944,5970,5947;, - 3;5901,5925,5928;, - 3;5901,5904,5925;, - 3;5925,5912,5971;, - 3;5925,5904,5912;, - 3;5902,5929,5891;, - 3;5891,5929,5915;, - 3;5930,5926,5916;, - 3;5916,5926,5917;, - 3;5927,5972,5918;, - 3;5918,5972,5934;, - 3;5913,5907,5973;, - 3;5907,5935,5973;, - 3;5905,5893,5914;, - 3;5893,5908,5914;, - 3;5903,5892,5906;, - 3;5892,5894,5906;, - 3;5895,5919,5898;, - 3;5895,5921,5919;, - 3;5919,5909,5898;, - 3;5919,5938,5909;, - 3;5892,5899,5894;, - 3;5892,5896,5899;, - 3;5916,5917,5922;, - 3;5923,5918,5920;, - 3;5891,5915,5897;, - 3;5915,5924,5897;, - 3;5893,5910,5908;, - 3;5893,5900,5910;, - 3;5939,5936,5907;, - 3;5911,5939,5907;, - 3;5920,5918,5940;, - 3;5918,5937,5940;, - 3;5977,5982,5984;, - 3;5974,5979,5978;, - 3;5985,5975,5974;, - 3;5990,5987,5986;, - 3;5990,5995,5991;, - 3;5993,5999,5996;, - 3;5998,6003,5999;, - 3;6001,5982,6004;, - 3;6005,5983,6006;, - 3;6000,6005,6006;, - 3;5997,6000,6006;, - 3;5992,5997,6006;, - 3;5992,6006,5988;, - 3;5988,6006,5976;, - 3;5976,6006,5980;, - 3;5980,6006,5983;, - 3;6010,6015,6017;, - 3;6007,6012,6011;, - 3;6018,6008,6007;, - 3;6023,6020,6019;, - 3;6023,6028,6024;, - 3;6026,6032,6029;, - 3;6031,6036,6032;, - 3;6034,6015,6037;, - 3;6038,6016,6039;, - 3;6033,6038,6039;, - 3;6030,6033,6039;, - 3;6025,6030,6039;, - 3;6025,6039,6021;, - 3;6021,6039,6009;, - 3;6009,6039,6013;, - 3;6013,6039,6016;, - 3;6090,6095,6092;, - 3;6080,6093,6081;, - 3;6098,6081,6100;, - 3;6103,6101,6104;, - 3;6103,6108,6106;, - 3;6107,6112,6111;, - 3;6111,6116,6114;, - 3;6115,6095,6097;, - 3;6117,6119,6096;, - 3;6113,6119,6117;, - 3;6109,6119,6113;, - 3;6105,6119,6109;, - 3;6105,6102,6119;, - 3;6102,6082,6119;, - 3;6082,6094,6119;, - 3;6094,6096,6119;, - 3;6050,6077,6074;, - 3;6050,6074,6053;, - 3;6074,6120,6061;, - 3;6074,6061,6053;, - 3;6051,6040,6078;, - 3;6040,6064,6078;, - 3;6079,6065,6075;, - 3;6065,6066,6075;, - 3;6076,6067,6121;, - 3;6067,6083,6121;, - 3;6062,6122,6056;, - 3;6056,6122,6084;, - 3;6054,6063,6042;, - 3;6042,6063,6057;, - 3;6052,6055,6041;, - 3;6041,6055,6043;, - 3;6044,6047,6068;, - 3;6044,6068,6070;, - 3;6068,6047,6058;, - 3;6068,6058,6087;, - 3;6041,6043,6048;, - 3;6041,6048,6045;, - 3;6065,6071,6066;, - 3;6072,6069,6067;, - 3;6040,6046,6064;, - 3;6064,6046,6073;, - 3;6042,6057,6059;, - 3;6042,6059,6049;, - 3;6088,6056,6085;, - 3;6060,6056,6088;, - 3;6069,6089,6067;, - 3;6067,6089,6086;, - 3;6126,6131,6128;, - 3;6123,6129,6124;, - 3;6134,6124,6136;, - 3;6139,6137,6140;, - 3;6139,6144,6142;, - 3;6143,6148,6147;, - 3;6147,6152,6150;, - 3;6151,6131,6133;, - 3;6153,6155,6132;, - 3;6149,6155,6153;, - 3;6145,6155,6149;, - 3;6141,6155,6145;, - 3;6141,6138,6155;, - 3;6138,6125,6155;, - 3;6125,6130,6155;, - 3;6130,6132,6155;, - 3;6159,6164,6161;, - 3;6156,6162,6157;, - 3;6167,6157,6169;, - 3;6172,6170,6173;, - 3;6172,6177,6175;, - 3;6176,6181,6180;, - 3;6180,6185,6183;, - 3;6184,6164,6166;, - 3;6186,6188,6165;, - 3;6182,6188,6186;, - 3;6178,6188,6182;, - 3;6174,6188,6178;, - 3;6174,6171,6188;, - 3;6171,6158,6188;, - 3;6158,6163,6188;, - 3;6163,6165,6188;, - 3;1063,1161,1747;, - 3;1068,1073,1035;, - 3;1064,1730,1705;, - 3;1074,1044,1152;, - 3;1042,1706,1745;, - 3;1069,1040,1046;, - 3;1039,1037,1042;, - 3;1071,1065,1043;, - 3;1070,1067,1063;, - 3;1066,1046,1044;, - 3;1066,1074,1162;, - 3;1163,1153,1155;, - 3;1046,1157,1152;, - 3;1746,1748,1160;, - 3;1047,2279,0;, - 3;740,1936,2279;, - 3;2,3,1936;, - 3;446,763,764;, - 3;762,4,5;, - 3;446,447,6;, - 3;420,736,737;, - 3;1958,8,1959;, - 3;425,427,193;, - 3;426,739,766;, - 3;1917,1920,737;, - 3;1962,1960,766;, - 3;421,424,427;, - 3;738,739,426;, - 3;738,1921,1962;, - 3;1918,1958,1961;, - 3;1075,2108,1749;, - 3;196,91,94;, - 3;91,93,96;, - 3;767,773,463;, - 3;466,464,468;, - 3;93,236,97;, - 3;470,469,478;, - 3;467,237,448;, - 3;237,234,195;, - 3;471,238,237;, - 3;238,92,234;, - 3;471,473,239;, - 3;238,239,235;, - 3;770,769,449;, - 3;199,450,449;, - 3;478,241,240;, - 3;241,98,236;, - 3;242,204,201;, - 3;84,202,201;, - 3;455,458,459;, - 3;456,203,205;, - 3;452,460,243;, - 3;202,85,86;, - 3;99,242,243;, - 3;84,99,100;, - 3;178,222,244;, - 3;180,225,227;, - 3;229,247,248;, - 3;245,212,214;, - 3;211,187,189;, - 3;185,189,187;, - 3;192,233,222;, - 3;228,226,229;, - 3;210,217,190;, - 3;209,244,250;, - 3;244,222,232;, - 3;178,191,186;, - 3;233,227,232;, - 3;192,186,227;, - 3;774,1078,1048;, - 3;743,1052,223;, - 3;1053,1080,246;, - 3;1079,778,212;, - 3;777,746,188;, - 3;744,183,188;, - 3;224,1051,1053;, - 3;747,741,1048;, - 3;775,742,746;, - 3;1076,1080,1053;, - 3;776,778,1079;, - 3;748,1056,1050;, - 3;1055,1049,1053;, - 3;742,749,744;, - 3;72,429,163;, - 3;61,139,385;, - 3;65,142,137;, - 3;386,433,76;, - 3;431,430,73;, - 3;144,148,169;, - 3;173,171,434;, - 3;146,390,435;, - 3;145,11,389;, - 3;391,1875,1922;, - 3;1874,393,394;, - 3;1923,1876,1878;, - 3;1881,1930,1926;, - 3;1924,1928,439;, - 3;1929,443,440;, - 3;438,441,395;, - 3;442,399,395;, - 3;12,150,151;, - 3;400,1883,1880;, - 3;13,1881,1879;, - 3;155,153,397;, - 3;149,400,396;, - 3;2214,2215,2315;, - 3;2214,1753,1755;, - 3;1758,2221,2215;, - 3;2218,1762,1753;, - 3;1164,1758,1755;, - 3;1760,1763,6191;, - 3;1765,6192,6191;, - 3;2219,2222,1764;, - 3;2223,1766,1764;, - 3;2319,2317,2321;, - 3;2327,2330,2324;, - 3;2224,2328,2322;, - 3;2316,2217,2226;, - 3;1754,6191,1767;, - 3;6192,1769,1767;, - 3;2329,2223,2222;, - 3;2219,2320,2326;, - 3;1770,2229,2230;, - 3;2220,1759,1773;, - 3;2216,2220,2231;, - 3;2229,2225,2228;, - 3;1168,1171,1172;, - 3;1757,1768,1170;, - 3;1759,1166,1173;, - 3;1767,1769,1771;, - 3;479,483,485;, - 3;1775,1175,1176;, - 3;2232,1775,1777;, - 3;1176,1175,1178;, - 3;479,489,1180;, - 3;1182,1183,1779;, - 3;1184,1781,1779;, - 3;1780,1779,2236;, - 3;1781,2237,2236;, - 3;15,2239,1783;, - 3;2240,1785,1783;, - 3;491,494,495;, - 3;495,494,497;, - 3;502,504,505;, - 3;508,511,506;, - 3;513,514,515;, - 3;514,518,519;, - 3;486,484,521;, - 3;527,528,519;, - 3;1186,1188,495;, - 3;1189,496,495;, - 3;1189,1188,1183;, - 3;1186,1184,1183;, - 3;1190,1192,1193;, - 3;1196,1197,1193;, - 3;1196,1192,505;, - 3;1190,508,505;, - 3;1197,1784,1783;, - 3;1785,1194,1193;, - 3;513,517,493;, - 3;520,526,522;, - 3;503,507,528;, - 3;1179,1187,501;, - 3;480,501,498;, - 3;482,499,493;, - 3;523,493,517;, - 3;1174,1185,1187;, - 3;1776,1782,1185;, - 3;2233,2238,1782;, - 3;1181,1191,1195;, - 3;1177,1195,1786;, - 3;1778,1786,2241;, - 3;490,509,1191;, - 3;487,512,509;, - 3;525,507,510;, - 3;519,528,507;, - 3;1198,1788,1789;, - 3;1787,1793,1794;, - 3;1204,1208,1795;, - 3;1210,1211,1212;, - 3;1201,1791,1796;, - 3;1199,1203,1211;, - 3;1199,1210,1213;, - 3;1213,1212,1207;, - 3;1202,1209,1212;, - 3;1214,2243,2244;, - 3;1214,1219,1220;, - 3;1221,1226,1228;, - 3;2245,2246,1230;, - 3;2242,1215,1232;, - 3;1217,2245,2246;, - 3;2242,1215,1232;, - 3;1215,1225,1229;, - 3;1231,1227,1222;, - 3;2248,2332,2333;, - 3;2331,2335,17;, - 3;2249,18,2335;, - 3;78,81,68;, - 3;82,75,167;, - 3;164,177,175;, - 3;428,444,176;, - 3;387,401,445;, - 3;401,388,138;, - 3;156,140,141;, - 3;158,143,66;, - 3;62,71,70;, - 3;64,68,71;, - 3;74,83,80;, - 3;432,445,444;, - 3;1081,1082,19;, - 3;21,22,1082;, - 3;2108,23,1797;, - 3;24,1075,1751;, - 3;469,475,529;, - 3;771,780,476;, - 3;94,103,218;, - 3;96,104,102;, - 3;241,478,529;, - 3;458,461,25;, - 3;207,221,461;, - 3;88,89,220;, - 3;101,26,89;, - 3;464,477,474;, - 3;97,106,104;, - 3;241,252,105;, - 3;1750,1798,1800;, - 3;451,200,219;, - 3;451,462,779;, - 3;1963,1966,1967;, - 3;1968,1967,2109;, - 3;2111,2110,2109;, - 3;1964,2112,2114;, - 3;1937,1963,1968;, - 3;1939,1968,2110;, - 3;2081,2110,2111;, - 3;1938,2083,2112;, - 3;1884,1887,2256;, - 3;1931,2262,2263;, - 3;1932,1889,2258;, - 3;2263,2262,2260;, - 3;1935,1893,1890;, - 3;159,1885,1889;, - 3;27,162,1891;, - 3;28,1888,1886;, - 3;1552,916,1554;, - 3;916,980,1626;, - 3;980,1630,1631;, - 3;1558,1559,1560;, - 3;1555,1562,1559;, - 3;1627,1634,1561;, - 3;1632,1635,1633;, - 3;1632,1629,1636;, - 3;1629,982,983;, - 3;981,918,919;, - 3;917,1553,1560;, - 3;1563,1566,1567;, - 3;921,1567,1637;, - 3;985,1637,1640;, - 3;1565,1564,1560;, - 3;1568,1565,1559;, - 3;1638,1569,1561;, - 3;1641,1639,1633;, - 3;1641,1635,1636;, - 3;1643,1636,983;, - 3;987,984,919;, - 3;923,920,1560;, - 3;1570,1573,1575;, - 3;1580,1585,1575;, - 3;1578,1587,1588;, - 3;1583,1582,924;, - 3;1446,1451,1452;, - 3;1456,1454,1452;, - 3;1449,1448,1590;, - 3;1460,929,930;, - 3;925,1589,1591;, - 3;1588,1587,1592;, - 3;1586,927,928;, - 3;926,924,930;, - 3;852,854,793;, - 3;1341,1347,1981;, - 3;2013,2017,1462;, - 3;876,1468,880;, - 3;880,1468,1469;, - 3;794,855,1436;, - 3;1351,799,795;, - 3;877,1477,1470;, - 3;1471,1480,1481;, - 3;2017,1482,1478;, - 3;1437,1441,1346;, - 3;1350,1346,1342;, - 3;1483,1466,1463;, - 3;1474,1486,1480;, - 3;884,886,887;, - 3;2018,2020,2022;, - 3;1487,1490,886;, - 3;1488,1493,1494;, - 3;2025,2023,1495;, - 3;852,887,886;, - 3;2020,1987,1983;, - 3;855,886,1497;, - 3;1496,1499,1498;, - 3;1438,1498,1499;, - 3;1439,1500,2023;, - 3;882,881,884;, - 3;880,1472,1487;, - 3;1473,1481,1493;, - 3;1482,2017,2025;, - 3;2017,2016,2018;, - 3;856,802,804;, - 3;1355,1990,1992;, - 3;2026,1503,1504;, - 3;891,895,897;, - 3;897,1508,1510;, - 3;805,1363,1442;, - 3;1365,1364,806;, - 3;892,1507,1511;, - 3;1512,1509,1517;, - 3;2029,1504,1520;, - 3;1443,1362,1361;, - 3;1362,1367,1356;, - 3;1522,1521,1505;, - 3;1514,1512,1519;, - 3;899,902,903;, - 3;2030,2033,2034;, - 3;1526,900,905;, - 3;1527,1529,1531;, - 3;2032,1535,1532;, - 3;856,858,905;, - 3;2036,2034,1994;, - 3;859,1442,1536;, - 3;1533,1530,1537;, - 3;1443,1445,1540;, - 3;1444,1993,2035;, - 3;895,902,899;, - 3;897,900,1526;, - 3;1509,1527,1534;, - 3;1518,1535,2032;, - 3;2029,2033,2030;, - 3;904,901,890;, - 3;901,896,883;, - 3;896,894,878;, - 3;893,1516,1475;, - 3;1515,1525,1484;, - 3;1524,1502,1465;, - 3;1502,2028,2014;, - 3;2027,2031,2019;, - 3;2031,2037,2021;, - 3;2037,1991,1985;, - 3;1989,1358,1343;, - 3;1357,1368,1353;, - 3;1366,803,797;, - 3;801,857,853;, - 3;857,904,888;, - 3;1138,1132,1133;, - 3;1009,1012,988;, - 3;1009,1016,1018;, - 3;1139,1143,1144;, - 3;993,990,988;, - 3;999,1134,1148;, - 3;1022,1000,999;, - 3;1144,1024,1027;, - 3;1019,1017,1027;, - 3;1119,1123,932;, - 3;937,939,934;, - 3;1148,1150,1029;, - 3;1021,1029,1031;, - 3;1033,1003,989;, - 3;1033,1013,1020;, - 3;1120,1125,1126;, - 3;1133,1132,1126;, - 3;939,937,941;, - 3;994,998,946;, - 3;1000,1007,1005;, - 3;997,989,950;, - 3;999,1008,1136;, - 3;951,1129,1136;, - 3;951,1008,1004;, - 3;999,1000,1004;, - 3;940,950,953;, - 3;989,1003,953;, - 3;1149,1135,1131;, - 3;1023,1011,991;, - 3;1030,1151,1146;, - 3;1150,1148,1141;, - 3;1022,1031,1014;, - 3;1032,1030,1028;, - 3;1006,944,938;, - 3;1007,995,943;, - 3;1007,1000,992;, - 3;1135,1137,1127;, - 3;1129,1124,1128;, - 3;952,933,1122;, - 3;949,938,933;, - 3;1267,1270,1288;, - 3;711,1269,1290;, - 3;589,711,718;, - 3;592,591,642;, - 3;594,592,643;, - 3;597,596,645;, - 3;1272,597,646;, - 3;1270,1274,1292;, - 3;304,294,318;, - 3;373,364,365;, - 3;293,296,322;, - 3;304,306,295;, - 3;374,365,367;, - 3;296,563,603;, - 3;305,574,561;, - 3;573,651,604;, - 3;335,373,374;, - 3;320,323,366;, - 3;335,321,364;, - 3;336,374,375;, - 3;650,375,367;, - 3;323,606,368;, - 3;564,569,298;, - 3;302,300,324;, - 3;303,329,607;, - 3;328,326,587;, - 3;299,560,588;, - 3;570,607,1842;, - 3;608,587,1845;, - 3;560,1828,1846;, - 3;566,1827,1829;, - 3;1826,1844,1847;, - 3;1233,1237,1247;, - 3;1238,1233,1249;, - 3;1238,1250,1810;, - 3;1240,1806,1812;, - 3;1244,1235,1234;, - 3;1244,1239,1802;, - 3;1236,1243,1251;, - 3;1803,1811,1813;, - 3;253,531,532;, - 3;254,109,110;, - 3;116,29,257;, - 3;535,259,260;, - 3;30,544,538;, - 3;533,530,540;, - 3;545,547,541;, - 3;534,542,261;, - 3;546,271,261;, - 3;256,261,111;, - 3;271,117,111;, - 3;539,540,530;, - 3;258,537,531;, - 3;543,545,540;, - 3;53,118,112;, - 3;53,48,50;, - 3;55,52,114;, - 3;118,273,262;, - 3;119,114,265;, - 3;272,275,266;, - 3;49,113,115;, - 3;113,264,267;, - 3;1594,1599,1542;, - 3;1595,957,958;, - 3;1598,960,906;, - 3;1596,1545,908;, - 3;956,909,907;, - 3;963,970,1607;, - 3;969,973,1610;, - 3;972,976,1645;, - 3;975,979,1648;, - 3;978,967,1601;, - 3;966,964,1605;, - 3;1546,1551,1995;, - 3;1547,912,913;, - 3;1550,915,860;, - 3;1999,1997,861;, - 3;1548,2000,864;, - 3;911,865,862;, - 3;1089,1094,1095;, - 3;1099,1104,2152;, - 3;729,1894,1896;, - 3;2158,2161,2162;, - 3;1894,1900,1901;, - 3;1105,1108,866;, - 3;870,873,868;, - 3;1100,874,867;, - 3;1102,1106,869;, - 3;2156,2001,874;, - 3;2002,871,874;, - 3;2153,1102,875;, - 3;872,2004,2003;, - 3;2168,2005,2001;, - 3;2007,2002,2001;, - 3;2170,2153,2003;, - 3;2004,2012,2009;, - 3;2171,2010,2006;, - 3;2011,2008,2006;, - 3;730,734,873;, - 3;733,1897,2004;, - 3;731,871,2002;, - 3;1897,1903,2012;, - 3;1898,2008,2011;, - 3;1895,2002,2007;, - 3;1107,1110,1111;, - 3;1101,1113,1114;, - 3;1106,1102,1115;, - 3;1108,1105,1118;, - 3;2156,2173,2175;, - 3;2169,2176,2177;, - 3;2153,2170,2178;, - 3;2157,2154,2180;, - 3;1110,1091,1098;, - 3;1117,1115,1096;, - 3;1109,1118,1093;, - 3;2173,2159,2166;, - 3;2176,2167,2163;, - 3;2179,2178,2164;, - 3;1112,2174,2181;, - 3;1115,2179,2160;, - 3;1097,1095,2161;, - 3;1111,1098,2159;, - 3;1369,1372,807;, - 3;1374,1377,1378;, - 3;1382,1384,1386;, - 3;1371,1370,1386;, - 3;1379,812,1385;, - 3;808,1373,1385;, - 3;1387,1391,1393;, - 3;1395,818,814;, - 3;1380,1376,819;, - 3;811,809,813;, - 3;815,819,1376;, - 3;1394,1392,1375;, - 3;1389,1377,1374;, - 3;1396,1394,1386;, - 3;816,811,819;, - 3;1397,1369,810;, - 3;1398,822,823;, - 3;1399,1403,1404;, - 3;1402,825,826;, - 3;820,1412,827;, - 3;1400,1409,1410;, - 3;1408,1406,828;, - 3;1413,831,832;, - 3;1414,1418,1419;, - 3;1417,834,835;, - 3;829,840,836;, - 3;1415,1424,838;, - 3;1423,1421,837;, - 3;1425,843,844;, - 3;1426,1429,1430;, - 3;1428,844,846;, - 3;841,851,847;, - 3;1427,1435,849;, - 3;1434,1432,848;, - 3;1670,1673,1674;, - 3;1650,1670,1676;, - 3;1656,1652,1654;, - 3;1678,1658,1660;, - 3;1678,1680,1682;, - 3;1707,1712,1713;, - 3;1717,1715,1686;, - 3;1708,1721,1726;, - 3;1711,1725,1724;, - 3;1709,1718,1723;, - 3;1714,1724,1675;, - 3;1688,1686,1674;, - 3;1718,1689,1672;, - 3;2264,2266,2280;, - 3;2266,2284,2285;, - 3;2264,2281,2287;, - 3;2271,2273,2274;, - 3;2277,2275,2289;, - 3;2290,2289,2292;, - 3;2295,2293,2298;, - 3;2299,2298,2301;, - 3;2084,2089,1940;, - 3;2273,2271,1943;, - 3;2302,2301,2088;, - 3;2265,2271,2276;, - 3;2282,2280,2300;, - 3;2268,2278,2291;, - 3;2283,2291,2296;, - 3;2285,2297,2300;, - 3;2287,2281,2303;, - 3;2270,2288,2087;, - 3;2264,2269,1945;, - 3;571,1266,1278;, - 3;268,1245,1266;, - 3;1266,1831,1848;, - 3;1245,1809,1831;, - 3;610,653,575;, - 3;1279,1296,652;, - 3;1849,1852,1296;, - 3;1832,1833,1851;, - 3;1807,1815,1833;, - 3;1246,1252,1814;, - 3;1252,1246,269;, - 3;277,270,572;, - 3;612,713,715;, - 3;612,1281,1322;, - 3;618,621,1282;, - 3;618,625,626;, - 3;1285,1281,612;, - 3;629,634,635;, - 3;330,631,639;, - 3;623,620,632;, - 3;619,614,636;, - 3;616,640,637;, - 3;714,719,720;, - 3;1280,1297,1326;, - 3;717,721,654;, - 3;622,628,656;, - 3;1283,1299,1300;, - 3;624,660,657;, - 3;332,339,340;, - 3;1287,1301,1297;, - 3;1324,1327,719;, - 3;622,658,1298;, - 3;331,341,659;, - 3;616,655,338;, - 3;1712,1728,1720;, - 3;1727,1722,1684;, - 3;2115,2119,2120;, - 3;2122,2120,2341;, - 3;2348,2352,2399;, - 3;2124,2336,2338;, - 3;2336,2405,2407;, - 3;2400,2407,2405;, - 3;2304,2123,2345;, - 3;2339,2408,2406;, - 3;2127,2117,2123;, - 3;2128,2339,2337;, - 3;2357,2349,2403;, - 3;2408,2410,2404;, - 3;2306,2121,2118;, - 3;2121,2306,2358;, - 3;2308,2360,2409;, - 3;2305,2355,2360;, - 3;2340,2128,2131;, - 3;2308,2131,2127;, - 3;2346,2343,2350;, - 3;2409,2360,2357;, - 3;2125,2133,2132;, - 3;2127,2132,2133;, - 3;2347,2349,2357;, - 3;6189,6194,2307;, - 3;6190,2126,2338;, - 3;6198,2338,2407;, - 3;6194,6195,2359;, - 3;6199,2407,2400;, - 3;6196,6201,2399;, - 3;6195,6197,2353;, - 3;2361,2365,2366;, - 3;2362,31,2371;, - 3;2364,2372,2373;, - 3;2370,2368,2374;, - 3;2375,2376,2378;, - 3;2376,2375,2381;, - 3;2309,2375,2380;, - 3;2310,2381,2375;, - 3;2386,2390,2384;, - 3;2391,2392,2393;, - 3;2391,2395,2388;, - 3;2312,2386,2382;, - 3;2314,34,2392;, - 3;2314,2391,2387;, - 3;2385,2397,2379;, - 3;2398,2389,2396;, - 3;2398,2397,2385;, - 3;934,1613,1731;, - 3;1120,1732,1733;, - 3;1125,1733,1737;, - 3;1133,1737,1739;, - 3;1143,1740,1741;, - 3;1144,1741,1692;, - 3;1694,1034,1026;, - 3;1002,1034,1694;, - 3;954,1002,1662;, - 3;936,954,1614;, - 3;2197,1743,1738;, - 3;2065,2051,1663;, - 3;2065,1695,1697;, - 3;2198,2202,1744;, - 3;2054,1667,1663;, - 3;2057,2072,2204;, - 3;2073,2072,2057;, - 3;1744,2202,2075;, - 3;1698,1700,2075;, - 3;1734,1615,2039;, - 3;2041,2039,1615;, - 3;2204,2072,2077;, - 3;2072,2073,2079;, - 3;1703,1696,1664;, - 3;1703,1702,1699;, - 3;1735,2185,2186;, - 3;1738,1736,2186;, - 3;1618,1622,2043;, - 3;2055,2046,1620;, - 3;2058,2062,2060;, - 3;1666,1621,1623;, - 3;2057,2193,2195;, - 3;2049,2064,2195;, - 3;2049,2047,2062;, - 3;2057,2064,2062;, - 3;1619,1617,1624;, - 3;1664,1623,1624;, - 3;2205,2200,2192;, - 3;2074,2059,2052;, - 3;2078,2076,2201;, - 3;2206,2203,2199;, - 3;2073,2067,2070;, - 3;2080,2071,2076;, - 3;2061,2048,2042;, - 3;2063,2060,2045;, - 3;2063,2056,2053;, - 3;2194,2192,2187;, - 3;2189,2195,2188;, - 3;2050,2190,2184;, - 3;2048,2050,2040;, - 3;1615,1734,1731;, - 3;1735,1736,1733;, - 3;1736,1738,1737;, - 3;1738,1743,1739;, - 3;1742,1744,1741;, - 3;1744,1700,1692;, - 3;1694,1693,1701;, - 3;1669,1662,1694;, - 3;1625,1614,1662;, - 3;1616,1612,1614;, - 3;2134,1729,1747;, - 3;2139,2092,2093;, - 3;2135,2098,1705;, - 3;2145,2254,2208;, - 3;2096,2210,1745;, - 3;2140,2138,2101;, - 3;2091,2100,2096;, - 3;2143,2095,2097;, - 3;2141,2144,2134;, - 3;2138,2145,2099;, - 3;2138,2252,2254;, - 3;2255,2253,2211;, - 3;2101,2099,2208;, - 3;1746,2213,2251;, - 3;781,1338,1339;, - 3;1083,1059,1060;, - 3;782,752,1333;, - 3;790,791,753;, - 3;750,758,1335;, - 3;1084,789,757;, - 3;1058,756,750;, - 3;1087,1062,751;, - 3;1085,1088,781;, - 3;789,790,755;, - 3;789,786,791;, - 3;792,787,759;, - 3;757,755,753;, - 3;1336,761,785;, - 3;1969,1974,1339;, - 3;2146,2151,2102;, - 3;1970,1337,1333;, - 3;1978,1949,1950;, - 3;1947,1334,1335;, - 3;2147,2107,1953;, - 3;2106,2104,1947;, - 3;2149,1971,1948;, - 3;2148,1972,1969;, - 3;1973,1953,1949;, - 3;1973,1978,1979;, - 3;1980,1951,1955;, - 3;1953,1957,1950;, - 3;1336,1340,1977;, - 3;1302,1289,1288;, - 3;722,718,1290;, - 3;661,641,718;, - 3;664,643,642;, - 3;666,644,643;, - 3;669,646,645;, - 3;1307,1291,646;, - 3;1305,1288,1292;, - 3;304,334,342;, - 3;37,38,381;, - 3;308,345,346;, - 3;304,307,310;, - 3;38,39,383;, - 3;309,346,671;, - 3;305,311,577;, - 3;573,578,672;, - 3;335,337,38;, - 3;343,380,382;, - 3;335,37,379;, - 3;337,650,39;, - 3;650,674,383;, - 3;347,382,384;, - 3;579,314,315;, - 3;312,350,355;, - 3;313,40,675;, - 3;349,676,709;, - 3;317,357,710;, - 3;40,1834,1853;, - 3;676,1855,1859;, - 3;41,710,1860;, - 3;581,586,1840;, - 3;1836,1841,1861;, - 3;1253,1249,1247;, - 3;1258,1250,1249;, - 3;1258,1818,1810;, - 3;1260,1251,1812;, - 3;42,1259,1254;, - 3;42,1820,1816;, - 3;1257,1248,1251;, - 3;1817,1821,1813;, - 3;278,280,550;, - 3;279,43,123;, - 3;116,123,43;, - 3;553,556,44;, - 3;30,44,556;, - 3;551,558,45;, - 3;545,45,558;, - 3;552,281,46;, - 3;546,559,46;, - 3;281,122,124;, - 3;271,46,124;, - 3;557,555,549;, - 3;283,278,548;, - 3;543,557,45;, - 3;53,56,125;, - 3;53,54,58;, - 3;55,119,127;, - 3;118,125,284;, - 3;119,274,287;, - 3;272,286,288;, - 3;57,60,128;, - 3;126,128,289;, - 3;582,678,1310;, - 3;290,582,47;, - 3;47,1310,1856;, - 3;1264,47,1837;, - 3;677,583,575;, - 3;1311,679,652;, - 3;1857,1311,1296;, - 3;1838,1858,1851;, - 3;1823,1838,1833;, - 3;1265,1824,1814;, - 3;1252,276,291;, - 3;277,575,583;, - 3;680,684,726;, - 3;680,724,1330;, - 3;686,1317,1314;, - 3;686,689,694;, - 3;1317,686,680;, - 3;697,708,703;, - 3;351,354,706;, - 3;692,699,701;, - 3;688,702,704;, - 3;683,682,705;, - 3;725,728,720;, - 3;1313,1332,1326;, - 3;727,685,654;, - 3;690,658,656;, - 3;1315,1319,1300;, - 3;693,696,657;, - 3;354,351,340;, - 3;1318,1313,1297;, - 3;1331,725,719;, - 3;690,1316,1298;, - 3;352,692,659;, - 3;683,353,338;, - 3;2444,2447,2452;, - 3;2439,2446,2454;, - 3;2412,2439,2441;, - 3;2415,2414,2424;, - 3;2417,2415,2425;, - 3;2420,2419,2427;, - 3;2449,2420,2428;, - 3;2447,2451,2456;, - 3;2457,2453,2452;, - 3;2442,2441,2454;, - 3;2429,2423,2441;, - 3;2432,2425,2424;, - 3;2434,2426,2425;, - 3;2437,2428,2427;, - 3;2462,2455,2428;, - 3;2460,2452,2456;, - 3;2475,2479,2480;, - 3;2476,2465,2485;, - 3;2478,2486,2487;, - 3;2484,2482,2488;, - 3;2489,2490,2492;, - 3;2490,2489,2495;, - 3;2469,2489,2494;, - 3;2470,2495,2489;, - 3;2500,2504,2498;, - 3;2505,2506,2507;, - 3;2505,2509,2502;, - 3;2472,2500,2496;, - 3;2474,2468,2506;, - 3;2474,2505,2501;, - 3;2499,2511,2493;, - 3;2512,2503,2510;, - 3;2512,2511,2499;, - 3;2521,2534,2533;, - 3;2523,2533,2538;, - 3;2521,2527,2540;, - 3;2528,2531,2274;, - 3;2530,2542,2289;, - 3;2542,2547,2292;, - 3;2544,2548,2298;, - 3;2548,2550,2301;, - 3;2517,2515,1940;, - 3;2273,1941,2513;, - 3;2550,2519,2088;, - 3;2522,2525,2531;, - 3;2535,2551,2549;, - 3;2524,2537,2543;, - 3;2537,2539,2545;, - 3;2538,2533,2549;, - 3;2540,2520,2551;, - 3;2526,2516,2518;, - 3;2521,2529,2514;, - 3;2584,2554,2555;, - 3;2585,2589,2590;, - 3;2588,2557,2558;, - 3;2552,2598,2559;, - 3;2586,2595,2596;, - 3;2594,2592,2560;, - 3;2599,2563,2564;, - 3;2600,2604,2605;, - 3;2603,2566,2567;, - 3;2561,2572,2568;, - 3;2601,2610,2570;, - 3;2609,2607,2569;, - 3;2611,2575,2576;, - 3;2612,2615,2616;, - 3;2614,2576,2578;, - 3;2573,2583,2579;, - 3;2613,2621,2581;, - 3;2620,2618,2580;, - 3;2654,2624,2625;, - 3;2655,2659,2660;, - 3;2658,2627,2628;, - 3;2622,2668,2629;, - 3;2656,2665,2666;, - 3;2664,2662,2630;, - 3;2669,2633,2634;, - 3;2670,2674,2675;, - 3;2673,2636,2637;, - 3;2631,2642,2638;, - 3;2671,2680,2640;, - 3;2679,2677,2639;, - 3;2681,2645,2646;, - 3;2682,2685,2686;, - 3;2684,2646,2648;, - 3;2643,2653,2649;, - 3;2683,2691,2651;, - 3;2690,2688,2650;, - 3;2724,2694,2695;, - 3;2725,2729,2730;, - 3;2728,2697,2698;, - 3;2692,2738,2699;, - 3;2726,2735,2736;, - 3;2734,2732,2700;, - 3;2739,2703,2704;, - 3;2740,2744,2745;, - 3;2743,2706,2707;, - 3;2701,2712,2708;, - 3;2741,2750,2710;, - 3;2749,2747,2709;, - 3;2751,2715,2716;, - 3;2752,2755,2756;, - 3;2754,2716,2718;, - 3;2713,2723,2719;, - 3;2753,2761,2721;, - 3;2760,2758,2720;, - 3;2794,2764,2765;, - 3;2795,2799,2800;, - 3;2798,2767,2768;, - 3;2762,2808,2769;, - 3;2796,2805,2806;, - 3;2804,2802,2770;, - 3;2809,2773,2774;, - 3;2810,2814,2815;, - 3;2813,2776,2777;, - 3;2771,2782,2778;, - 3;2811,2820,2780;, - 3;2819,2817,2779;, - 3;2821,2785,2786;, - 3;2822,2825,2826;, - 3;2824,2786,2788;, - 3;2783,2793,2789;, - 3;2823,2831,2791;, - 3;2830,2828,2790;, - 3;2853,2855,2858;, - 3;2850,2854,2860;, - 3;2832,2850,2851;, - 3;2834,2833,2839;, - 3;2835,2834,2840;, - 3;2837,2836,2842;, - 3;2856,2837,2843;, - 3;2855,2857,2862;, - 3;2863,2859,2858;, - 3;2852,2851,2860;, - 3;2844,2838,2851;, - 3;2846,2840,2839;, - 3;2847,2841,2840;, - 3;2849,2843,2842;, - 3;2866,2861,2843;, - 3;2865,2858,2862;, - 3;2889,2891,2894;, - 3;2886,2890,2896;, - 3;2868,2886,2887;, - 3;2870,2869,2875;, - 3;2871,2870,2876;, - 3;2873,2872,2878;, - 3;2892,2873,2879;, - 3;2891,2893,2898;, - 3;2899,2895,2894;, - 3;2888,2887,2896;, - 3;2880,2874,2887;, - 3;2882,2876,2875;, - 3;2883,2877,2876;, - 3;2885,2879,2878;, - 3;2902,2897,2879;, - 3;2901,2894,2898;, - 3;2928,2931,2933;, - 3;2938,2943,2933;, - 3;2936,2945,2946;, - 3;2941,2940,2904;, - 3;2912,2917,2918;, - 3;2922,2920,2918;, - 3;2915,2914,2948;, - 3;2926,2909,2910;, - 3;2905,2947,2949;, - 3;2946,2945,2950;, - 3;2944,2907,2908;, - 3;2906,2904,2910;, - 3;2954,2961,2978;, - 3;2960,2964,2981;, - 3;2963,2967,2984;, - 3;2966,2970,2987;, - 3;2969,2958,2972;, - 3;2957,2955,2976;, - 3;2992,2999,3016;, - 3;2998,3002,3019;, - 3;3001,3005,3022;, - 3;3004,3008,3025;, - 3;3007,2996,3010;, - 3;2995,2993,3014;, - 3;4008,4663,4680;, - 3;4013,3985,3980;, - 3;4009,3988,4638;, - 3;4019,4106,4096;, - 3;3986,4098,4678;, - 3;4014,4012,3991;, - 3;3984,3990,3986;, - 3;4017,3982,3987;, - 3;4015,4018,4008;, - 3;4012,4019,3989;, - 3;4012,4104,4106;, - 3;4107,4105,4099;, - 3;3991,3989,4096;, - 3;4679,4101,4103;, - 3;3992,3029,3028;, - 3;3689,3992,5175;, - 3;3030,3689,4847;, - 3;446,3414,3711;, - 3;762,3712,3032;, - 3;446,7,3033;, - 3;420,3396,3686;, - 3;1958,4872,4869;, - 3;425,9,3176;, - 3;3399,3177,3713;, - 3;1917,736,3686;, - 3;4871,3688,3713;, - 3;421,425,3398;, - 3;3687,3397,3399;, - 3;3687,3688,4871;, - 3;1918,4836,4872;, - 3;4020,4684,4682;, - 3;3179,3183,3091;, - 3;3088,3092,3093;, - 3;3714,3432,3428;, - 3;3430,3435,3433;, - 3;3090,3093,3094;, - 3;3435,3438,3439;, - 3;3431,3716,3415;, - 3;3216,3415,3178;, - 3;3436,3431,3216;, - 3;3217,3216,3213;, - 3;3436,3217,3218;, - 3;3217,3089,3215;, - 3;3718,3417,3416;, - 3;3181,3180,3416;, - 3;3439,3438,3219;, - 3;3220,3219,3214;, - 3;3221,3419,3184;, - 3;3082,3187,3184;, - 3;3422,3420,3426;, - 3;3423,3425,3188;, - 3;3419,3221,3222;, - 3;3185,3190,3084;, - 3;3096,3097,3222;, - 3;3082,3086,3097;, - 3;3161,3193,3223;, - 3;3163,3169,3206;, - 3;3208,3211,3227;, - 3;3225,3229,3197;, - 3;3195,3199,3172;, - 3;3167,3165,3170;, - 3;3175,3161,3201;, - 3;3207,3211,3208;, - 3;3192,3162,3173;, - 3;3193,3200,3228;, - 3;3223,3230,3210;, - 3;3161,3175,3168;, - 3;3212,3201,3210;, - 3;3175,3212,3206;, - 3;3721,3690,3993;, - 3;3692,3166,3204;, - 3;3998,3209,3226;, - 3;4025,3225,3194;, - 3;3725,3196,3171;, - 3;3693,3695,3171;, - 3;3205,3209,3998;, - 3;3696,4001,3993;, - 3;3722,3725,3695;, - 3;4022,3994,3998;, - 3;3723,4023,4025;, - 3;3697,3694,3997;, - 3;4000,3996,3998;, - 3;3691,3695,3693;, - 3;3074,3154,3150;, - 3;3067,3070,3363;, - 3;3071,3067,3130;, - 3;3364,3070,3078;, - 3;3404,3080,3075;, - 3;3136,3160,3156;, - 3;3159,3034,3406;, - 3;3139,3158,3407;, - 3;3137,3140,3368;, - 3;3369,3409,4837;, - 3;4797,4802,3372;, - 3;4838,4842,4799;, - 3;1881,4801,4840;, - 3;4839,3410,3411;, - 3;1929,4843,3412;, - 3;3408,3371,3373;, - 3;442,3413,3373;, - 3;12,154,3143;, - 3;3376,3375,4800;, - 3;13,4804,4801;, - 3;155,398,3374;, - 3;3142,3145,3375;, - 3;5118,5214,5211;, - 3;5118,5119,4688;, - 3;4691,4688,5119;, - 3;5122,5118,4686;, - 3;4108,4112,4688;, - 3;4694,4687,6193;, - 3;1765,4696,6193;, - 3;5123,4695,4697;, - 3;2223,5126,4697;, - 3;5215,5221,5217;, - 3;2327,5217,5219;, - 3;2224,5127,5218;, - 3;5213,5218,5127;, - 3;4687,4690,4698;, - 3;6192,6193,4698;, - 3;2329,5222,5126;, - 3;5123,5126,5220;, - 3;1770,4701,5130;, - 3;5125,5131,4700;, - 3;5121,5129,5131;, - 3;2229,5130,5128;, - 3;4111,4110,4116;, - 3;4689,4113,4115;, - 3;4692,4700,4117;, - 3;4698,4702,1771;, - 3;3440,3450,3446;, - 3;4703,4705,4120;, - 3;5132,5134,4705;, - 3;4120,4124,4122;, - 3;3440,4122,4124;, - 3;1182,1780,4707;, - 3;4127,4126,4707;, - 3;1780,14,5136;, - 3;4708,4707,5136;, - 3;15,1784,4710;, - 3;5140,5139,4710;, - 3;491,496,3454;, - 3;3454,3459,3455;, - 3;502,3461,3460;, - 3;3463,3460,3461;, - 3;513,3470,3468;, - 3;514,3468,3471;, - 3;3447,3478,3473;, - 3;527,518,3471;, - 3;4129,3459,3454;, - 3;1189,4131,3454;, - 3;1189,1182,4126;, - 3;4129,4131,4126;, - 3;4132,4136,4135;, - 3;1196,4134,4135;, - 3;1196,504,3460;, - 3;4132,4134,3460;, - 3;1197,4135,4710;, - 3;4711,4710,4135;, - 3;513,492,3453;, - 3;3472,3469,3474;, - 3;503,527,3479;, - 3;4123,3441,3458;, - 3;3441,3445,3456;, - 3;3444,3475,3453;, - 3;3475,3468,3470;, - 3;4119,4123,4130;, - 3;4704,4119,4128;, - 3;5133,4704,4709;, - 3;4125,4121,4137;, - 3;4121,4706,4712;, - 3;4706,5135,5141;, - 3;3451,4125,4133;, - 3;3448,3451,3464;, - 3;3477,3449,3467;, - 3;3471,3477,3462;, - 3;4138,4143,4715;, - 3;4714,4717,4720;, - 3;4144,4719,4721;, - 3;4150,4153,4152;, - 3;4140,4149,4722;, - 3;4139,4150,4151;, - 3;4139,4145,4153;, - 3;4153,4145,4147;, - 3;4142,4151,4152;, - 3;4154,4158,5144;, - 3;4154,4164,4160;, - 3;4161,4165,1228;, - 3;5145,4157,1230;, - 3;5143,2247,1232;, - 3;4157,1230,2246;, - 3;5143,2247,1232;, - 3;4155,1232,1229;, - 3;1231,4159,4162;, - 3;5146,3036,5225;, - 3;5224,5226,17;, - 3;5147,5224,2335;, - 3;3079,3069,68;, - 3;82,174,3153;, - 3;3151,3155,175;, - 3;3402,3152,176;, - 3;3365,3405,445;, - 3;401,156,3131;, - 3;156,157,3134;, - 3;158,69,3072;, - 3;3068,3073,70;, - 3;3069,3068,71;, - 3;3077,3081,80;, - 3;3405,3402,444;, - 3;4026,3037,19;, - 3;3038,4026,1082;, - 3;5015,4682,1797;, - 3;24,1799,4684;, - 3;3434,3439,529;, - 3;3719,3428,476;, - 3;3091,3183,218;, - 3;3093,3092,102;, - 3;3220,252,529;, - 3;3424,3426,25;, - 3;3189,3424,461;, - 3;3085,3191,220;, - 3;3098,3085,89;, - 3;3429,3433,474;, - 3;3094,3093,104;, - 3;3220,3095,105;, - 3;4683,4685,1800;, - 3;3418,462,219;, - 3;3418,3720,779;, - 3;4873,4875,1967;, - 3;4875,5016,2109;, - 3;5017,2113,2109;, - 3;4874,1965,2114;, - 3;4848,4850,4875;, - 3;4850,4988,5016;, - 3;4988,4990,5017;, - 3;4849,4874,5018;, - 3;4805,5157,2256;, - 3;4844,1934,2263;, - 3;4845,5159,5154;, - 3;2263,2256,5156;, - 3;1935,4846,4809;, - 3;3146,3149,4808;, - 3;27,1892,4810;, - 3;28,3147,4807;, - 3;4485,4491,4487;, - 3;3861,4487,4559;, - 3;3925,4559,4564;, - 3;4490,4486,4493;, - 3;4488,4490,4492;, - 3;4560,4489,4495;, - 3;4565,4561,4567;, - 3;4565,4568,4569;, - 3;4563,4569,3928;, - 3;3927,3929,3864;, - 3;3863,3865,4493;, - 3;4496,3866,4500;, - 3;3866,3930,4570;, - 3;3930,4576,4573;, - 3;4499,4492,4493;, - 3;4501,4494,4492;, - 3;4571,4566,4495;, - 3;4574,4568,4567;, - 3;4574,4575,4569;, - 3;4575,3932,3928;, - 3;3931,3868,3864;, - 3;3867,4497,4493;, - 3;4503,4512,4508;, - 3;4513,4506,4508;, - 3;4510,4505,4521;, - 3;4517,3872,3869;, - 3;4379,4387,4385;, - 3;4389,4394,4385;, - 3;4383,4525,4523;, - 3;4392,4391,3875;, - 3;3870,3876,4524;, - 3;4521,4523,4525;, - 3;4520,4526,3874;, - 3;3872,3873,3875;, - 3;3797,3743,3738;, - 3;4274,4893,4888;, - 3;4920,4399,4395;, - 3;3821,3827,3825;, - 3;3825,4405,4402;, - 3;3739,4282,4369;, - 3;4284,4283,3740;, - 3;3822,4401,4403;, - 3;4404,4406,4414;, - 3;4924,4395,4412;, - 3;4370,4281,4280;, - 3;4281,4286,4275;, - 3;4416,4413,4396;, - 3;4408,4404,4411;, - 3;3829,3835,3832;, - 3;4925,4932,4929;, - 3;4420,3830,3831;, - 3;4421,4423,4427;, - 3;4931,4426,4428;, - 3;3797,3799,3831;, - 3;4927,4929,4890;, - 3;3800,4369,4430;, - 3;4429,4424,4431;, - 3;4371,4374,4432;, - 3;4372,4889,4930;, - 3;3827,3835,3829;, - 3;3825,3830,4420;, - 3;4406,4421,4425;, - 3;4415,4426,4931;, - 3;4924,4932,4925;, - 3;3801,3803,3749;, - 3;4288,4294,4899;, - 3;4933,4936,4437;, - 3;3836,4440,3842;, - 3;3842,4440,4443;, - 3;3750,3804,4375;, - 3;4298,3748,3751;, - 3;3837,4449,4444;, - 3;4445,4454,4450;, - 3;4936,4451,4452;, - 3;4376,4378,4293;, - 3;4297,4293,4289;, - 3;4455,4436,4438;, - 3;4446,4458,4454;, - 3;3844,3850,3848;, - 3;4937,4943,4941;, - 3;4459,4462,3850;, - 3;4460,4468,4464;, - 3;4940,4942,4465;, - 3;3801,3848,3850;, - 3;4943,4898,4901;, - 3;3804,3850,4469;, - 3;4466,4474,4470;, - 3;4376,4471,4472;, - 3;4377,4473,4942;, - 3;3840,3843,3844;, - 3;3842,4441,4459;, - 3;4442,4450,4468;, - 3;4451,4936,4940;, - 3;4936,4933,4937;, - 3;3849,3833,3834;, - 3;3847,3834,3828;, - 3;3841,3828,3823;, - 3;3839,3824,4409;, - 3;4448,4410,4418;, - 3;4457,4419,4398;, - 3;4435,4398,4922;, - 3;4935,4923,4926;, - 3;4938,4926,4928;, - 3;4944,4928,4892;, - 3;4897,4894,4276;, - 3;4291,4277,4285;, - 3;4301,4287,3742;, - 3;3747,3744,3798;, - 3;3802,3798,3833;, - 3;4082,4087,4077;, - 3;3954,3935,3933;, - 3;3954,3957,3963;, - 3;4083,4090,4088;, - 3;3938,3943,3933;, - 3;3944,3966,4092;, - 3;3967,3966,3944;, - 3;4088,4090,3972;, - 3;3964,3969,3972;, - 3;4063,3879,3877;, - 3;3882,3877,3879;, - 3;4092,3966,3974;, - 3;3966,3967,3976;, - 3;3978,3958,3934;, - 3;3978,3971,3965;, - 3;4064,4068,4070;, - 3;4077,4069,4070;, - 3;3884,3892,3886;, - 3;3939,3889,3890;, - 3;3945,3949,3950;, - 3;3942,3891,3895;, - 3;3944,4078,4080;, - 3;3896,3953,4080;, - 3;3896,3893,3949;, - 3;3944,3953,3949;, - 3;3885,3881,3898;, - 3;3934,3895,3898;, - 3;4093,4085,4076;, - 3;3968,3946,3936;, - 3;3975,3973,4089;, - 3;4094,4091,4084;, - 3;3967,3956,3961;, - 3;3977,3962,3973;, - 3;3951,3894,3883;, - 3;3952,3950,3888;, - 3;3952,3940,3937;, - 3;4079,4076,4071;, - 3;4073,4080,4072;, - 3;3897,4074,4067;, - 3;3894,3897,3878;, - 3;4200,4223,4221;, - 3;3661,3668,4222;, - 3;3539,3592,3668;, - 3;3542,3593,3591;, - 3;3544,3595,3593;, - 3;3547,3596,3594;, - 3;4205,4225,3596;, - 3;4203,4221,4224;, - 3;3282,3313,3296;, - 3;3351,3352,3343;, - 3;3272,3299,3300;, - 3;3282,3271,3274;, - 3;3352,3353,3345;, - 3;3273,3300,3553;, - 3;3284,3275,3512;, - 3;3524,3513,3554;, - 3;3312,3314,3352;, - 3;3297,3342,3344;, - 3;3312,3351,3341;, - 3;3314,3601,3353;, - 3;3601,3556,3345;, - 3;3301,3344,3346;, - 3;3514,3281,3276;, - 3;3279,3307,3302;, - 3;3280,3520,3557;, - 3;3306,3558,3537;, - 3;3278,3304,3538;, - 3;3520,4747,4764;, - 3;3558,4766,4767;, - 3;3510,3538,4768;, - 3;3516,3519,4751;, - 3;4749,4752,4769;, - 3;4166,4182,4180;, - 3;4171,4183,4182;, - 3;4171,4725,4732;, - 3;4173,4184,4734;, - 3;4177,4172,4167;, - 3;4177,4727,4723;, - 3;4170,4181,4184;, - 3;4724,4728,4735;, - 3;3231,3233,3482;, - 3;3232,3235,3102;, - 3;3108,3102,3235;, - 3;3485,3488,3238;, - 3;3040,3238,3488;, - 3;3483,3491,3490;, - 3;3495,3490,3491;, - 3;3484,3234,3239;, - 3;3497,3492,3239;, - 3;3234,3101,3103;, - 3;3249,3239,3103;, - 3;3489,3487,3481;, - 3;3237,3231,3480;, - 3;3494,3489,3490;, - 3;3059,3054,3104;, - 3;3059,3061,3056;, - 3;3060,3111,3106;, - 3;3110,3104,3240;, - 3;3111,3253,3243;, - 3;3251,3242,3244;, - 3;3055,3058,3107;, - 3;3105,3107,3245;, - 3;4527,4478,4475;, - 3;4528,4532,3903;, - 3;4531,4476,3851;, - 3;4529,3902,3853;, - 3;3901,3905,3852;, - 3;3908,4538,4540;, - 3;3915,4541,4543;, - 3;3918,4544,4578;, - 3;3921,4579,4581;, - 3;3924,4582,4534;, - 3;3912,4535,4537;, - 3;4479,4907,4902;, - 3;4480,4484,3858;, - 3;4483,4904,3805;, - 3;4905,3810,3806;, - 3;4481,3857,3808;, - 3;3856,3860,3807;, - 3;4033,4042,4039;, - 3;4043,5061,5056;, - 3;3679,3684,4813;, - 3;5062,5071,5066;, - 3;4811,4813,4818;, - 3;4049,3813,3811;, - 3;3815,3811,3813;, - 3;4044,4052,3812;, - 3;4047,3820,3814;, - 3;5059,4044,3819;, - 3;4909,4908,3819;, - 3;5057,4910,3820;, - 3;3818,3820,4910;, - 3;5072,5059,4908;, - 3;4914,4912,4908;, - 3;5074,4916,4910;, - 3;4911,4910,4916;, - 3;5075,5073,4913;, - 3;4919,4917,4913;, - 3;3680,3815,3817;, - 3;3683,3818,4911;, - 3;3681,4812,4909;, - 3;4814,4911,4918;, - 3;4816,4820,4919;, - 3;4812,4817,4914;, - 3;4052,4044,4055;, - 3;4045,4048,4058;, - 3;4050,4062,4059;, - 3;4051,4054,4061;, - 3;5059,5072,5079;, - 3;5073,5075,5081;, - 3;5057,5084,5082;, - 3;5060,5078,5083;, - 3;4053,4055,4041;, - 3;4062,4038,4040;, - 3;4054,4035,4037;, - 3;5076,5079,5069;, - 3;5080,5081,5067;, - 3;5084,5065,5068;, - 3;4057,4060,5085;, - 3;4059,4040,5065;, - 3;4042,5062,5064;, - 3;4055,5076,5063;, - 3;4302,3756,3752;, - 3;4307,4315,4311;, - 3;4314,4308,4319;, - 3;4305,4317,4319;, - 3;4312,4316,4318;, - 3;3753,3757,4318;, - 3;4320,3759,4326;, - 3;4328,4326,3759;, - 3;4313,3758,3764;, - 3;3755,3764,3758;, - 3;3760,4322,4310;, - 3;4327,4319,4308;, - 3;4321,4325,4307;, - 3;4329,4303,4319;, - 3;3762,3760,3764;, - 3;4330,3763,3756;, - 3;4331,4336,3768;, - 3;4332,4342,4337;, - 3;4335,4339,3771;, - 3;3766,3770,3772;, - 3;4333,3767,4344;, - 3;4341,4345,3773;, - 3;4346,4351,3777;, - 3;4347,4357,4352;, - 3;4350,4354,3780;, - 3;3775,3779,3781;, - 3;4348,3776,3784;, - 3;4356,3785,3782;, - 3;4358,4362,3789;, - 3;4359,4368,4363;, - 3;4362,4365,3791;, - 3;3787,3790,3792;, - 3;4360,3788,3795;, - 3;4367,3796,3793;, - 3;4603,4609,4607;, - 3;4583,4588,4609;, - 3;4589,4594,4586;, - 3;4611,4613,4592;, - 3;4611,4618,4615;, - 3;4640,4651,4646;, - 3;4649,4621,4619;, - 3;4641,4645,4659;, - 3;4644,4648,4657;, - 3;4642,4652,4656;, - 3;4648,4620,4608;, - 3;4621,4605,4607;, - 3;4650,4656,4606;, - 3;5160,5177,5176;, - 3;5162,5176,5181;, - 3;5160,5166,5183;, - 3;5167,5173,5170;, - 3;5172,5186,5185;, - 3;5186,5193,5188;, - 3;5190,5195,5194;, - 3;5195,5198,5197;, - 3;4991,4855,4851;, - 3;5169,4852,4853;, - 3;5198,4993,4996;, - 3;5161,5164,5173;, - 3;5178,5199,5196;, - 3;5163,5180,5187;, - 3;5180,5182,5191;, - 3;5181,5176,5196;, - 3;5183,4994,5199;, - 3;5165,4856,4992;, - 3;5160,5168,4854;, - 3;3521,3560,4211;, - 3;3246,3521,4199;, - 3;4199,4211,4770;, - 3;4178,4199,4753;, - 3;3559,3522,3525;, - 3;4212,3561,3603;, - 3;4771,4212,4229;, - 3;4754,4772,4774;, - 3;4730,4754,4755;, - 3;4179,4731,4737;, - 3;4185,3255,3247;, - 3;3254,3525,3522;, - 3;3562,3566,3665;, - 3;3562,3663,4255;, - 3;3568,4218,4215;, - 3;3568,3571,3576;, - 3;4218,3568,3562;, - 3;3579,3590,3585;, - 3;3308,3311,3588;, - 3;3574,3581,3583;, - 3;3570,3584,3586;, - 3;3565,3564,3587;, - 3;3664,3667,3670;, - 3;4214,4257,4259;, - 3;3666,3567,3604;, - 3;3572,3608,3606;, - 3;4216,4220,4233;, - 3;3575,3578,3607;, - 3;3311,3308,3318;, - 3;4219,4214,4230;, - 3;4256,3664,3669;, - 3;3572,4217,4232;, - 3;3309,3574,3610;, - 3;3565,3310,3317;, - 3;4643,4640,4654;, - 3;4661,4615,4618;, - 3;5019,5026,5024;, - 3;5026,5238,5232;, - 3;5239,5282,5278;, - 3;5028,5030,5229;, - 3;5227,5229,5286;, - 3;5279,5283,5284;, - 3;5200,5246,5235;, - 3;5230,5228,5285;, - 3;5031,5200,5027;, - 3;5032,5029,5228;, - 3;5248,5289,5280;, - 3;5287,5285,5281;, - 3;5202,5033,5023;, - 3;5025,5234,5249;, - 3;5204,5231,5288;, - 3;5201,5204,5251;, - 3;5231,5204,5035;, - 3;5204,5201,5031;, - 3;5236,5239,5242;, - 3;5288,5289,5248;, - 3;5029,5032,5036;, - 3;5031,5021,5037;, - 3;5237,5247,5248;, - 3;6189,5034,5203;, - 3;6190,6198,5229;, - 3;6198,6199,5286;, - 3;6194,5203,5250;, - 3;6199,6200,5279;, - 3;6196,5241,5278;, - 3;6195,5250,5244;, - 3;5252,5261,5257;, - 3;5253,5256,2371;, - 3;5255,5259,2373;, - 3;5260,32,2374;, - 3;5262,2380,2378;, - 3;5263,5269,5265;, - 3;5205,33,2380;, - 3;5206,5205,5262;, - 3;5270,5266,5267;, - 3;5275,5276,2393;, - 3;5275,5271,5273;, - 3;5208,5207,5266;, - 3;5210,5275,2392;, - 3;5210,5209,5271;, - 3;5268,5264,2379;, - 3;2398,2394,5277;, - 3;2398,5274,5268;, - 3;3879,4063,4664;, - 3;4064,4069,4666;, - 3;4069,4077,4670;, - 3;4077,4087,4672;, - 3;4086,4088,4674;, - 3;4088,3969,4625;, - 3;4627,4626,3970;, - 3;3948,4595,4627;, - 3;3899,4547,4595;, - 3;3880,4546,4547;, - 3;5101,5096,4671;, - 3;4972,4628,4596;, - 3;4972,4977,4630;, - 3;5102,4676,4677;, - 3;4961,4958,4596;, - 3;4964,5097,5108;, - 3;4980,4965,4964;, - 3;4677,4633,4982;, - 3;4631,4978,4982;, - 3;4667,5088,4946;, - 3;4948,4551,4548;, - 3;5108,5110,4984;, - 3;4979,4984,4986;, - 3;4636,4602,4597;, - 3;4636,4629,4632;, - 3;4668,4669,5090;, - 3;4671,5096,5090;, - 3;4551,4948,4950;, - 3;4962,4600,4554;, - 3;4965,4970,4967;, - 3;4599,4597,4556;, - 3;4964,4971,5099;, - 3;4956,5093,5099;, - 3;4956,4971,4969;, - 3;4964,4965,4969;, - 3;4552,4556,4557;, - 3;4597,4602,4557;, - 3;5109,5098,5095;, - 3;4981,4974,4959;, - 3;4985,5111,5106;, - 3;5110,5108,5104;, - 3;4980,4986,4975;, - 3;4987,4985,4983;, - 3;4968,4953,4949;, - 3;4970,4963,4952;, - 3;4970,4965,4960;, - 3;5098,5100,5091;, - 3;5093,5089,5092;, - 3;4957,4947,5087;, - 3;4955,4949,4947;, - 3;4548,4545,4664;, - 3;4668,4665,4666;, - 3;4669,4666,4670;, - 3;4671,4670,4672;, - 3;4676,4673,4674;, - 3;4677,4674,4625;, - 3;4627,4637,4635;, - 3;4601,4637,4627;, - 3;4558,4601,4595;, - 3;4550,4558,4547;, - 3;5038,5148,4680;, - 3;5043,5048,5000;, - 3;5039,4662,4638;, - 3;5049,5006,5112;, - 3;5004,4639,4678;, - 3;5044,4999,5008;, - 3;4998,5002,5004;, - 3;5046,5040,5005;, - 3;5045,5041,5038;, - 3;5042,5008,5006;, - 3;5042,5049,5152;, - 3;5153,5113,5115;, - 3;5008,5117,5112;, - 3;4679,4681,5151;, - 3;3726,3729,4272;, - 3;4027,4032,4005;, - 3;3727,4271,4266;, - 3;3735,3704,3702;, - 3;3700,4267,4268;, - 3;4028,4004,3706;, - 3;4003,4007,3700;, - 3;4030,3728,3701;, - 3;4029,3733,3726;, - 3;3734,3706,3704;, - 3;3734,3735,3736;, - 3;3737,3703,3708;, - 3;3706,3710,3702;, - 3;4269,4273,3732;, - 3;4876,4270,4272;, - 3;5050,5014,5009;, - 3;4877,4859,4266;, - 3;4885,4886,4861;, - 3;4857,4865,4268;, - 3;5051,4880,4864;, - 3;5013,4863,4857;, - 3;5054,5011,4858;, - 3;5052,5055,4876;, - 3;4880,4885,4860;, - 3;4880,4883,4886;, - 3;4887,4884,4866;, - 3;4864,4860,4861;, - 3;4269,4868,4882;, - 3;4235,4238,4221;, - 3;3672,4237,4222;, - 3;3611,3672,3668;, - 3;3614,3613,3591;, - 3;3616,3614,3593;, - 3;3619,3618,3594;, - 3;4240,3619,3596;, - 3;4238,4242,4224;, - 3;3282,3286,3320;, - 3;3043,3358,3359;, - 3;3285,3288,3324;, - 3;3282,3283,3287;, - 3;3044,3359,3361;, - 3;3288,3528,3621;, - 3;3284,3523,3526;, - 3;3524,3600,3622;, - 3;3312,3043,3044;, - 3;3322,3325,3360;, - 3;3312,3323,3358;, - 3;3315,3044,3045;, - 3;3601,3045,3361;, - 3;3325,3624,3362;, - 3;3529,3536,3293;, - 3;3291,3295,3333;, - 3;3292,3328,3625;, - 3;3327,3335,3659;, - 3;3294,3047,3660;, - 3;3046,3625,4775;, - 3;3626,3659,4781;, - 3;3047,4761,4782;, - 3;3531,4758,4762;, - 3;4757,4777,4783;, - 3;4186,4190,4180;, - 3;4191,4186,4182;, - 3;4191,4183,4732;, - 3;4193,4743,4734;, - 3;3048,4188,4187;, - 3;3048,4192,4739;, - 3;4189,4196,4184;, - 3;4740,4733,4735;, - 3;3256,3499,3500;, - 3;3257,3114,3115;, - 3;3108,3039,3049;, - 3;3503,3261,3050;, - 3;3040,3493,3506;, - 3;3501,3498,3051;, - 3;3495,3496,3508;, - 3;3502,3509,3052;, - 3;3497,3249,3052;, - 3;3259,3052,3116;, - 3;3249,3109,3116;, - 3;3507,3051,3498;, - 3;3260,3505,3499;, - 3;3494,3495,3051;, - 3;3059,3110,3117;, - 3;3059,3062,3064;, - 3;3060,3066,3119;, - 3;3110,3250,3262;, - 3;3111,3119,3265;, - 3;3251,3252,3266;, - 3;3063,3118,3120;, - 3;3118,3264,3267;, - 3;3532,3053,4243;, - 3;3268,4197,3053;, - 3;3053,4759,4778;, - 3;4197,4746,4759;, - 3;3628,3602,3525;, - 3;4244,4229,3603;, - 3;4779,4773,4229;, - 3;4760,4755,4774;, - 3;4744,4736,4755;, - 3;4198,4185,4737;, - 3;4185,4198,3269;, - 3;3254,3270,3533;, - 3;3630,3674,3676;, - 3;3630,4246,4263;, - 3;3636,3639,4247;, - 3;3636,3643,3644;, - 3;4250,4246,3630;, - 3;3647,3652,3653;, - 3;3329,3649,3657;, - 3;3641,3638,3650;, - 3;3637,3632,3654;, - 3;3634,3658,3655;, - 3;3675,3669,3670;, - 3;4245,4230,4259;, - 3;3678,3671,3604;, - 3;3640,3646,3606;, - 3;4248,4231,4233;, - 3;3642,3609,3607;, - 3;3331,3316,3318;, - 3;4252,4234,4230;, - 3;4265,4260,3669;, - 3;3640,3608,4232;, - 3;3330,3319,3610;, - 3;3634,3605,3317;, - 3;5323,5333,5331;, - 3;5318,5320,5332;, - 3;5291,5303,5320;, - 3;5294,5304,5302;, - 3;5296,5306,5304;, - 3;5299,5307,5305;, - 3;5328,5335,5307;, - 3;5326,5331,5334;, - 3;5336,5339,5331;, - 3;5321,5338,5332;, - 3;5308,5321,5320;, - 3;5311,5310,5302;, - 3;5313,5311,5304;, - 3;5316,5315,5305;, - 3;5341,5316,5307;, - 3;5339,5343,5334;, - 3;5350,5359,5355;, - 3;5351,5354,2485;, - 3;5353,5357,2487;, - 3;5358,2466,2488;, - 3;5360,2494,2492;, - 3;5361,5367,5363;, - 3;5344,2467,2494;, - 3;5345,5344,5360;, - 3;5368,5364,5365;, - 3;5373,5374,2507;, - 3;5373,5369,5371;, - 3;5347,5346,5364;, - 3;5349,5373,2506;, - 3;5349,5348,5369;, - 3;5366,5362,2493;, - 3;2512,2508,5375;, - 3;2512,5372,5366;, - 3;5384,5386,5396;, - 3;5386,5400,5401;, - 3;5384,5397,5403;, - 3;5391,5169,5170;, - 3;5394,5171,5185;, - 3;5405,5185,5188;, - 3;5408,5189,5194;, - 3;5411,5194,5197;, - 3;5380,4995,4851;, - 3;5169,5391,5377;, - 3;5413,5197,4996;, - 3;5385,5391,5393;, - 3;5398,5396,5412;, - 3;5388,5395,5406;, - 3;5399,5406,5409;, - 3;5401,5410,5412;, - 3;5403,5397,5414;, - 3;5390,5404,5383;, - 3;5384,5389,5379;, - 3;5447,5452,5418;, - 3;5448,5458,5453;, - 3;5451,5455,5421;, - 3;5416,5420,5422;, - 3;5449,5417,5460;, - 3;5457,5461,5423;, - 3;5462,5467,5427;, - 3;5463,5473,5468;, - 3;5466,5470,5430;, - 3;5425,5429,5431;, - 3;5464,5426,5434;, - 3;5472,5435,5432;, - 3;5474,5478,5439;, - 3;5475,5484,5479;, - 3;5478,5481,5441;, - 3;5437,5440,5442;, - 3;5476,5438,5445;, - 3;5483,5446,5443;, - 3;5517,5522,5488;, - 3;5518,5528,5523;, - 3;5521,5525,5491;, - 3;5486,5490,5492;, - 3;5519,5487,5530;, - 3;5527,5531,5493;, - 3;5532,5537,5497;, - 3;5533,5543,5538;, - 3;5536,5540,5500;, - 3;5495,5499,5501;, - 3;5534,5496,5504;, - 3;5542,5505,5502;, - 3;5544,5548,5509;, - 3;5545,5554,5549;, - 3;5548,5551,5511;, - 3;5507,5510,5512;, - 3;5546,5508,5515;, - 3;5553,5516,5513;, - 3;5587,5592,5558;, - 3;5588,5598,5593;, - 3;5591,5595,5561;, - 3;5556,5560,5562;, - 3;5589,5557,5600;, - 3;5597,5601,5563;, - 3;5602,5607,5567;, - 3;5603,5613,5608;, - 3;5606,5610,5570;, - 3;5565,5569,5571;, - 3;5604,5566,5574;, - 3;5612,5575,5572;, - 3;5614,5618,5579;, - 3;5615,5624,5619;, - 3;5618,5621,5581;, - 3;5577,5580,5582;, - 3;5616,5578,5585;, - 3;5623,5586,5583;, - 3;5657,5662,5628;, - 3;5658,5668,5663;, - 3;5661,5665,5631;, - 3;5626,5630,5632;, - 3;5659,5627,5670;, - 3;5667,5671,5633;, - 3;5672,5677,5637;, - 3;5673,5683,5678;, - 3;5676,5680,5640;, - 3;5635,5639,5641;, - 3;5674,5636,5644;, - 3;5682,5645,5642;, - 3;5684,5688,5649;, - 3;5685,5694,5689;, - 3;5688,5691,5651;, - 3;5647,5650,5652;, - 3;5686,5648,5655;, - 3;5693,5656,5653;, - 3;5716,5723,5721;, - 3;5713,5714,5722;, - 3;5695,5702,5714;, - 3;5697,5703,5701;, - 3;5698,5705,5703;, - 3;5700,5706,5704;, - 3;5719,5725,5706;, - 3;5718,5721,5724;, - 3;5726,5728,5721;, - 3;5715,5727,5722;, - 3;5707,5715,5714;, - 3;5709,5708,5701;, - 3;5710,5709,5703;, - 3;5712,5711,5704;, - 3;5729,5712,5706;, - 3;5728,5730,5724;, - 3;5752,5759,5757;, - 3;5749,5750,5758;, - 3;5731,5738,5750;, - 3;5733,5739,5737;, - 3;5734,5741,5739;, - 3;5736,5742,5740;, - 3;5755,5761,5742;, - 3;5754,5757,5760;, - 3;5762,5764,5757;, - 3;5751,5763,5758;, - 3;5743,5751,5750;, - 3;5745,5744,5737;, - 3;5746,5745,5739;, - 3;5748,5747,5740;, - 3;5765,5748,5742;, - 3;5764,5766,5760;, - 3;5791,5800,5796;, - 3;5801,5794,5796;, - 3;5798,5793,5809;, - 3;5805,5770,5767;, - 3;5775,5783,5781;, - 3;5785,5790,5781;, - 3;5779,5813,5811;, - 3;5788,5787,5773;, - 3;5768,5774,5812;, - 3;5809,5811,5813;, - 3;5808,5814,5772;, - 3;5770,5771,5773;, - 3;5817,5839,5841;, - 3;5824,5842,5844;, - 3;5827,5845,5847;, - 3;5830,5848,5850;, - 3;5833,5851,5835;, - 3;5821,5836,5838;, - 3;5855,5877,5879;, - 3;5862,5880,5882;, - 3;5865,5883,5885;, - 3;5868,5886,5888;, - 3;5871,5889,5873;, - 3;5859,5874,5876;, - 3;5941,5945,5946;, - 3;5931,5932,5943;, - 3;5949,5953,5932;, - 3;5954,5955,5951;, - 3;5954,5958,5959;, - 3;5957,5962,5963;, - 3;5962,5966,5967;, - 3;5965,5948,5946;, - 3;5977,5981,5982;, - 3;5974,5975,5979;, - 3;5985,5989,5975;, - 3;5990,5991,5987;, - 3;5990,5994,5995;, - 3;5993,5998,5999;, - 3;5998,6002,6003;, - 3;6001,5984,5982;, - 3;6010,6014,6015;, - 3;6007,6008,6012;, - 3;6018,6022,6008;, - 3;6023,6024,6020;, - 3;6023,6027,6028;, - 3;6026,6031,6032;, - 3;6031,6035,6036;, - 3;6034,6017,6015;, - 3;6090,6097,6095;, - 3;6080,6091,6093;, - 3;6098,6080,6081;, - 3;6103,6099,6101;, - 3;6103,6104,6108;, - 3;6107,6110,6112;, - 3;6111,6112,6116;, - 3;6115,6118,6095;, - 3;6126,6133,6131;, - 3;6123,6127,6129;, - 3;6134,6123,6124;, - 3;6139,6135,6137;, - 3;6139,6140,6144;, - 3;6143,6146,6148;, - 3;6147,6148,6152;, - 3;6151,6154,6131;, - 3;6159,6166,6164;, - 3;6156,6160,6162;, - 3;6167,6156,6157;, - 3;6172,6168,6170;, - 3;6172,6173,6177;, - 3;6176,6179,6181;, - 3;6180,6181,6185;, - 3;6184,6187,6164;; - - MeshNormals { - 6202; - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.722410;-0.691465;, - 0.000000;-0.722410;-0.691465;, - 0.000000;-0.173017;0.984919;, - 0.000000;-0.376027;-0.926609;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.184987;-0.982741;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.999519;-0.012421;0.028413;, - 0.000000;-0.182834;0.983144;, - 0.000000;-0.975913;0.218160;, - 0.000000;0.812111;-0.583502;, - 0.000000;0.812111;-0.583502;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.258306;0.966063;, - 0.000000;0.407045;-0.913408;, - 0.000000;-0.265741;0.964045;, - 0.000000;0.359196;-0.933262;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.976749;0.214388;, - 0.000000;0.986719;0.162438;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;-0.000000;-0.000000;, - 1.000000;0.000000;0.000000;, - -0.320176;0.909831;-0.263999;, - -0.459174;0.888346;0.000000;, - -0.320176;0.909831;0.263999;, - -1.000000;0.000000;0.000000;, - 0.997088;-0.076255;0.000000;, - 0.996327;0.038419;0.076524;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.250841;0.968028;, - 0.000000;0.978200;-0.207665;, - 0.998651;0.051906;-0.001130;, - 0.000000;-0.963715;-0.266933;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.857493;-0.514495;, - -1.000000;0.000000;0.000000;, - 0.000000;0.862416;-0.506201;, - 0.000000;-0.963715;-0.266933;, - 0.000000;-0.857493;-0.514495;, - 0.000000;0.862416;-0.506201;, - 0.000000;-0.963715;-0.266933;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.857493;-0.514495;, - 0.000000;0.862416;-0.506201;, - 1.000000;0.000000;0.000000;, - -0.568003;-0.528656;-0.630789;, - -0.568003;-0.528656;-0.630789;, - -0.631424;-0.350513;-0.691696;, - -0.631424;-0.350513;-0.691696;, - -0.465679;-0.689984;-0.554135;, - -0.465679;-0.689984;-0.554135;, - -0.465679;-0.689984;-0.554135;, - 0.000000;-0.267931;-0.963438;, - 0.000000;-0.806761;-0.590877;, - 0.000000;-0.806761;-0.590877;, - 0.000000;-0.514994;-0.857194;, - -0.609822;0.175716;-0.772814;, - -0.609822;0.175716;-0.772814;, - -0.609822;0.175716;-0.772814;, - -0.609822;0.175716;-0.772814;, - -0.636200;0.063603;-0.768898;, - -0.636200;0.063603;-0.768898;, - -0.636200;0.063603;-0.768898;, - -0.636200;0.063603;-0.768898;, - 0.000000;0.098842;-0.995103;, - 0.000000;0.098842;-0.995103;, - 0.000000;0.112611;-0.993639;, - 0.000000;0.112611;-0.993639;, - -0.923416;-0.078017;-0.375788;, - -0.923416;-0.078017;-0.375788;, - -0.377631;-0.156099;-0.912704;, - -0.377631;-0.156099;-0.912704;, - -0.377631;-0.156099;-0.912704;, - 0.000000;-0.141474;-0.989942;, - -0.884679;-0.172172;-0.433244;, - -0.884679;-0.172172;-0.433244;, - -0.901160;0.122972;-0.415677;, - -0.901160;0.122972;-0.415677;, - -0.266114;-0.355012;-0.896186;, - -0.266114;-0.355012;-0.896186;, - -0.203413;0.300293;-0.931905;, - -0.214097;0.668101;-0.712603;, - -0.214097;0.668101;-0.712603;, - -0.923596;0.269341;-0.272812;, - -0.490059;0.496470;-0.716492;, - -0.490059;0.496470;-0.716492;, - 0.000000;-0.367379;-0.930071;, - 0.000000;-0.367379;-0.930071;, - 0.000000;0.327765;-0.944759;, - 0.000000;0.696186;-0.717861;, - 0.000000;0.696186;-0.717861;, - -1.000000;0.000000;0.000000;, - 0.000000;0.773957;-0.633238;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.964991;-0.262282;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.964991;-0.262282;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.964991;-0.262282;, - 1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.001183;-0.449065;-0.893498;, - 0.001183;-0.449065;-0.893498;, - 0.000000;-0.450375;-0.892840;, - 0.000000;-0.450375;-0.892840;, - 1.000000;0.000000;0.000000;, - -0.001183;-0.449065;-0.893498;, - -0.001183;-0.449065;-0.893498;, - -0.922670;-0.345728;-0.170740;, - -0.382376;-0.569938;0.727296;, - -0.783932;-0.598346;0.165629;, - 0.000000;-0.378105;0.925763;, - 0.000000;0.000000;1.000000;, - -0.643705;-0.753560;-0.133384;, - -0.643705;-0.753560;-0.133384;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.184987;-0.982741;, - 0.000000;-0.184987;-0.982741;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;-0.184987;-0.982741;, - 0.000000;1.000000;0.000000;, - 0.000000;-0.378105;0.925763;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - -0.659309;-0.751872;0.000000;, - -0.659309;-0.751872;0.000000;, - -0.991432;-0.130624;0.000000;, - 0.000000;1.000000;0.000000;, - -0.456239;0.854986;0.246667;, - -0.456239;0.854986;0.246667;, - -0.456239;0.854986;0.246667;, - -0.405203;0.686558;-0.603696;, - -0.405203;0.686558;-0.603696;, - -0.405203;0.686558;-0.603696;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.729521;-0.683958;, - 0.000000;0.729521;-0.683958;, - 0.000000;0.892165;0.451711;, - 0.000000;0.892165;0.451711;, - -0.071029;-0.568445;-0.819650;, - -0.071029;-0.568445;-0.819650;, - -0.813177;-0.579468;-0.054409;, - -0.813177;-0.579468;-0.054409;, - -0.813177;-0.579468;-0.054409;, - -0.813177;-0.579468;-0.054409;, - -0.608486;-0.622828;-0.491763;, - -0.608486;-0.622828;-0.491763;, - -0.608486;-0.622828;-0.491763;, - -0.165797;-0.985639;-0.032041;, - -0.165797;-0.985639;-0.032041;, - -0.148332;-0.907977;-0.391886;, - -0.148332;-0.907977;-0.391886;, - -0.148332;-0.907977;-0.391886;, - -0.229863;-0.512566;-0.827308;, - -0.549758;-0.282120;-0.786241;, - -0.549758;-0.282120;-0.786241;, - -0.901537;-0.408133;-0.143730;, - -0.901537;-0.408133;-0.143730;, - -0.901537;-0.408133;-0.143730;, - -0.324502;-0.896254;-0.302369;, - -0.324502;-0.896254;-0.302369;, - -0.324502;-0.896254;-0.302369;, - -1.000000;0.000000;0.000000;, - -0.913099;-0.363269;-0.185167;, - -0.913099;-0.363269;-0.185167;, - -1.000000;0.000000;0.000000;, - -0.350617;-0.836690;-0.420734;, - -0.350617;-0.836690;-0.420734;, - -0.350617;-0.836690;-0.420734;, - -0.350617;-0.836690;-0.420734;, - 0.142002;-0.523952;-0.839827;, - 0.142002;-0.523952;-0.839827;, - 0.000000;-0.999568;-0.029404;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999568;-0.029404;, - 0.477824;-0.715291;-0.509944;, - 0.477824;-0.715291;-0.509944;, - 0.477824;-0.715291;-0.509944;, - 0.477824;-0.715291;-0.509944;, - 0.000000;-0.950866;-0.309602;, - 0.000000;-0.950866;-0.309602;, - 0.000000;-0.895357;-0.445349;, - 0.000000;-0.895357;-0.445349;, - -0.093017;-0.036036;-0.995012;, - -0.845563;0.464159;-0.263779;, - -0.845563;0.464159;-0.263779;, - -0.845563;0.464159;-0.263779;, - -0.845563;0.464159;-0.263779;, - -0.695672;0.222611;-0.682997;, - -0.695672;0.222611;-0.682997;, - -0.232657;0.873824;-0.426968;, - -0.232657;0.873824;-0.426968;, - -0.194237;0.693443;-0.693836;, - -0.194237;0.693443;-0.693836;, - -0.264427;-0.221960;-0.938516;, - -1.000000;0.000000;0.000000;, - -0.719556;0.465442;-0.515366;, - -0.719556;0.465442;-0.515366;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -0.839393;0.476139;-0.262127;, - -0.839393;0.476139;-0.262127;, - -0.209199;0.856636;-0.471604;, - -0.924952;0.375115;0.061252;, - -0.682450;0.721378;0.117794;, - 0.152278;-0.112636;-0.981898;, - 1.000000;0.000000;0.000000;, - 0.000000;0.901820;-0.432111;, - 0.000000;0.901820;-0.432111;, - 0.000000;0.746324;-0.665583;, - 0.839416;-0.217607;-0.498024;, - 0.632618;0.043851;-0.773222;, - 0.173513;0.437151;-0.882492;, - 0.000000;0.876019;-0.482276;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - -1.000000;0.000000;0.000000;, - 0.000000;0.978200;-0.207665;, - 0.000000;-0.897668;-0.440673;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.978200;-0.207665;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - -0.657933;0.281340;-0.698550;, - 0.000000;-0.987330;-0.158678;, - -0.657933;0.281340;-0.698550;, - 0.000000;0.978200;-0.207665;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.987330;-0.158678;, - 0.000000;0.352088;-0.935967;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 1.000000;0.000000;0.000000;, - 0.000000;0.978200;-0.207665;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.657933;0.281340;-0.698550;, - 0.000000;-0.987330;-0.158678;, - 0.657933;0.281340;-0.698550;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.371391;-0.928477;, - 0.000000;-0.919145;-0.393919;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.919145;-0.393919;, - -0.704085;-0.354065;-0.615550;, - -0.704085;-0.354065;-0.615550;, - -0.704085;-0.354065;-0.615550;, - 0.000000;-0.481363;-0.876521;, - 0.000000;-0.481363;-0.876521;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.371391;-0.928477;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.371391;-0.928477;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.481363;-0.876521;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.481363;-0.876521;, - 0.704085;-0.354065;-0.615550;, - 0.704085;-0.354065;-0.615550;, - 0.704085;-0.354065;-0.615550;, - 0.000000;0.404553;-0.914514;, - -0.946660;0.322234;0.000000;, - -0.765120;0.576310;-0.287155;, - -0.345860;0.589303;-0.730139;, - -0.946660;0.322234;0.000000;, - -0.946660;0.322234;0.000000;, - -0.671803;0.000000;-0.740730;, - -0.671803;0.000000;-0.740730;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - -0.262974;-0.511171;-0.818259;, - -0.262974;-0.511171;-0.818259;, - -0.262974;0.511173;-0.818258;, - -0.262974;0.511173;-0.818258;, - 0.000000;0.618986;-0.785402;, - 0.000000;0.618986;-0.785402;, - 0.815811;0.578319;0.000000;, - -0.815811;0.578319;0.000000;, - 0.000000;0.508835;-0.860864;, - 0.000000;0.508835;-0.860864;, - 0.000000;-0.508833;-0.860865;, - 0.000000;-0.508833;-0.860865;, - 0.000000;0.404553;-0.914514;, - 0.765120;0.576310;-0.287155;, - 0.345860;0.589303;-0.730139;, - 0.946660;0.322234;0.000000;, - 0.946660;0.322234;0.000000;, - 0.946660;0.322234;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.262974;-0.511171;-0.818259;, - 0.262974;-0.511171;-0.818259;, - 0.262974;0.511173;-0.818258;, - 0.262974;0.511173;-0.818258;, - 0.671803;0.000000;-0.740730;, - 0.000000;1.000000;0.000000;, - 0.671803;0.000000;-0.740730;, - -1.000000;0.000000;0.000000;, - 0.002643;-0.988024;-0.154279;, - 0.002643;-0.988024;-0.154279;, - 0.000000;-0.196037;-0.980597;, - -0.992902;-0.118932;0.000000;, - -0.308346;0.914546;-0.261780;, - -0.308346;0.914546;-0.261780;, - -0.441536;0.897244;0.000000;, - -0.441536;0.897244;0.000000;, - -0.308346;0.914546;0.261780;, - -0.308346;0.914546;0.261780;, - 0.000000;-0.946157;-0.323708;, - 0.000000;-0.946157;-0.323708;, - 0.000000;-0.196037;-0.980597;, - 0.996514;-0.083420;0.000000;, - 0.320176;0.909831;-0.263999;, - 0.459174;0.888346;0.000000;, - 0.320176;0.909831;0.263999;, - 1.000000;0.000000;0.000000;, - -0.002643;-0.988024;-0.154279;, - -0.002643;-0.988024;-0.154279;, - 0.308346;0.914546;-0.261780;, - 0.308346;0.914546;-0.261780;, - 0.441536;0.897244;0.000000;, - 0.441536;0.897244;0.000000;, - 0.308346;0.914546;0.261780;, - 0.308346;0.914546;0.261780;, - -0.812034;-0.553973;0.183615;, - -0.946603;-0.281034;-0.157994;, - 0.000000;-0.378105;0.925763;, - -0.382376;-0.569938;0.727296;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.378105;0.925763;, - -1.000000;0.000000;0.000000;, - 0.000000;0.710283;-0.703916;, - -1.000000;0.000000;0.000000;, - 0.000000;0.946563;-0.322518;, - 0.000000;0.946563;-0.322518;, - -1.000000;0.000000;0.000000;, - 0.000000;0.555569;-0.831470;, - 0.000000;0.764153;-0.645035;, - 0.000000;0.764153;-0.645035;, - 0.000000;0.710283;-0.703916;, - 0.000000;0.555569;-0.831470;, - 1.000000;0.000000;0.000000;, - 0.000000;0.710283;-0.703916;, - 1.000000;0.000000;0.000000;, - 0.000000;0.946563;-0.322518;, - 0.000000;0.946563;-0.322518;, - 1.000000;0.000000;0.000000;, - 0.000000;0.555569;-0.831470;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.389197;-0.921154;, - 0.000000;-1.000000;0.000000;, - -0.542285;0.325571;-0.774552;, - -0.542285;0.325571;-0.774552;, - 0.000000;0.007127;-0.999975;, - -0.573119;0.023866;-0.819124;, - -0.573119;0.023866;-0.819124;, - 0.000000;0.216852;0.976204;, - -0.961193;0.164049;-0.221802;, - -0.961193;0.164049;-0.221802;, - -0.980187;0.000000;-0.198074;, - 0.000000;0.000000;1.000000;, - -0.980187;0.000000;-0.198074;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.216852;0.976204;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.928011;-0.372552;, - 0.000000;-0.928011;-0.372552;, - -0.915407;-0.402528;0.001330;, - -0.915407;-0.402528;0.001330;, - -0.362628;-0.931929;0.003080;, - -0.362628;-0.931929;0.003080;, - -0.932383;0.105681;0.345678;, - -0.932383;0.105681;0.345678;, - -0.939177;-0.277805;0.201919;, - -0.939177;-0.277805;0.201919;, - -0.939177;-0.277805;0.201919;, - -0.423043;-0.726679;0.541270;, - -0.423043;-0.726679;0.541270;, - -0.510845;0.042579;0.858618;, - -0.510845;0.042579;0.858618;, - 0.000000;-0.796632;0.604464;, - 0.000000;-0.999995;0.003305;, - -0.297759;0.272112;0.915038;, - -0.297759;0.272112;0.915038;, - -0.886619;0.124974;0.445295;, - -0.886619;0.124974;0.445295;, - -0.886619;0.124974;0.445295;, - -0.229087;0.702960;0.673325;, - -0.229087;0.702960;0.673325;, - -0.864236;0.368497;0.342501;, - -0.864236;0.368497;0.342501;, - -0.713439;0.698664;-0.053601;, - -0.713439;0.698664;-0.053601;, - 0.000000;0.712829;0.701337;, - 0.000000;0.712829;0.701337;, - 0.000000;0.297145;0.954832;, - 0.000000;0.297145;0.954832;, - -0.204500;0.976588;-0.066752;, - -0.987857;-0.005063;-0.155282;, - -0.987857;-0.005063;-0.155282;, - -0.582078;-0.000864;-0.813132;, - -0.582078;-0.000864;-0.813132;, - -0.582078;-0.000864;-0.813132;, - -0.582078;-0.000864;-0.813132;, - -0.581799;-0.016819;-0.813159;, - -0.581799;-0.016819;-0.813159;, - -0.581799;-0.016819;-0.813159;, - -0.581799;-0.016819;-0.813159;, - -0.987819;-0.010866;-0.155226;, - -0.987819;-0.010866;-0.155226;, - 0.000000;0.883291;-0.468826;, - 0.000000;-0.657889;-0.753115;, - 0.113771;0.245370;-0.962730;, - 0.113771;0.245370;-0.962730;, - -0.171571;0.921590;-0.348189;, - 0.000000;0.948652;-0.316321;, - -0.520068;0.319591;-0.792081;, - -0.520068;0.319591;-0.792081;, - -0.520068;0.319591;-0.792081;, - -0.800913;0.509642;-0.314332;, - -0.800913;0.509642;-0.314332;, - 0.000000;-0.774307;-0.632810;, - 0.000000;0.660625;-0.750716;, - 0.000000;-0.935118;-0.354337;, - -0.153552;-0.920031;-0.360507;, - 0.118314;-0.167948;-0.978670;, - 0.118314;-0.167948;-0.978670;, - -0.787478;-0.534510;-0.306884;, - -0.787478;-0.534510;-0.306884;, - -0.491605;-0.323829;-0.808368;, - -0.491605;-0.323829;-0.808368;, - -0.491605;-0.323829;-0.808368;, - 0.000000;-0.351344;-0.936246;, - 0.000000;0.000000;-1.000000;, - 0.379424;-0.028718;-0.924777;, - 0.379424;-0.028718;-0.924777;, - 0.261457;-0.285374;-0.922064;, - 0.000000;0.000000;-1.000000;, - 0.376619;0.054435;-0.924768;, - 0.376619;0.054435;-0.924768;, - 0.386721;-0.025977;-0.921831;, - 0.386721;-0.025977;-0.921831;, - 0.386721;-0.025977;-0.921831;, - 0.383931;0.053652;-0.921802;, - 0.383931;0.053652;-0.921802;, - 0.383931;0.053652;-0.921802;, - 0.000000;0.353047;-0.935606;, - 0.254652;0.321336;-0.912083;, - 0.000000;0.998175;-0.060396;, - 0.000000;-0.250841;0.968028;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.250841;0.968028;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.250841;0.968028;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.250841;0.968028;, - 1.000000;0.000000;0.000000;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.861871;0.507128;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - -0.997088;-0.076255;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.703016;-0.711174;0.000000;, - -0.703016;-0.711174;0.000000;, - -0.703016;-0.711174;0.000000;, - 1.000000;0.000000;0.000000;, - -0.688808;0.146582;-0.709970;, - -0.688808;0.146582;-0.709970;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.178932;-0.983862;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.688808;0.146582;-0.709970;, - 0.688808;0.146582;-0.709970;, - 0.703016;-0.711174;0.000000;, - 0.703016;-0.711174;0.000000;, - 0.703016;-0.711174;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -0.673085;0.543157;-0.501933;, - -0.673085;0.543157;-0.501933;, - -0.673085;0.543157;-0.501933;, - -0.681821;-0.000000;-0.731519;, - -0.681821;-0.000000;-0.731519;, - -0.673085;-0.543157;-0.501933;, - -0.673085;-0.543157;-0.501933;, - -0.673085;-0.543157;-0.501933;, - -0.665741;-0.746183;0.000000;, - -0.665741;-0.746183;0.000000;, - -1.000000;-0.000000;-0.000000;, - -0.297521;-0.752416;-0.587666;, - -0.297521;-0.752416;-0.587666;, - -0.297521;-0.752416;-0.587666;, - -0.946660;0.322234;0.000000;, - 0.000000;0.404553;0.914514;, - -0.345860;0.589303;0.730139;, - -0.765120;0.576310;0.287155;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - -0.961703;0.274094;0.000000;, - -0.961703;0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - -0.408026;0.782721;-0.469960;, - -0.408026;0.782721;-0.469960;, - -0.408026;0.782721;-0.469960;, - -0.961703;-0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - -0.961703;-0.274094;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;-0.000000;, - -0.408026;-0.782720;-0.469961;, - -0.408026;-0.782720;-0.469961;, - -0.408026;-0.782720;-0.469961;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-0.734960;-0.678111;, - -0.709688;-0.575075;-0.406979;, - -0.709688;-0.575075;-0.406979;, - -0.709688;-0.575075;-0.406979;, - -0.812989;-0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - -0.812989;-0.582279;0.000000;, - -0.812989;0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - -0.812989;0.582279;0.000000;, - -0.709688;0.575076;-0.406978;, - -0.709688;0.575076;-0.406978;, - -0.709688;0.575076;-0.406978;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.525821;-0.675119;-0.517422;, - 0.525821;-0.675119;-0.517422;, - 0.525821;-0.675119;-0.517422;, - 0.000000;0.618986;0.785402;, - 0.000000;0.618986;0.785402;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.682437;-0.730944;, - 0.000000;0.682437;-0.730944;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-1.000000;-0.000000;, - 0.000000;-0.682436;-0.730946;, - 0.000000;-0.682436;-0.730946;, - 0.673085;0.543157;-0.501933;, - 0.673085;0.543157;-0.501933;, - 0.673085;0.543157;-0.501933;, - 0.681820;-0.000000;-0.731520;, - 0.681820;-0.000000;-0.731520;, - 0.673085;-0.543157;-0.501933;, - 0.673085;-0.543157;-0.501933;, - 0.673085;-0.543157;-0.501933;, - 0.665741;-0.746183;0.000000;, - 0.665741;-0.746183;0.000000;, - 0.946660;0.322234;0.000000;, - 0.000000;0.404553;0.914514;, - 0.765120;0.576310;0.287155;, - 0.345860;0.589303;0.730139;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.961703;0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - 0.961703;0.274094;0.000000;, - 0.408026;0.782721;-0.469960;, - 0.408026;0.782721;-0.469960;, - 0.408026;0.782721;-0.469960;, - 0.961703;-0.274094;0.000000;, - 0.961703;-0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;-0.000000;, - 0.408026;-0.782720;-0.469961;, - 0.408026;-0.782720;-0.469961;, - 0.408026;-0.782720;-0.469961;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-0.734960;-0.678111;, - 0.709688;-0.575075;-0.406979;, - 0.709688;-0.575075;-0.406979;, - 0.709688;-0.575075;-0.406979;, - 0.812989;-0.582279;0.000000;, - 0.812989;-0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - 0.812989;0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - 0.812989;0.582279;0.000000;, - 0.709688;0.575076;-0.406978;, - 0.709688;0.575076;-0.406978;, - 0.709688;0.575076;-0.406978;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - -0.665741;0.746183;0.000000;, - -0.665741;0.746183;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;-0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.734960;-0.678111;, - 0.000000;0.734960;-0.678111;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;-0.000000;, - 0.000000;0.734960;-0.678111;, - 0.000000;0.734960;-0.678111;, - 0.665741;0.746183;0.000000;, - 0.665741;0.746183;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;-0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.734960;-0.678111;, - 0.000000;0.734960;-0.678111;, - 0.000000;-1.000000;0.000000;, - 0.006548;0.000000;-0.999979;, - 0.999860;0.000000;0.016754;, - 0.000000;-1.000000;0.000000;, - -0.999860;0.000000;-0.016753;, - 0.006548;0.000000;-0.999979;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.974062;0.193186;-0.117820;, - -0.990365;0.035316;-0.133904;, - -1.000000;0.000000;0.000000;, - -0.067354;-0.443547;0.893716;, - -0.067354;-0.443547;0.893716;, - -0.817977;-0.560175;0.130831;, - -0.817977;-0.560175;0.130831;, - -0.817977;-0.560175;0.130831;, - -0.143343;-0.948306;0.283140;, - -0.575371;-0.360864;0.733979;, - -0.575371;-0.360864;0.733979;, - -0.575371;-0.360864;0.733979;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -0.237889;-0.660874;-0.711797;, - -0.237889;-0.660874;-0.711797;, - -0.225248;-0.235329;-0.945454;, - -0.694911;-0.059586;-0.716623;, - -0.694911;-0.059586;-0.716623;, - -0.724776;-0.636464;-0.263843;, - -0.724776;-0.636464;-0.263843;, - -0.724776;-0.636464;-0.263843;, - -0.724776;-0.636464;-0.263843;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.981599;-0.122465;-0.146514;, - -0.921060;-0.243934;0.303554;, - -0.921060;-0.243934;0.303554;, - -0.921060;-0.243934;0.303554;, - -0.590930;-0.729027;0.345429;, - -0.339709;0.184859;0.922185;, - -0.356763;-0.934190;0.003088;, - -0.591008;-0.180066;0.786312;, - 0.000000;-0.447847;0.894110;, - 0.000000;-0.447847;0.894110;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.957775;0.287517;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999995;0.003306;, - 0.000000;0.212834;0.977088;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.724776;-0.636464;-0.263843;, - 0.724776;-0.636464;-0.263843;, - 0.724776;-0.636464;-0.263843;, - 0.724776;-0.636464;-0.263843;, - 0.694911;-0.059586;-0.716623;, - 0.694911;-0.059586;-0.716623;, - 0.225248;-0.235329;-0.945454;, - 0.237889;-0.660874;-0.711797;, - 0.237889;-0.660874;-0.711797;, - -0.306622;-0.892935;-0.329622;, - -0.306622;-0.892935;-0.329622;, - -0.306622;-0.892935;-0.329622;, - -0.328658;-0.526006;-0.784412;, - -0.938714;-0.344697;0.000000;, - 0.000000;-0.300372;-0.953822;, - -0.767964;-0.531687;-0.357126;, - -0.767968;0.531681;-0.357129;, - 0.000000;0.300367;-0.953824;, - -0.328661;0.526000;-0.784415;, - -0.938716;0.344692;0.000000;, - -0.306626;0.892932;-0.329625;, - -0.306626;0.892932;-0.329625;, - -0.306626;0.892932;-0.329625;, - -0.901160;-0.433486;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.887308;-0.461177;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.198966;0.000000;-0.980006;, - 0.000000;-1.000000;0.000000;, - 0.198966;0.000000;-0.980006;, - 0.000000;0.000000;-1.000000;, - -0.505754;-0.862678;0.000000;, - -0.505754;-0.862678;0.000000;, - 0.198966;0.000000;-0.980006;, - 0.163134;-0.084068;-0.983016;, - 0.334945;0.942238;0.000000;, - 0.334945;0.942238;0.000000;, - -0.631267;0.775565;0.000000;, - 0.163134;-0.084068;-0.983016;, - -0.631267;0.775565;0.000000;, - -0.986099;0.166158;0.000000;, - 0.356869;-0.669712;-0.651253;, - 0.356869;-0.669712;-0.651253;, - 0.000000;0.000000;-1.000000;, - 0.953833;0.300339;0.000000;, - 0.953833;0.300339;0.000000;, - 0.712537;0.701634;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.682801;0.730605;0.000000;, - -0.682801;0.730605;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.712526;-0.701646;0.000000;, - 0.985989;-0.166808;0.000000;, - -0.712526;-0.701646;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.933289;-0.359126;0.000000;, - 0.933289;-0.359126;0.000000;, - 0.797086;0.603866;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.337034;0.941492;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.997575;-0.069594;0.000000;, - 0.693605;-0.720355;0.000000;, - -0.997575;-0.069594;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.300371;-0.953822;, - 0.000000;-0.300371;-0.953822;, - 0.000000;-0.886849;-0.462059;, - 0.000000;-0.886849;-0.462059;, - 0.000000;0.300367;-0.953824;, - 0.000000;0.300367;-0.953824;, - -0.000000;0.886847;-0.462064;, - -0.000000;0.886847;-0.462064;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;-0.016753;, - -0.007275;0.000000;-0.999974;, - -0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - -0.007275;0.000000;-0.999974;, - 0.006063;-0.377782;-0.925875;, - 0.999860;0.000000;0.016754;, - 0.006063;-0.377782;-0.925875;, - -0.999860;0.000001;-0.016752;, - 0.006063;-0.377782;-0.925875;, - 0.999860;0.000000;0.016754;, - -0.999860;0.000001;-0.016753;, - 0.006063;-0.377782;-0.925875;, - 0.999860;0.000000;0.016754;, - -0.999860;0.000001;-0.016753;, - 0.845995;-0.382332;-0.371638;, - 0.845995;-0.382332;-0.371638;, - 0.845995;-0.382332;-0.371638;, - 0.845995;-0.382332;-0.371638;, - 0.128250;-0.917776;-0.375819;, - 0.128250;-0.917776;-0.375819;, - 0.315649;-0.364073;-0.876251;, - 0.315649;-0.364073;-0.876251;, - 0.000000;-0.886848;-0.462062;, - 0.000000;-0.886848;-0.462062;, - 0.000000;-0.929961;-0.367658;, - 0.000000;-0.300370;-0.953823;, - 0.000000;-0.300370;-0.953823;, - 0.000000;-0.300369;-0.953823;, - 0.000000;-0.300369;-0.953823;, - 0.845995;0.382332;-0.371638;, - 0.845995;0.382332;-0.371638;, - 0.845995;0.382332;-0.371638;, - 0.845995;0.382332;-0.371638;, - 0.315649;0.364073;-0.876251;, - 0.315649;0.364073;-0.876251;, - 0.128250;0.917776;-0.375819;, - 0.128250;0.917776;-0.375819;, - 0.000000;0.886848;-0.462062;, - 0.000000;0.886848;-0.462062;, - 0.000000;0.300369;-0.953823;, - 0.000000;0.300369;-0.953823;, - 0.000000;0.300368;-0.953823;, - 0.000000;0.300368;-0.953823;, - -0.000000;0.929961;-0.367659;, - 0.000000;1.000000;0.000000;, - 0.009877;0.000000;-0.999951;, - 0.000000;-1.000000;0.000000;, - 0.009877;0.000000;-0.999951;, - 0.000000;-1.000000;0.000000;, - -0.007275;0.000000;-0.999974;, - 0.999860;0.000000;0.016753;, - 0.999860;0.000000;0.016753;, - -0.007275;0.000000;-0.999974;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - 0.000000;1.000000;0.000000;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - 0.225238;0.000000;-0.974304;, - 0.000000;-1.000000;0.000000;, - 0.225238;0.000000;-0.974304;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.225236;-0.000001;-0.974304;, - -0.225236;-0.000001;-0.974304;, - 0.000000;-1.000000;0.000000;, - -0.952657;0.000000;-0.304046;, - -0.952657;0.000000;-0.304046;, - -1.000000;0.000000;-0.000000;, - -0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - -0.897253;-0.281640;-0.340023;, - -0.897253;-0.281640;-0.340023;, - -0.943629;-0.331006;0.000000;, - -0.000000;0.000000;1.000000;, - -0.428060;-0.799374;-0.421624;, - -0.428060;-0.799374;-0.421624;, - -0.428060;-0.799374;-0.421624;, - -0.428060;-0.799374;-0.421624;, - -0.433190;-0.901303;0.000000;, - -0.433190;-0.901303;0.000000;, - -0.000000;-0.000000;1.000000;, - -0.410415;-0.110414;-0.905190;, - -0.410415;-0.110414;-0.905190;, - -0.000000;-0.000000;1.000000;, - -0.458637;0.000000;-0.888624;, - -0.458637;0.000000;-0.888624;, - -0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.009877;0.000000;-0.999951;, - 0.999835;0.000000;-0.018151;, - 0.999835;0.000000;-0.018151;, - 0.009877;0.000000;-0.999951;, - 0.000000;1.000000;0.000000;, - 0.008295;0.000000;-0.999966;, - -0.739674;0.429300;-0.518250;, - -0.739674;0.429300;-0.518250;, - -0.739674;0.429300;-0.518250;, - 0.003774;0.861001;-0.508589;, - 0.003774;0.861001;-0.508589;, - 0.003774;0.861001;-0.508589;, - -0.739674;-0.429300;-0.518250;, - -0.739674;-0.429300;-0.518250;, - -0.739674;-0.429300;-0.518250;, - 0.003774;-0.861001;-0.508589;, - 0.003774;-0.861001;-0.508589;, - 0.003774;-0.861001;-0.508589;, - 0.751445;-0.431739;-0.498932;, - 0.751445;-0.431739;-0.498932;, - 0.751445;-0.431739;-0.498932;, - 0.751445;0.431739;-0.498932;, - 0.751445;0.431739;-0.498932;, - 0.751445;0.431739;-0.498932;, - 0.000000;-1.000000;0.000000;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.000000;1.000000;0.000000;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.492699;-0.870200;0.000000;, - -0.000000;-0.000000;1.000000;, - 0.418146;-0.801329;-0.427815;, - 0.418146;-0.801329;-0.427815;, - 0.418146;-0.801329;-0.427815;, - 0.421913;-0.784056;-0.455242;, - 0.421913;-0.784056;-0.455242;, - 0.421913;-0.784056;-0.455242;, - 0.492699;-0.870200;0.000000;, - -0.000000;-0.000000;1.000000;, - 0.492699;-0.870200;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.115463;-0.249286;-0.961522;, - 0.115463;-0.249286;-0.961522;, - 0.100988;-0.994888;0.000000;, - -0.000000;0.000000;1.000000;, - 0.000000;-0.000000;-1.000000;, - -0.179157;-0.288632;-0.940529;, - -0.179157;-0.288632;-0.940529;, - 0.191831;-0.385043;-0.902742;, - 0.000000;-0.000000;-1.000000;, - 0.292367;-0.866429;-0.404750;, - 0.292367;-0.866429;-0.404750;, - 0.292367;-0.866429;-0.404750;, - 0.331004;-0.943629;0.000000;, - -0.000000;0.000000;1.000000;, - 0.830569;-0.387539;-0.399961;, - 0.830569;-0.387539;-0.399961;, - 0.830569;-0.387539;-0.399961;, - 0.830569;-0.387539;-0.399961;, - 0.901302;-0.433191;0.000000;, - 0.901302;-0.433191;0.000000;, - -0.000000;0.000000;1.000000;, - 0.000000;0.000000;-1.000000;, - 0.109902;-0.344862;-0.932197;, - 0.109902;-0.344862;-0.932197;, - 1.000000;0.000000;0.000000;, - -0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.945889;0.000000;-0.324489;, - 0.945889;0.000000;-0.324489;, - 0.439396;0.000000;-0.898293;, - 0.439396;0.000000;-0.898293;, - 0.442680;-0.198092;-0.874525;, - 0.442680;-0.198092;-0.874525;, - -0.000000;0.000000;1.000000;, - 0.100988;-0.994888;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.222802;0.267250;-0.937516;, - -0.694990;0.067591;-0.715836;, - -0.694990;0.067591;-0.715836;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.182865;0.983138;0.000000;, - -0.841860;0.510164;-0.176079;, - -0.841860;0.510164;-0.176079;, - -0.841860;0.510164;-0.176079;, - -0.212237;0.942309;-0.258861;, - 0.000000;0.000000;1.000000;, - -0.824489;0.565879;0.000000;, - -0.824489;0.565879;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.694990;0.067591;-0.715836;, - 0.694990;0.067591;-0.715836;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.222803;0.267250;-0.937516;, - -0.643961;0.458788;-0.612232;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.965546;-0.260232;, - 0.000000;0.951870;-0.306503;, - 0.000000;0.951870;-0.306503;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.006548;0.000000;-0.999979;, - 0.999860;0.000000;0.016754;, - -0.999860;0.000000;-0.016752;, - 0.006548;0.000000;-0.999979;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;-0.016753;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;0.016754;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;0.016754;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - -0.006548;0.000000;0.999979;, - 0.000000;1.000000;0.000000;, - 0.006548;0.000000;-0.999979;, - -0.999860;0.000000;-0.016752;, - 0.999860;0.000000;0.016754;, - 0.006548;0.000000;-0.999979;, - 0.006548;0.000000;-0.999979;, - 0.999860;0.000000;0.016754;, - 0.999860;0.000000;0.016754;, - 0.000000;-1.000000;0.000000;, - -0.006548;0.000000;0.999979;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - -0.999860;0.000000;-0.016752;, - 0.006548;0.000000;-0.999979;, - -0.894428;0.447212;-0.000000;, - -0.894428;0.447212;-0.000000;, - -0.831040;0.403243;-0.383102;, - -0.831040;0.403243;-0.383102;, - -0.831040;0.403243;-0.383102;, - -0.831040;0.403243;-0.383102;, - -0.316229;0.948683;-0.000000;, - -0.282244;0.875709;-0.391756;, - -0.282244;0.875709;-0.391756;, - -0.282244;0.875709;-0.391756;, - -0.457151;0.212943;-0.863521;, - -0.457151;0.212943;-0.863521;, - 0.000000;0.933082;-0.359664;, - 0.000000;0.933082;-0.359664;, - 0.000000;1.000000;0.000000;, - 0.000000;0.405468;-0.914109;, - 0.000000;0.405468;-0.914109;, - -0.109882;0.357779;-0.927319;, - -0.109882;0.357779;-0.927319;, - 0.349235;0.855784;-0.381665;, - 0.349235;0.855784;-0.381665;, - 0.349235;0.855784;-0.381665;, - 0.349235;0.855784;-0.381665;, - 0.382684;0.923879;0.000000;, - 0.382684;0.923879;0.000000;, - 0.923880;0.382683;0.000000;, - 0.859819;0.357289;-0.364767;, - 0.859819;0.357289;-0.364767;, - 0.859819;0.357289;-0.364767;, - 0.142369;0.355966;-0.923590;, - 0.142369;0.355966;-0.923590;, - 0.486422;0.202974;-0.849820;, - 0.486422;0.202974;-0.849820;, - -0.231732;0.696563;-0.679043;, - -0.231732;0.696563;-0.679043;, - -0.718710;0.648693;-0.250309;, - -0.718710;0.648693;-0.250309;, - -0.718710;0.648693;-0.250309;, - -0.718710;0.648693;-0.250309;, - 0.718710;0.648692;-0.250309;, - 0.718710;0.648692;-0.250309;, - 0.718710;0.648692;-0.250309;, - 0.718710;0.648692;-0.250309;, - 0.231732;0.696563;-0.679043;, - 0.231732;0.696563;-0.679043;, - -1.000000;0.000000;0.000000;, - 0.000000;0.220606;-0.975363;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.220606;-0.975363;, - 0.000000;-1.000000;0.000000;, - -0.999563;0.015174;-0.025377;, - -0.999563;0.015174;-0.025377;, - -0.999715;0.000062;-0.023881;, - -0.999715;0.000062;-0.023881;, - -0.999670;0.005731;-0.025038;, - -0.999670;0.005731;-0.025038;, - -0.999698;0.006980;-0.023542;, - -0.999698;0.006980;-0.023542;, - 0.000000;0.999327;-0.036692;, - -0.186111;0.981867;-0.036054;, - -0.817235;0.575047;-0.038051;, - -0.817235;0.575047;-0.038051;, - -0.821447;0.564406;-0.081677;, - -0.821447;0.564406;-0.081677;, - -0.185128;0.976271;-0.112354;, - 0.000000;0.993444;-0.114318;, - -0.817690;-0.575000;-0.027537;, - -0.817690;-0.575000;-0.027537;, - -0.164892;-0.986122;-0.019346;, - -0.164920;-0.986307;0.000000;, - -0.813788;-0.580936;-0.016218;, - -0.813788;-0.580936;-0.016218;, - 0.000000;-0.999808;-0.019615;, - 0.000000;-1.000000;0.000000;, - 0.417231;-0.749047;-0.514632;, - 0.417231;-0.749047;-0.514632;, - 0.000000;-0.910249;-0.414061;, - -0.901271;0.000000;-0.433257;, - -0.697396;-0.282082;-0.658839;, - -0.266525;-0.707134;-0.654925;, - 0.417231;0.749047;-0.514632;, - 0.417231;0.749047;-0.514632;, - -0.901271;0.000000;-0.433257;, - -0.266525;0.707134;-0.654925;, - 0.000000;0.910249;-0.414061;, - -0.697396;0.282082;-0.658839;, - 0.381399;-0.271517;-0.883636;, - -0.232012;-0.244096;-0.941588;, - -0.232012;0.244096;-0.941588;, - 0.381399;0.271517;-0.883636;, - -0.491030;-0.830349;-0.263459;, - -0.491030;-0.830349;-0.263459;, - -0.950288;-0.070780;-0.303222;, - 0.000000;0.960955;-0.276705;, - -0.272426;0.849198;-0.452379;, - -0.783289;0.222369;-0.580526;, - -0.326957;0.115768;-0.937921;, - -0.326957;0.115768;-0.937921;, - -0.326957;0.115768;-0.937921;, - -0.327272;-0.520278;-0.788799;, - -0.327272;-0.520278;-0.788799;, - -0.327272;-0.520278;-0.788799;, - 0.000000;0.235109;-0.971969;, - 0.000000;0.235109;-0.971969;, - 0.000000;-0.642876;-0.765970;, - 0.000000;-0.642876;-0.765970;, - 0.000000;0.960955;-0.276705;, - 0.000000;0.960955;-0.276705;, - 0.000000;-0.991073;-0.133319;, - 0.000000;-0.818404;-0.574643;, - -0.999257;0.038532;0.001036;, - -0.999257;0.038532;0.001036;, - 0.000000;0.317049;-0.948409;, - 0.000000;0.317049;-0.948409;, - 0.000000;-1.000000;0.000000;, - -0.996327;0.038419;0.076524;, - -0.511973;0.849126;0.129878;, - -0.996327;0.038420;0.076524;, - -0.863785;0.365054;0.347291;, - 0.000000;0.998092;0.061747;, - -0.996327;0.038419;0.076524;, - -0.994571;0.104035;-0.002266;, - 0.000000;-0.995327;0.096563;, - 0.000000;0.317049;-0.948409;, - 0.000000;0.317049;-0.948409;, - 0.000000;-0.818404;-0.574643;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.998092;0.061747;, - 0.000000;-0.995327;0.096563;, - 0.000000;-0.818404;-0.574643;, - 0.999257;0.038532;0.001036;, - 0.000000;0.317049;-0.948409;, - 0.999257;0.038532;0.001036;, - 0.000000;0.317049;-0.948409;, - 0.000000;-1.000000;0.000000;, - 0.996327;0.038419;0.076524;, - 0.511973;0.849126;0.129878;, - 0.996327;0.038420;0.076524;, - 0.863785;0.365054;0.347291;, - 0.000000;0.998092;0.061747;, - 0.994571;0.104035;-0.002266;, - 0.000000;-0.995327;0.096563;, - -0.998651;0.051906;-0.001130;, - -0.673085;0.543157;0.501933;, - -0.673085;0.543157;0.501933;, - -0.673085;0.543157;0.501933;, - -0.681821;-0.000000;0.731519;, - -0.681821;-0.000000;0.731519;, - -0.673085;-0.543157;0.501933;, - -0.673085;-0.543157;0.501933;, - -0.673085;-0.543157;0.501933;, - -0.599172;-0.557346;0.574768;, - -0.599172;-0.557346;0.574768;, - -0.599172;-0.557346;0.574768;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.215555;0.976492;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.734960;0.678111;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.000000;1.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.601258;-0.745604;0.287339;, - 0.601258;-0.745604;0.287339;, - 0.601258;-0.745604;0.287339;, - 0.000000;1.000000;0.000000;, - 0.000000;0.215555;0.976492;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.215556;0.976492;, - 0.673085;0.543157;0.501933;, - 0.673085;0.543157;0.501933;, - 0.673085;0.543157;0.501933;, - 0.681820;-0.000000;0.731520;, - 0.681820;-0.000000;0.731520;, - 0.673085;-0.543157;0.501933;, - 0.673085;-0.543157;0.501933;, - 0.673085;-0.543157;0.501933;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.215555;0.976492;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.734960;0.678111;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.215556;0.976492;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.999984;0.005657;, - -1.000000;0.000000;0.000000;, - 0.000000;0.734960;0.678111;, - 0.000000;0.734960;0.678111;, - 0.000000;-0.999941;0.010885;, - 0.000000;0.734960;0.678111;, - 0.000000;0.734960;0.678111;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999984;0.005657;, - 1.000000;0.000000;0.000000;, - 0.000000;0.734960;0.678111;, - 0.000000;0.734960;0.678111;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.877728;-0.330691;0.346751;, - -0.877728;-0.330691;0.346751;, - -0.877728;-0.330691;0.346751;, - -0.877728;-0.330691;0.346751;, - -0.395322;-0.904274;0.161270;, - -0.395322;-0.904274;0.161270;, - -0.395322;-0.904274;0.161270;, - -0.420034;-0.907509;0.000000;, - -0.420034;-0.907509;0.000000;, - -0.420034;-0.907509;0.000000;, - -0.938714;-0.344697;0.000000;, - -0.938714;-0.344697;0.000000;, - -0.938714;-0.344697;0.000000;, - -0.938714;-0.344697;0.000000;, - -0.877730;0.330686;0.346752;, - -0.877730;0.330686;0.346752;, - -0.877730;0.330686;0.346752;, - -0.877730;0.330686;0.346752;, - -0.395326;0.904272;0.161272;, - -0.395326;0.904272;0.161272;, - -0.395326;0.904272;0.161272;, - -0.420038;0.907506;0.000000;, - -0.420038;0.907506;0.000000;, - -0.420038;0.907506;0.000000;, - -0.938716;0.344692;0.000000;, - -0.938716;0.344692;0.000000;, - -0.938716;0.344692;0.000000;, - -0.938716;0.344692;0.000000;, - -0.887308;-0.461177;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -0.901160;-0.433486;0.000000;, - 0.000000;1.000000;0.000000;, - 0.852367;0.000000;0.522944;, - 0.852367;0.000000;0.522944;, - 0.833659;0.000000;-0.552279;, - 0.833659;0.000000;-0.552279;, - 0.833659;0.000000;-0.552279;, - 0.000000;1.000000;0.000000;, - 0.833659;0.000000;-0.552279;, - 0.852367;0.000000;0.522944;, - 0.852367;0.000000;0.522944;, - 0.000000;1.000000;0.000000;, - 0.232937;0.000000;0.972492;, - 0.000000;1.000000;0.000000;, - 0.232937;0.000000;0.972492;, - 0.000000;-1.000000;0.000000;, - 0.833659;0.000000;-0.552279;, - 0.833659;0.000000;-0.552279;, - 0.852367;0.000000;0.522944;, - 0.000000;-1.000000;0.000000;, - 0.852367;0.000000;0.522944;, - 0.000000;-1.000000;0.000000;, - 0.232937;0.000000;0.972492;, - -0.505754;-0.862678;0.000000;, - 0.000000;0.000000;1.000000;, - -0.505754;-0.862678;0.000000;, - 0.334945;0.942238;0.000000;, - 0.163134;-0.084065;0.983016;, - 0.334945;0.942238;0.000000;, - -0.631267;0.775565;0.000000;, - -0.631267;0.775565;0.000000;, - 0.163134;-0.084065;0.983016;, - 0.356870;-0.669711;0.651254;, - -0.986099;0.166158;0.000000;, - 0.356870;-0.669711;0.651254;, - 0.356870;-0.669711;0.651254;, - 0.356870;-0.669711;0.651254;, - 0.601679;0.798738;0.000000;, - 0.601679;0.798738;0.000000;, - 0.356869;-0.669712;-0.651253;, - 0.356869;-0.669712;-0.651253;, - 0.953833;0.300339;0.000000;, - 0.000000;0.000000;1.000000;, - 0.953833;0.300339;0.000000;, - 0.712537;0.701634;0.000000;, - -0.682801;0.730605;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -0.682801;0.730605;0.000000;, - -0.712526;-0.701646;0.000000;, - 0.000000;0.000000;1.000000;, - -0.712526;-0.701646;0.000000;, - 0.985989;-0.166808;0.000000;, - 0.933289;-0.359126;0.000000;, - 0.000000;0.000000;1.000000;, - 0.933289;-0.359126;0.000000;, - 0.797086;0.603866;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.337034;0.941492;0.000000;, - -0.997575;-0.069594;0.000000;, - 0.000000;0.000000;1.000000;, - -0.997575;-0.069594;0.000000;, - 0.693605;-0.720355;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.747101;0.000000;0.664711;, - 0.000000;-1.000000;0.000000;, - -0.747101;0.000000;0.664711;, - -0.747101;0.000000;0.664711;, - 0.000000;1.000000;0.000000;, - -0.747101;0.000000;0.664711;, - -1.000000;-0.000001;-0.000002;, - 0.000000;1.000000;0.000000;, - -1.000000;-0.000001;-0.000002;, - 0.000000;-1.000000;0.000000;, - -0.747099;-0.000002;-0.664713;, - -0.747099;-0.000002;-0.664713;, - 0.000000;-1.000000;0.000000;, - -0.747099;-0.000002;-0.664713;, - -0.747099;-0.000002;-0.664713;, - 0.000000;1.000000;0.000000;, - 0.502197;-0.844060;0.188043;, - 0.502197;-0.844060;0.188043;, - 0.872012;-0.358050;0.333759;, - 0.872012;-0.358050;0.333759;, - 0.872012;-0.358050;0.333759;, - 0.467763;-0.861860;-0.195947;, - 0.467763;-0.861860;-0.195947;, - 0.445914;-0.895076;0.000000;, - 0.445914;-0.895076;0.000000;, - 0.445914;-0.895076;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.445914;-0.895076;0.000000;, - 0.445914;-0.895076;0.000000;, - 0.445914;-0.895076;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.948223;-0.317605;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.872012;0.358050;0.333759;, - 0.872012;0.358050;0.333759;, - 0.872012;0.358050;0.333759;, - 0.502197;0.844060;0.188043;, - 0.502197;0.844060;0.188043;, - 0.467763;0.861860;-0.195947;, - 0.467763;0.861860;-0.195947;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.445914;0.895076;0.000000;, - 0.445914;0.895076;0.000000;, - 0.445914;0.895076;0.000000;, - 0.948223;0.317605;0.000000;, - 0.948223;0.317605;0.000000;, - 0.948223;0.317605;0.000000;, - 0.948223;0.317605;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.445914;0.895076;0.000000;, - 0.445914;0.895076;0.000000;, - 0.445914;0.895076;0.000000;, - 0.948223;0.317605;0.000000;, - 0.948223;0.317605;0.000000;, - 0.948223;0.317605;0.000000;, - 0.948223;0.317605;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.009641;0.000000;0.999954;, - 0.000000;1.000000;0.000000;, - -0.009641;0.000000;0.999954;, - 0.000000;-1.000000;0.000000;, - 0.007275;0.000000;0.999974;, - 0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - 0.000000;1.000000;0.000000;, - 0.007275;0.000000;0.999974;, - 0.000000;-1.000000;0.000000;, - -0.947824;0.000000;-0.318793;, - 0.000000;-1.000000;0.000000;, - -0.444793;0.000000;0.895634;, - -0.444793;0.000000;0.895634;, - 0.000000;-1.000000;0.000000;, - -0.947824;0.000000;0.318793;, - -0.947824;0.000000;0.318793;, - -0.947824;0.000000;-0.318793;, - -0.444793;0.000000;0.895634;, - -0.444793;0.000000;0.895634;, - 0.000000;1.000000;0.000000;, - -0.947824;0.000000;-0.318793;, - -0.947824;0.000000;0.318793;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.444793;0.000000;0.895634;, - -0.444793;0.000000;0.895634;, - 0.812847;0.000000;0.582477;, - 0.812847;0.000000;0.582477;, - 0.000000;-1.000000;0.000000;, - 0.920207;0.000000;-0.391432;, - 0.000000;-1.000000;0.000000;, - 0.920207;0.000000;-0.391432;, - 0.000000;1.000000;0.000000;, - 0.812847;0.000000;0.582477;, - 0.812847;0.000000;0.582477;, - 0.000000;1.000000;0.000000;, - 0.519988;0.000000;-0.854174;, - 0.000000;-1.000000;0.000000;, - 0.519988;0.000000;-0.854174;, - 0.519988;0.000000;-0.854174;, - 0.000000;1.000000;0.000000;, - 0.519988;0.000000;-0.854174;, - 0.000000;1.000000;0.000000;, - 0.225237;0.000000;0.974304;, - 0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;1.000000;0.000000;, - -0.009641;0.000000;0.999954;, - 0.999835;0.000000;-0.018151;, - 0.000000;-1.000000;0.000000;, - 0.999835;0.000000;-0.018151;, - 0.000000;1.000000;0.000000;, - -0.009641;0.000000;0.999954;, - -0.003775;0.861001;0.508589;, - -0.003775;0.861001;0.508589;, - -0.003775;0.861001;0.508589;, - -0.751444;0.431738;0.498932;, - -0.751444;0.431738;0.498932;, - -0.751444;0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.003775;-0.861001;0.508589;, - -0.003775;-0.861001;0.508589;, - -0.003775;-0.861001;0.508589;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.000000;0.000000;-1.000000;, - -0.943629;-0.331006;0.000000;, - -0.000000;0.000000;-1.000000;, - -0.433190;-0.901303;0.000000;, - -0.000000;-0.000000;-1.000000;, - -0.433190;-0.901303;0.000000;, - -0.000000;-0.000000;-1.000000;, - -0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.444792;0.000000;0.895634;, - 0.444792;0.000000;0.895634;, - 0.947824;0.000000;-0.318793;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.947824;0.000000;0.318794;, - 0.444792;0.000000;0.895634;, - 0.444792;0.000000;0.895634;, - 0.947824;0.000000;0.318794;, - 0.947824;0.000000;-0.318793;, - 0.000000;1.000000;0.000000;, - 0.444792;0.000000;0.895634;, - 0.444792;0.000000;0.895634;, - 0.000000;1.000000;0.000000;, - 0.947824;0.000000;0.318794;, - 0.000000;1.000000;0.000000;, - 0.947824;0.000000;-0.318793;, - 0.739674;-0.429301;0.518250;, - 0.739674;-0.429301;0.518250;, - 0.739674;-0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - -0.923880;0.382683;0.000000;, - -0.000000;0.000000;1.000000;, - -0.923880;0.382683;0.000000;, - -0.923880;0.382683;0.000000;, - -0.923880;0.382683;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.923880;-0.382683;0.000000;, - -0.000000;-0.000000;1.000000;, - -0.923880;-0.382683;0.000000;, - -0.923880;-0.382683;0.000000;, - -0.923880;-0.382683;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.100988;-0.994888;-0.000000;, - 0.492699;-0.870200;0.000000;, - -0.000000;-0.000000;-1.000000;, - 0.492699;-0.870200;0.000000;, - -0.000000;-0.000000;-1.000000;, - 0.492699;-0.870200;0.000000;, - -0.000000;0.000000;-1.000000;, - 0.100988;-0.994888;-0.000000;, - -0.382683;0.923880;0.000000;, - -0.000000;0.000000;1.000000;, - -0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.382683;0.923880;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.382683;-0.923880;0.000000;, - -0.000000;-0.000000;1.000000;, - -0.382683;-0.923880;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.382683;-0.923880;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.382683;-0.923880;0.000000;, - -0.000000;-0.000000;1.000000;, - 0.410296;0.911952;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.410296;0.911952;0.000000;, - -0.000000;-0.000000;1.000000;, - -0.000000;-0.000000;1.000000;, - 0.000000;-0.000000;-1.000000;, - 1.000000;0.000000;-0.000000;, - 0.000000;-1.000000;0.000000;, - 0.100988;-0.994888;-0.000000;, - 0.331004;-0.943629;0.000000;, - -0.000000;0.000000;-1.000000;, - 0.901302;-0.433191;-0.000000;, - 0.901302;-0.433191;-0.000000;, - -0.000000;0.000000;-1.000000;, - 1.000000;0.000000;-0.000000;, - 0.000000;-1.000000;0.000000;, - -0.000000;0.000000;-1.000000;, - -0.000000;0.000000;-1.000000;, - 0.100988;-0.994888;-0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.922348;0.386359;0.000000;, - -0.701454;-0.712715;0.000000;, - -0.000000;0.000000;1.000000;, - -0.701454;-0.712715;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.922348;0.386359;0.000000;, - 0.934971;0.354724;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.934971;0.354724;0.000000;, - 0.934971;0.354724;0.000000;, - 0.934971;0.354724;0.000000;, - -0.000000;-0.000000;1.000000;, - -0.000000;-0.000000;1.000000;, - 0.701454;0.712715;0.000000;, - -0.701454;-0.712715;0.000000;, - 0.707107;-0.707107;0.000000;, - -0.000000;0.000000;1.000000;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.000000;-1.000000;, - -0.701454;-0.712715;0.000000;, - 0.707107;-0.707107;0.000000;, - 0.701454;0.712715;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.894428;0.447212;0.000000;, - -0.894428;0.447212;0.000000;, - -0.316229;0.948683;0.000000;, - -0.894428;0.447212;0.000000;, - -0.894428;0.447212;0.000000;, - -0.316229;0.948683;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.382684;0.923879;-0.000000;, - 0.382684;0.923879;-0.000000;, - 0.923880;0.382683;-0.000000;, - 0.382684;0.923879;-0.000000;, - 0.382684;0.923879;-0.000000;, - 0.923880;0.382683;-0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.467971;0.748047;0.470562;, - -0.467971;0.748047;0.470562;, - -0.448202;0.785835;-0.426119;, - -0.448202;0.785835;-0.426119;, - -0.734898;0.095942;-0.671356;, - -0.734898;0.095942;-0.671356;, - -1.000000;0.000000;0.000000;, - -0.000216;0.747545;-0.664211;, - -0.000216;0.747545;-0.664211;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.780420;0.375853;-0.499679;, - -0.780420;0.375853;-0.499679;, - -0.780420;0.375853;-0.499679;, - -0.255331;0.610630;-0.749625;, - -0.255331;0.610630;-0.749625;, - 0.000000;0.657542;-0.753418;, - 0.000000;0.657542;-0.753418;, - -0.000100;0.382250;-0.924059;, - -0.000100;0.382250;-0.924059;, - 0.000000;0.058903;-0.998264;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.999885;0.015182;0.000000;, - -0.999885;0.015182;0.000000;, - -0.999956;-0.009391;0.000000;, - -0.999956;-0.009391;0.000000;, - -0.186216;0.982509;0.000000;, - 0.000000;1.000000;0.000000;, - -0.817769;0.575546;0.000000;, - -0.817769;0.575546;0.000000;, - -0.164920;-0.986307;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.808550;-0.588427;0.000000;, - -0.808550;-0.588427;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.793192;0.608972;, - 0.000000;0.793192;0.608972;, - 0.000000;0.838762;-0.544498;, - 0.000000;0.838762;-0.544498;, - -0.486044;-0.714149;0.503739;, - -0.486044;-0.714149;0.503739;, - -0.486044;-0.714149;0.503739;, - -0.729011;0.129146;0.672209;, - -0.729011;0.129146;0.672209;, - -0.729011;0.129146;0.672209;, - -0.535202;-0.323949;0.780138;, - -0.535202;-0.323949;0.780138;, - -0.535202;-0.323949;0.780138;, - 0.000000;-0.862942;0.505302;, - 0.000000;-0.862942;0.505302;, - 0.000000;0.177449;0.984130;, - 0.000000;0.177449;0.984130;, - 0.000000;-0.483412;0.875393;, - 0.000000;-0.483412;0.875393;, - 0.486044;-0.714149;0.503739;, - 0.486044;-0.714149;0.503739;, - 0.486044;-0.714149;0.503739;, - 0.729011;0.129146;0.672209;, - 0.729011;0.129146;0.672209;, - 0.729011;0.129146;0.672209;, - 0.535202;-0.323949;0.780138;, - 0.535202;-0.323949;0.780138;, - 0.535202;-0.323949;0.780138;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.481363;0.876521;, - 0.000000;-0.481363;0.876521;, - -0.704085;-0.354065;0.615550;, - -0.704085;-0.354065;0.615550;, - -0.704085;-0.354065;0.615550;, - -0.683829;0.118010;0.720036;, - -0.683829;0.118010;0.720036;, - 0.000000;0.104270;0.994549;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.481363;0.876521;, - 0.000000;-0.481363;0.876521;, - 0.683829;0.118010;0.720036;, - 0.683829;0.118010;0.720036;, - 0.704085;-0.354065;0.615550;, - 0.704085;-0.354065;0.615550;, - 0.704085;-0.354065;0.615550;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -0.671803;0.000000;0.740730;, - -0.671803;0.000000;0.740730;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.671803;0.000000;0.740730;, - 0.671803;0.000000;0.740730;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.575435;0.817848;, - 0.000000;-0.575435;0.817848;, - 0.000000;-0.304659;0.952461;, - -0.992902;-0.118932;0.000000;, - 0.000000;-0.912569;0.408924;, - 0.000000;-0.912569;0.408924;, - 0.000000;-0.304659;0.952461;, - 0.996514;-0.083420;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.575435;0.817848;, - 0.000000;-0.575435;0.817848;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - -0.712713;-0.627305;0.313893;, - -0.712713;-0.627305;0.313893;, - -0.712713;-0.627305;0.313893;, - 0.000000;-0.861394;0.507938;, - 0.000000;-0.861394;0.507938;, - -0.995295;-0.096836;-0.003218;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - -0.999860;0.000000;-0.016753;, - -0.006548;0.000000;0.999979;, - 0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - -1.000000;0.000000;0.000000;, - 0.000000;0.175892;0.984409;, - -1.000000;0.000000;0.000000;, - 0.000000;0.821703;0.569915;, - 0.000000;0.821703;0.569915;, - 0.000000;-0.010682;0.999943;, - 0.000000;0.821703;0.569915;, - 0.000000;0.821703;0.569915;, - 1.000000;0.000000;0.000000;, - 0.000000;0.175892;0.984409;, - 1.000000;0.000000;0.000000;, - 0.000000;0.821703;0.569915;, - 0.000000;0.821703;0.569915;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.228734;0.973489;, - -0.623102;0.286079;0.727944;, - 0.000000;-1.000000;0.000000;, - -0.623102;0.286079;0.727944;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.964942;0.262464;, - -0.999551;-0.028922;-0.007867;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.964942;0.262464;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.855810;0.517291;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.491279;0.871002;, - 0.000000;-0.494957;-0.868917;, - 0.000000;-0.494957;-0.868917;, - -0.414336;-0.420954;-0.806922;, - -0.414336;-0.420954;-0.806922;, - -0.414336;-0.420954;-0.806922;, - -0.414336;-0.420954;-0.806922;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.225248;-0.235329;0.945454;, - -0.237889;-0.660874;0.711797;, - -0.237889;-0.660874;0.711797;, - -0.694911;-0.059586;0.716623;, - -0.694911;-0.059586;0.716623;, - -0.724776;-0.636464;0.263843;, - -0.724776;-0.636464;0.263843;, - -0.724776;-0.636464;0.263843;, - -0.724776;-0.636464;0.263843;, - 0.000000;0.028439;0.999596;, - -0.656366;-0.210294;0.724542;, - -0.656366;-0.210294;0.724542;, - -0.660218;0.043171;0.749833;, - -0.660218;0.043171;0.749833;, - 0.000000;-0.855810;0.517291;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.855810;0.517291;, - 0.000000;-0.491279;0.871002;, - 0.000000;-0.491279;0.871002;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.694911;-0.059586;0.716623;, - 0.694911;-0.059586;0.716623;, - 0.724776;-0.636464;0.263843;, - 0.724776;-0.636464;0.263843;, - 0.724776;-0.636464;0.263843;, - 0.724776;-0.636464;0.263843;, - 0.225248;-0.235329;0.945454;, - 0.237889;-0.660874;0.711797;, - 0.237889;-0.660874;0.711797;, - -0.181527;-0.897955;0.400904;, - -0.181527;-0.897955;0.400904;, - -0.181527;-0.897955;0.400904;, - -0.388340;-0.313507;0.866548;, - -0.388340;-0.313507;0.866548;, - -0.388340;-0.313507;0.866548;, - -0.388340;-0.313507;0.866548;, - -0.388341;0.313505;0.866548;, - -0.388341;0.313505;0.866548;, - -0.388341;0.313505;0.866548;, - -0.388341;0.313505;0.866548;, - -0.181529;0.897954;0.400905;, - -0.181529;0.897954;0.400905;, - -0.181529;0.897954;0.400905;, - 0.007275;0.000000;0.999974;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;-0.016753;, - 0.007275;0.000000;0.999974;, - -0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - 0.999860;0.000000;0.016753;, - -0.999860;0.000000;-0.016753;, - -0.999860;0.000000;-0.016753;, - 0.999860;0.000000;0.016753;, - -0.006548;0.000000;0.999979;, - 0.999860;0.000000;0.016753;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - -0.006548;0.000000;0.999979;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - 0.368706;-0.354448;0.859315;, - 0.368706;-0.354448;0.859315;, - 0.368706;-0.354448;0.859315;, - 0.368706;-0.354448;0.859315;, - 0.155472;-0.914282;0.374054;, - -0.000000;-0.300369;0.953823;, - -0.000000;-0.300369;0.953823;, - -0.000000;-0.300369;0.953823;, - -0.000000;-0.300369;0.953823;, - 0.000000;-0.929961;0.367659;, - 0.000000;-0.929961;0.367659;, - -0.000000;-0.886848;0.462062;, - -0.000000;-0.886848;0.462062;, - 0.368706;0.354448;0.859315;, - 0.368706;0.354448;0.859315;, - 0.368706;0.354448;0.859315;, - 0.155472;0.914282;0.374054;, - -0.000000;0.300369;0.953823;, - -0.000000;0.300369;0.953823;, - -0.000000;0.886848;0.462062;, - -0.000000;0.886848;0.462062;, - -0.000000;0.929961;0.367659;, - -0.000000;0.929961;0.367659;, - -0.000000;0.300369;0.953823;, - -0.000000;0.300369;0.953823;, - -0.008294;0.000000;0.999966;, - -0.952657;0.000000;0.304046;, - -0.952657;0.000000;0.304046;, - -0.897253;-0.281640;0.340023;, - -0.897253;-0.281640;0.340023;, - -0.428060;-0.799374;0.421624;, - -0.428060;-0.799374;0.421624;, - -0.428060;-0.799374;0.421624;, - -0.428060;-0.799374;0.421624;, - -0.410415;-0.110414;0.905189;, - -0.410415;-0.110414;0.905189;, - -0.458637;0.000000;0.888624;, - -0.458637;0.000000;0.888624;, - 0.418146;-0.801329;0.427815;, - 0.418146;-0.801329;0.427815;, - 0.418146;-0.801329;0.427815;, - 0.421913;-0.784056;0.455242;, - 0.421913;-0.784056;0.455242;, - 0.421913;-0.784056;0.455242;, - 0.000000;-0.000000;1.000000;, - 0.115463;-0.249286;0.961522;, - 0.115463;-0.249286;0.961522;, - -0.179157;-0.288632;0.940529;, - -0.179157;-0.288632;0.940529;, - 0.000000;0.000000;1.000000;, - 0.191832;-0.385043;0.902742;, - 0.000000;-0.000000;1.000000;, - 0.292367;-0.866429;0.404750;, - 0.292367;-0.866429;0.404750;, - 0.292367;-0.866429;0.404750;, - 0.830569;-0.387539;0.399961;, - 0.830569;-0.387539;0.399961;, - 0.830569;-0.387539;0.399961;, - 0.830569;-0.387539;0.399961;, - 0.000000;0.000000;1.000000;, - 0.109902;-0.344862;0.932197;, - 0.109902;-0.344862;0.932197;, - 0.945889;0.000000;0.324489;, - 0.945889;0.000000;0.324489;, - 0.439396;0.000000;0.898293;, - 0.439396;0.000000;0.898293;, - 0.442680;-0.198092;0.874525;, - 0.442680;-0.198092;0.874525;, - 0.000000;0.445625;0.895220;, - 0.000000;0.797864;0.602838;, - 0.000000;0.000000;-1.000000;, - -0.410381;0.364278;-0.835996;, - -0.410381;0.364278;-0.835996;, - -0.410381;0.364278;-0.835996;, - -0.410381;0.364278;-0.835996;, - 0.000000;0.435777;-0.900055;, - 0.000000;0.435777;-0.900055;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - -0.222802;0.267250;0.937516;, - -0.694989;0.067591;0.715836;, - -0.694989;0.067591;0.715836;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.656242;0.365940;0.659875;, - 0.000000;0.445625;0.895220;, - 0.000000;0.445625;0.895220;, - 0.000000;0.797864;0.602838;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.797864;0.602838;, - 0.000000;0.000000;-1.000000;, - -0.598854;-0.729241;-0.331031;, - -0.598854;-0.729241;-0.331031;, - -0.598854;-0.729241;-0.331031;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.948481;0.316834;, - 1.000000;0.000000;0.000000;, - -0.294926;-0.896305;0.331144;, - -0.294926;-0.896305;0.331144;, - -0.458630;0.558096;-0.691511;, - -0.458630;0.558096;-0.691511;, - 0.000000;0.803358;-0.595497;, - -0.920337;-0.258232;-0.293762;, - -0.843584;0.257465;-0.471252;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999619;0.027602;, - -0.912505;0.010391;-0.408934;, - -0.912505;0.010391;-0.408934;, - -0.665236;0.018966;-0.746392;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.694990;0.067591;0.715836;, - 0.694990;0.067591;0.715836;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.222802;0.267250;0.937516;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;-0.016753;, - 0.006548;0.000000;-0.999979;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - 0.006548;0.000000;-0.999979;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - -0.999860;0.000000;-0.016754;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - -0.006548;0.000000;0.999979;, - 0.999860;0.000000;0.016753;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - -0.006548;0.000000;0.999979;, - 0.006548;0.000000;-0.999979;, - 0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - 0.999860;0.000000;0.016753;, - -0.006548;0.000000;0.999979;, - -0.006548;0.000000;0.999979;, - -0.999860;0.000000;-0.016753;, - -0.999860;0.000000;-0.016753;, - 0.006548;0.000000;-0.999979;, - 0.000000;-1.000000;0.000000;, - -0.831040;0.403243;0.383102;, - -0.831040;0.403243;0.383102;, - -0.831040;0.403243;0.383102;, - -0.831040;0.403243;0.383102;, - -0.282244;0.875709;0.391756;, - -0.282244;0.875709;0.391756;, - -0.282244;0.875709;0.391756;, - -0.457151;0.212943;0.863521;, - -0.457151;0.212943;0.863521;, - 0.000000;0.933082;0.359664;, - 0.000000;0.933082;0.359664;, - 0.000000;0.405468;0.914109;, - 0.000000;0.405468;0.914109;, - -0.109882;0.357779;0.927319;, - -0.109882;0.357779;0.927319;, - 0.349235;0.855784;0.381665;, - 0.349235;0.855784;0.381665;, - 0.349235;0.855784;0.381665;, - 0.349235;0.855784;0.381665;, - 0.859819;0.357289;0.364767;, - 0.859819;0.357289;0.364767;, - 0.859819;0.357289;0.364767;, - 0.142369;0.355966;0.923590;, - 0.142369;0.355966;0.923590;, - 0.486422;0.202974;0.849820;, - 0.486422;0.202974;0.849820;, - -0.231731;0.696564;0.679043;, - -0.231731;0.696564;0.679043;, - -0.718709;0.648693;0.250309;, - -0.718709;0.648693;0.250309;, - -0.718709;0.648693;0.250309;, - -0.718709;0.648693;0.250309;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - -0.919279;0.393601;-0.001941;, - -0.919279;0.393601;-0.001941;, - 0.000000;-0.834468;0.551056;, - -1.000000;0.000000;0.000000;, - -0.370322;0.928840;-0.010859;, - 0.000000;0.999861;-0.016680;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - -0.999885;0.015182;0.000000;, - -0.999885;0.015182;0.000000;, - -0.999956;-0.009391;0.000000;, - -0.999956;-0.009391;0.000000;, - -0.186216;0.982509;0.000000;, - -0.817769;0.575546;0.000000;, - -0.817769;0.575546;0.000000;, - -0.164920;-0.986307;0.000000;, - -0.808550;-0.588427;0.000000;, - -0.808550;-0.588427;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.999519;-0.012421;0.028413;, - 0.000000;-0.975913;0.218160;, - 0.718710;0.648693;0.250309;, - 0.718710;0.648693;0.250309;, - 0.718710;0.648693;0.250309;, - 0.718710;0.648693;0.250309;, - 0.231732;0.696564;0.679043;, - 0.231732;0.696564;0.679043;, - 0.000000;-0.249931;0.968264;, - -0.449264;-0.278514;0.848877;, - -0.996793;-0.079877;-0.004828;, - -0.879287;-0.284211;0.382202;, - 0.000000;-0.249931;0.968264;, - -0.999551;-0.028922;-0.007867;, - 0.000000;0.607263;0.794501;, - 0.000000;0.607263;0.794501;, - -0.920795;-0.364979;-0.137577;, - -0.920795;-0.364979;-0.137577;, - -0.924846;-0.329505;0.189965;, - -0.924846;-0.329505;0.189965;, - -0.924846;-0.329505;0.189965;, - -0.868861;-0.198793;-0.453389;, - -0.868861;-0.198793;-0.453389;, - -0.374350;-0.888608;-0.265025;, - -0.374350;-0.888608;-0.265025;, - 0.000000;-0.964405;-0.264430;, - 0.000000;-0.869582;0.493788;, - 0.000000;-0.869582;0.493788;, - -0.379211;-0.803330;0.459195;, - -0.379211;-0.803330;0.459195;, - -0.379211;-0.803330;0.459195;, - -1.000000;0.000000;0.000000;, - -0.910502;0.394198;0.124877;, - -0.918267;0.364101;-0.155619;, - -0.918267;0.364101;-0.155619;, - -0.852588;-0.139808;0.503535;, - -0.852588;-0.139808;0.503535;, - -0.881297;0.207501;0.424568;, - -0.881297;0.207501;0.424568;, - -0.867287;0.166714;-0.469062;, - -0.867287;0.166714;-0.469062;, - 0.000000;-0.265726;0.964049;, - -0.369966;-0.247588;0.895447;, - -0.369966;-0.247588;0.895447;, - 0.000000;0.441670;0.897178;, - 0.000000;0.441670;0.897178;, - -0.413389;0.401188;0.817410;, - -0.413389;0.401188;0.817410;, - -0.413389;0.401188;0.817410;, - -0.413389;0.401188;0.817410;, - 0.000000;0.946708;0.322092;, - -0.345924;0.891018;0.293977;, - -0.345924;0.891018;0.293977;, - 0.000000;0.944576;-0.328294;, - -0.363628;0.875934;-0.317041;, - -0.363628;0.875934;-0.317041;, - -0.892669;-0.416427;0.172425;, - -0.892669;-0.416427;0.172425;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999666;0.025839;, - -1.000000;0.000000;0.000000;, - -0.365213;0.930924;0.000867;, - -0.916507;0.400018;0.000880;, - -0.916507;0.400018;0.000880;, - -0.916507;-0.400018;0.000881;, - -0.916507;-0.400018;0.000881;, - -0.365213;-0.930924;0.000867;, - -0.747129;-0.554595;0.366363;, - -0.747129;-0.554595;0.366363;, - -0.747129;-0.554595;0.366363;, - -0.947248;0.154288;0.280921;, - -0.947248;0.154288;0.280921;, - -0.947248;0.154288;0.280921;, - -0.196577;-0.789407;0.581544;, - -0.196577;-0.789407;0.581544;, - -0.540165;0.139016;0.829998;, - -0.313397;-0.205419;0.927138;, - -0.360386;0.905749;0.223026;, - -0.550087;0.653417;0.520048;, - 0.000000;-0.776534;0.630075;, - 0.000000;-0.776534;0.630075;, - 0.000000;0.973368;0.229249;, - 0.000000;-0.206011;0.978550;, - 0.000000;-0.694243;0.719740;, - -0.999519;-0.012421;0.028413;, - -0.999519;-0.012421;0.028413;, - 0.000000;-0.182834;0.983144;, - 0.000000;-0.694243;0.719740;, - -0.297687;0.906393;-0.299723;, - -0.297687;0.906393;-0.299723;, - 0.000000;0.949568;-0.313562;, - -0.888768;0.435110;-0.144120;, - -0.888768;0.435110;-0.144120;, - 0.000000;-0.629060;0.777357;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.629060;0.777357;, - -0.253225;-0.608206;0.752305;, - -0.253225;-0.608206;0.752305;, - -0.253225;-0.608206;0.752305;, - -0.253225;-0.608206;0.752305;, - -0.346801;-0.205807;0.915080;, - -0.346801;-0.205807;0.915080;, - 0.000000;-0.432176;0.901789;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.143364;0.989670;, - 0.000000;-0.827784;0.561046;, - -0.867484;-0.312547;0.387021;, - -0.867484;-0.312547;0.387021;, - -0.867484;-0.312547;0.387021;, - -0.909236;-0.093398;0.405669;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999215;0.039615;, - -1.000000;0.000000;0.000000;, - -0.993070;0.000000;0.117523;, - 0.000000;-0.976749;0.214388;, - -0.515284;-0.506815;0.691102;, - -0.515284;-0.506815;0.691102;, - -0.515284;-0.506815;0.691102;, - -0.523532;0.520184;0.674777;, - -0.523532;0.520184;0.674777;, - -0.523532;0.520184;0.674777;, - -0.993070;0.000000;0.117523;, - 0.000000;0.986719;0.162438;, - 0.000000;-0.626742;0.779227;, - 0.000000;-0.626742;0.779227;, - 0.000000;0.647133;0.762377;, - 0.000000;0.647133;0.762377;, - -0.356854;0.918943;0.167923;, - -0.264647;0.688916;0.674802;, - -0.264647;0.688916;0.674802;, - 0.000000;0.610148;0.792287;, - 0.000000;0.610148;0.792287;, - 0.000000;0.991672;0.128792;, - -0.903543;0.390832;0.175672;, - -0.903543;0.390832;0.175672;, - -0.505677;0.216655;0.835075;, - -0.505677;0.216655;0.835075;, - -0.505677;0.216655;0.835075;, - -0.903542;-0.390835;0.175672;, - -0.903542;-0.390835;0.175672;, - -0.505675;-0.216658;0.835076;, - -0.505675;-0.216658;0.835076;, - -0.505675;-0.216658;0.835076;, - -0.356852;-0.918945;0.167922;, - 0.000000;-0.991672;0.128791;, - 0.000000;-0.610149;0.792287;, - 0.000000;-0.610149;0.792287;, - -0.264644;-0.688919;0.674800;, - -0.264644;-0.688919;0.674800;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.493245;0.869891;, - 0.000000;0.493245;0.869891;, - -0.415843;0.444085;0.793639;, - -0.415843;0.444085;0.793639;, - -0.415843;0.444085;0.793639;, - -0.415843;0.444085;0.793639;, - -0.342656;0.907349;0.243524;, - -0.342656;0.907349;0.243524;, - 0.000000;0.963882;0.266329;, - -0.908555;0.404498;0.104448;, - -0.908555;0.404498;0.104448;, - -0.882298;0.226639;0.412534;, - 1.000000;-0.000000;-0.000000;, - -0.689334;0.531821;-0.491919;, - -0.689334;0.531821;-0.491919;, - -0.689334;0.531821;-0.491919;, - -0.697330;-0.000000;-0.716750;, - -0.697330;-0.000000;-0.716750;, - -0.689334;-0.531822;-0.491919;, - -0.689334;-0.531822;-0.491919;, - -0.689334;-0.531822;-0.491919;, - -0.682700;-0.730699;0.000000;, - -0.682700;-0.730699;0.000000;, - -1.000000;-0.000000;-0.000000;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.689334;0.531821;-0.491919;, - 0.689334;0.531821;-0.491919;, - 0.689334;0.531821;-0.491919;, - 0.697330;-0.000000;-0.716750;, - 0.697330;-0.000000;-0.716750;, - 0.689334;-0.531822;-0.491919;, - 0.689334;-0.531822;-0.491919;, - 0.689334;-0.531822;-0.491919;, - 0.682700;-0.730699;0.000000;, - 0.682700;-0.730699;0.000000;, - -0.682700;0.730699;0.000000;, - -0.682700;0.730699;0.000000;, - 0.000000;1.000000;0.000000;, - 0.682700;0.730699;0.000000;, - 0.682700;0.730699;0.000000;, - -0.689334;0.531821;0.491919;, - -0.689334;0.531821;0.491919;, - -0.689334;0.531821;0.491919;, - -0.697331;-0.000000;0.716750;, - -0.697331;-0.000000;0.716750;, - -0.689334;-0.531822;0.491919;, - -0.689334;-0.531822;0.491919;, - -0.689334;-0.531822;0.491919;, - 0.000000;-0.000000;1.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.689334;0.531821;0.491919;, - 0.689334;0.531821;0.491919;, - 0.689334;0.531821;0.491919;, - 0.697331;-0.000000;0.716750;, - 0.697331;-0.000000;0.716750;, - 0.689334;-0.531822;0.491919;, - 0.689334;-0.531822;0.491919;, - 0.689334;-0.531822;0.491919;, - 0.000000;-0.976748;0.214391;, - 0.000000;0.986719;0.162435;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.365213;0.930924;0.000867;, - -0.916507;0.400018;0.000881;, - -0.916507;0.400018;0.000881;, - -0.916507;-0.400018;0.000881;, - -0.916507;-0.400018;0.000881;, - -0.365213;-0.930924;0.000867;, - -0.993070;0.000000;0.117523;, - 0.000000;-0.976748;0.214391;, - -0.515283;-0.506814;0.691102;, - -0.515283;-0.506814;0.691102;, - -0.515283;-0.506814;0.691102;, - -0.523532;0.520184;0.674776;, - -0.523532;0.520184;0.674776;, - -0.523532;0.520184;0.674776;, - -0.993070;0.000000;0.117523;, - 0.000000;0.986719;0.162435;, - 0.000000;-0.626741;0.779227;, - 0.000000;-0.626741;0.779227;, - 0.000000;0.647134;0.762376;, - 0.000000;0.647134;0.762376;, - -0.356851;0.918944;0.167924;, - -0.264643;0.688917;0.674802;, - -0.264643;0.688917;0.674802;, - 0.000000;0.610147;0.792288;, - 0.000000;0.610147;0.792288;, - 0.000000;0.991672;0.128793;, - -0.903541;0.390835;0.175673;, - -0.903541;0.390835;0.175673;, - -0.505675;0.216658;0.835076;, - -0.505675;0.216658;0.835076;, - -0.505675;0.216658;0.835076;, - -0.903543;-0.390832;0.175672;, - -0.903543;-0.390832;0.175672;, - -0.505677;-0.216655;0.835075;, - -0.505677;-0.216655;0.835075;, - -0.505677;-0.216655;0.835075;, - -0.356854;-0.918943;0.167923;, - 0.000000;-0.991672;0.128792;, - 0.000000;-0.610148;0.792287;, - 0.000000;-0.610148;0.792287;, - -0.264647;-0.688916;0.674802;, - -0.264647;-0.688916;0.674802;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.414336;-0.420954;-0.806922;, - 0.414336;-0.420954;-0.806922;, - 0.414336;-0.420954;-0.806922;, - 0.414336;-0.420954;-0.806922;, - 0.410381;0.364278;-0.835996;, - 0.410381;0.364278;-0.835996;, - 0.410381;0.364278;-0.835996;, - 0.410381;0.364278;-0.835996;, - 0.920795;-0.364979;-0.137577;, - 0.920795;-0.364979;-0.137577;, - 0.924846;-0.329505;0.189965;, - 0.924846;-0.329505;0.189965;, - 0.924846;-0.329505;0.189965;, - 0.868862;-0.198793;-0.453388;, - 0.868862;-0.198793;-0.453388;, - 0.374350;-0.888608;-0.265025;, - 0.374350;-0.888608;-0.265025;, - 0.379211;-0.803330;0.459195;, - 0.379211;-0.803330;0.459195;, - 0.379211;-0.803330;0.459195;, - 0.910502;0.394198;0.124877;, - 0.918267;0.364101;-0.155618;, - 0.918267;0.364101;-0.155618;, - 0.852588;-0.139808;0.503534;, - 0.852588;-0.139808;0.503534;, - 0.881298;0.207501;0.424568;, - 0.881298;0.207501;0.424568;, - 0.867287;0.166715;-0.469062;, - 0.867287;0.166715;-0.469062;, - 0.369966;-0.247588;0.895447;, - 0.369966;-0.247588;0.895447;, - 0.413389;0.401187;0.817410;, - 0.413389;0.401187;0.817410;, - 0.413389;0.401187;0.817410;, - 0.413389;0.401187;0.817410;, - 0.345924;0.891018;0.293977;, - 0.345924;0.891018;0.293977;, - 0.363628;0.875934;-0.317041;, - 0.363628;0.875934;-0.317041;, - 0.983435;-0.159487;0.086139;, - 0.000000;0.520825;0.853663;, - 0.000000;0.520825;0.853663;, - 0.000000;0.999161;-0.040963;, - 0.983435;-0.159487;0.086139;, - 0.000000;0.999161;-0.040963;, - 0.000000;0.699533;-0.714601;, - 0.653421;-0.748902;-0.110393;, - 0.653421;-0.748902;-0.110393;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.332036;0.943267;, - 0.000000;-0.332036;0.943267;, - 0.000000;0.098302;0.995157;, - 1.000000;0.000000;0.000000;, - 0.000000;0.990031;-0.140848;, - 0.000000;0.990031;-0.140848;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.098305;-0.995156;, - 0.000000;-0.699991;0.714152;, - 0.000000;-0.098305;-0.995156;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.832489;0.554042;, - 0.000000;-0.832489;0.554042;, - 0.000000;-0.008043;0.999968;, - 1.000000;0.000000;0.000000;, - 0.000000;0.511880;0.859057;, - 1.000000;0.000000;0.000000;, - 0.000000;0.525640;-0.850707;, - 0.000000;-0.987687;0.156440;, - 0.000000;0.525640;-0.850707;, - 1.000000;0.000000;0.000000;, - 0.000000;0.520825;0.853663;, - -0.983434;-0.159485;0.086147;, - 0.000000;0.520825;0.853663;, - 0.000000;0.999161;-0.040963;, - 0.000000;0.999161;-0.040963;, - -0.983434;-0.159485;0.086147;, - -0.653422;-0.748902;-0.110387;, - 0.000000;0.699533;-0.714601;, - -0.653422;-0.748902;-0.110387;, - -0.653422;-0.748902;-0.110387;, - -0.653422;-0.748902;-0.110387;, - 0.000000;0.236676;0.971589;, - 0.000000;0.236676;0.971589;, - 0.653421;-0.748902;-0.110393;, - 0.653421;-0.748902;-0.110393;, - 0.000000;-0.332036;0.943267;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.332036;0.943267;, - 0.000000;0.098302;0.995157;, - 0.000000;0.990031;-0.140848;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.990031;-0.140848;, - 0.000000;-0.098305;-0.995156;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.098305;-0.995156;, - 0.000000;-0.699991;0.714152;, - 0.000000;-0.832489;0.554042;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.832489;0.554042;, - 0.000000;-0.008043;0.999968;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.511880;0.859057;, - 0.000000;0.525640;-0.850707;, - -1.000000;0.000000;0.000000;, - 0.000000;0.525640;-0.850707;, - 0.000000;-0.987687;0.156440;, - 0.152110;-0.074173;-0.985576;, - 0.348514;0.937303;0.000000;, - 0.348514;0.937303;0.000000;, - -0.633860;0.773448;0.000000;, - 0.152110;-0.074173;-0.985576;, - -0.633860;0.773448;0.000000;, - -0.987527;0.157450;0.000000;, - 0.363340;-0.661392;-0.656159;, - 0.363340;-0.661392;-0.656159;, - 0.000000;0.000000;-1.000000;, - 0.956602;0.291397;0.000000;, - 0.956602;0.291397;0.000000;, - 0.731614;0.681719;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.702697;0.711489;0.000000;, - -0.702697;0.711489;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.731621;-0.681712;0.000000;, - 0.987428;-0.158070;0.000000;, - -0.731621;-0.681712;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.937513;-0.347951;0.000000;, - 0.937513;-0.347951;0.000000;, - 0.803579;0.595198;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.353851;0.935302;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.997828;-0.065872;0.000000;, - 0.713241;-0.700918;0.000000;, - -0.997828;-0.065872;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.348514;0.937303;0.000000;, - 0.152109;-0.074175;0.985576;, - 0.348514;0.937303;0.000000;, - -0.633860;0.773448;0.000000;, - -0.633860;0.773448;0.000000;, - 0.152109;-0.074175;0.985576;, - 0.363339;-0.661393;0.656158;, - -0.987527;0.157450;0.000000;, - 0.363339;-0.661393;0.656158;, - 0.363339;-0.661393;0.656158;, - 0.363339;-0.661393;0.656158;, - 0.622827;0.782360;0.000000;, - 0.622827;0.782360;0.000000;, - 0.363340;-0.661392;-0.656159;, - 0.363340;-0.661392;-0.656159;, - 0.956602;0.291397;0.000000;, - 0.000000;0.000000;1.000000;, - 0.956602;0.291397;0.000000;, - 0.731614;0.681719;0.000000;, - -0.702697;0.711489;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -0.702697;0.711489;0.000000;, - -0.731621;-0.681712;0.000000;, - 0.000000;0.000000;1.000000;, - -0.731621;-0.681712;0.000000;, - 0.987428;-0.158070;0.000000;, - 0.937513;-0.347951;0.000000;, - 0.000000;0.000000;1.000000;, - 0.937513;-0.347951;0.000000;, - 0.803579;0.595198;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.353851;0.935302;0.000000;, - -0.997828;-0.065872;0.000000;, - 0.000000;0.000000;1.000000;, - -0.997828;-0.065872;0.000000;, - 0.713241;-0.700918;0.000000;, - 0.163134;-0.084068;-0.983016;, - 0.334945;0.942238;0.000000;, - 0.334945;0.942238;0.000000;, - -0.631267;0.775565;0.000000;, - 0.163134;-0.084068;-0.983016;, - -0.631267;0.775565;0.000000;, - -0.986099;0.166158;0.000000;, - 0.356869;-0.669712;-0.651253;, - 0.356869;-0.669712;-0.651253;, - 0.000000;0.000000;-1.000000;, - 0.953833;0.300339;0.000000;, - 0.953833;0.300339;0.000000;, - 0.712537;0.701634;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.682801;0.730605;0.000000;, - -0.682801;0.730605;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.712526;-0.701646;0.000000;, - 0.985989;-0.166808;0.000000;, - -0.712526;-0.701646;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.933289;-0.359126;0.000000;, - 0.933289;-0.359126;0.000000;, - 0.797086;0.603866;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.337034;0.941492;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.997575;-0.069594;0.000000;, - 0.693605;-0.720355;0.000000;, - -0.997575;-0.069594;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.334945;0.942238;0.000000;, - 0.163134;-0.084064;0.983016;, - 0.334945;0.942238;0.000000;, - -0.631267;0.775565;0.000000;, - -0.631267;0.775565;0.000000;, - 0.163134;-0.084064;0.983016;, - 0.356870;-0.669710;0.651254;, - -0.986099;0.166158;0.000000;, - 0.356870;-0.669710;0.651254;, - 0.356870;-0.669710;0.651254;, - 0.356870;-0.669710;0.651254;, - 0.601679;0.798738;0.000000;, - 0.601679;0.798738;0.000000;, - 0.356869;-0.669712;-0.651253;, - 0.356869;-0.669712;-0.651253;, - 0.953833;0.300339;0.000000;, - 0.000000;0.000000;1.000000;, - 0.953833;0.300339;0.000000;, - 0.712537;0.701634;0.000000;, - -0.682801;0.730605;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -0.682801;0.730605;0.000000;, - -0.712526;-0.701646;0.000000;, - 0.000000;0.000000;1.000000;, - -0.712526;-0.701646;0.000000;, - 0.985989;-0.166808;0.000000;, - 0.933289;-0.359126;0.000000;, - 0.000000;0.000000;1.000000;, - 0.933289;-0.359126;0.000000;, - 0.797086;0.603866;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.337034;0.941492;0.000000;, - -0.997575;-0.069594;0.000000;, - 0.000000;0.000000;1.000000;, - -0.997575;-0.069594;0.000000;, - 0.693605;-0.720355;0.000000;, - 0.152109;-0.074174;-0.985576;, - 0.348514;0.937303;0.000000;, - 0.348514;0.937303;0.000000;, - -0.633860;0.773448;0.000000;, - 0.152109;-0.074174;-0.985576;, - -0.633860;0.773448;0.000000;, - -0.987527;0.157450;0.000000;, - 0.363340;-0.661393;-0.656159;, - 0.363340;-0.661393;-0.656159;, - 0.000000;0.000000;-1.000000;, - 0.956602;0.291397;0.000000;, - 0.956602;0.291397;0.000000;, - 0.731614;0.681719;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.702697;0.711489;0.000000;, - -0.702697;0.711489;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.731621;-0.681712;0.000000;, - 0.987428;-0.158070;0.000000;, - -0.731621;-0.681712;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.937513;-0.347951;0.000000;, - 0.937513;-0.347951;0.000000;, - 0.803579;0.595198;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.353851;0.935302;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.997828;-0.065872;0.000000;, - 0.713241;-0.700918;0.000000;, - -0.997828;-0.065872;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.348514;0.937303;0.000000;, - 0.152109;-0.074173;0.985577;, - 0.348514;0.937303;0.000000;, - -0.633860;0.773448;0.000000;, - -0.633860;0.773448;0.000000;, - 0.152109;-0.074173;0.985577;, - 0.363340;-0.661392;0.656159;, - -0.987527;0.157450;0.000000;, - 0.363340;-0.661392;0.656159;, - 0.363340;-0.661392;0.656159;, - 0.363340;-0.661392;0.656159;, - 0.622827;0.782360;0.000000;, - 0.622827;0.782360;0.000000;, - 0.363340;-0.661393;-0.656159;, - 0.363340;-0.661393;-0.656159;, - 0.956602;0.291397;0.000000;, - 0.000000;0.000000;1.000000;, - 0.956602;0.291397;0.000000;, - 0.731614;0.681719;0.000000;, - -0.702697;0.711489;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -0.702697;0.711489;0.000000;, - -0.731621;-0.681712;0.000000;, - 0.000000;0.000000;1.000000;, - -0.731621;-0.681712;0.000000;, - 0.987428;-0.158070;0.000000;, - 0.937513;-0.347951;0.000000;, - 0.000000;0.000000;1.000000;, - 0.937513;-0.347951;0.000000;, - 0.803579;0.595198;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.353851;0.935302;0.000000;, - -0.997828;-0.065872;0.000000;, - 0.000000;0.000000;1.000000;, - -0.997828;-0.065872;0.000000;, - 0.713241;-0.700918;0.000000;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;0.000000;1.000000;, - 0.000000;0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.000000;1.000000;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.000000;1.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.000000;1.000000;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.225238;0.000000;-0.974304;, - 0.000000;-1.000000;0.000000;, - 0.225238;0.000000;-0.974304;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.225236;-0.000000;-0.974304;, - -0.225236;-0.000000;-0.974304;, - 0.000000;-1.000000;0.000000;, - -0.747100;0.000000;0.664711;, - 0.000000;-1.000000;0.000000;, - -0.747100;0.000000;0.664711;, - -0.747100;0.000000;0.664711;, - 0.000000;1.000000;0.000000;, - -0.747100;0.000000;0.664711;, - -1.000000;-0.000001;-0.000001;, - 0.000000;1.000000;0.000000;, - -1.000000;-0.000001;-0.000001;, - 0.000000;-1.000000;0.000000;, - -0.747099;-0.000001;-0.664712;, - -0.747099;-0.000001;-0.664712;, - 0.000000;-1.000000;0.000000;, - -0.747099;-0.000001;-0.664712;, - -0.747099;-0.000001;-0.664712;, - 0.000000;1.000000;0.000000;, - 0.747100;0.000000;0.664712;, - 0.747100;0.000000;0.664712;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.747100;0.000000;0.664712;, - 0.747100;0.000000;0.664712;, - 0.000000;1.000000;0.000000;, - 0.747100;0.000000;-0.664711;, - 0.000000;-1.000000;0.000000;, - 0.747100;0.000000;-0.664711;, - 0.747100;0.000000;-0.664711;, - 0.000000;1.000000;0.000000;, - 0.747100;0.000000;-0.664711;, - 0.000000;1.000000;0.000000;, - 0.225237;0.000000;0.974304;, - 0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;1.000000;0.000000;, - 0.008295;0.000000;-0.999966;, - -0.739674;0.429301;-0.518250;, - -0.739674;0.429301;-0.518250;, - -0.739674;0.429301;-0.518250;, - 0.003775;0.861001;-0.508589;, - 0.003775;0.861001;-0.508589;, - 0.003775;0.861001;-0.508589;, - -0.739674;-0.429301;-0.518250;, - -0.739674;-0.429301;-0.518250;, - -0.739674;-0.429301;-0.518250;, - 0.003775;-0.861001;-0.508589;, - 0.003775;-0.861001;-0.508589;, - 0.003775;-0.861001;-0.508589;, - 0.751445;-0.431738;-0.498932;, - 0.751445;-0.431738;-0.498932;, - 0.751445;-0.431738;-0.498932;, - 0.751445;0.431738;-0.498932;, - 0.751445;0.431738;-0.498932;, - 0.751445;0.431738;-0.498932;, - -0.003774;0.861001;0.508589;, - -0.003774;0.861001;0.508589;, - -0.003774;0.861001;0.508589;, - -0.751445;0.431738;0.498932;, - -0.751445;0.431738;0.498932;, - -0.751445;0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.003774;-0.861001;0.508589;, - -0.003774;-0.861001;0.508589;, - -0.003774;-0.861001;0.508589;, - 0.739674;-0.429301;0.518250;, - 0.739674;-0.429301;0.518250;, - 0.739674;-0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - -0.008295;0.000000;0.999966;, - 0.008295;0.000000;-0.999966;, - -0.739674;0.429300;-0.518250;, - -0.739674;0.429300;-0.518250;, - -0.739674;0.429300;-0.518250;, - 0.003774;0.861001;-0.508589;, - 0.003774;0.861001;-0.508589;, - 0.003774;0.861001;-0.508589;, - -0.739674;-0.429300;-0.518250;, - -0.739674;-0.429300;-0.518250;, - -0.739674;-0.429300;-0.518250;, - 0.003774;-0.861001;-0.508589;, - 0.003774;-0.861001;-0.508589;, - 0.003774;-0.861001;-0.508589;, - 0.751445;-0.431739;-0.498932;, - 0.751445;-0.431739;-0.498932;, - 0.751445;-0.431739;-0.498932;, - 0.751445;0.431739;-0.498932;, - 0.751445;0.431739;-0.498932;, - 0.751445;0.431739;-0.498932;, - -0.003775;0.861001;0.508589;, - -0.003775;0.861001;0.508589;, - -0.003775;0.861001;0.508589;, - -0.751444;0.431738;0.498932;, - -0.751444;0.431738;0.498932;, - -0.751444;0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.751445;-0.431738;0.498932;, - -0.003775;-0.861001;0.508589;, - -0.003775;-0.861001;0.508589;, - -0.003775;-0.861001;0.508589;, - 0.739674;-0.429301;0.518250;, - 0.739674;-0.429301;0.518250;, - 0.739674;-0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - 0.739674;0.429301;0.518250;, - -0.008294;0.000000;0.999966;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.722410;-0.691465;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.999519;-0.012421;0.028413;, - 0.000000;0.812111;-0.583502;, - 0.000000;1.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-1.000000;0.000000;, - -1.000000;-0.000000;-0.000000;, - -1.000000;0.000000;0.000000;, - 0.320176;0.909831;-0.263999;, - 0.459174;0.888346;0.000000;, - 0.320176;0.909831;0.263999;, - 1.000000;0.000000;0.000000;, - -0.997088;-0.076255;0.000000;, - -0.996327;0.038419;0.076524;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.250841;0.968028;, - 0.000000;0.978200;-0.207665;, - -0.998651;0.051906;-0.001130;, - 0.000000;-0.963715;-0.266933;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.857493;-0.514495;, - 0.000000;0.862416;-0.506201;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.963715;-0.266933;, - 0.000000;0.862416;-0.506201;, - 0.000000;-0.857493;-0.514495;, - 0.000000;-0.963715;-0.266933;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.857493;-0.514495;, - -1.000000;0.000000;0.000000;, - 0.000000;0.862416;-0.506201;, - 0.568003;-0.528656;-0.630789;, - 0.568003;-0.528656;-0.630789;, - 0.631424;-0.350513;-0.691696;, - 0.631424;-0.350513;-0.691696;, - 0.465679;-0.689984;-0.554135;, - 0.465679;-0.689984;-0.554135;, - 0.465679;-0.689984;-0.554135;, - 0.609822;0.175716;-0.772814;, - 0.609822;0.175716;-0.772814;, - 0.609822;0.175716;-0.772814;, - 0.609822;0.175716;-0.772814;, - 0.636200;0.063603;-0.768898;, - 0.636200;0.063603;-0.768898;, - 0.636200;0.063603;-0.768898;, - 0.636200;0.063603;-0.768898;, - 0.923416;-0.078017;-0.375788;, - 0.923416;-0.078017;-0.375788;, - 0.377631;-0.156099;-0.912704;, - 0.377631;-0.156099;-0.912704;, - 0.377631;-0.156099;-0.912704;, - 0.884679;-0.172172;-0.433244;, - 0.884679;-0.172172;-0.433244;, - 0.901160;0.122972;-0.415677;, - 0.901160;0.122972;-0.415677;, - 0.266114;-0.355012;-0.896186;, - 0.266114;-0.355012;-0.896186;, - 0.203413;0.300293;-0.931905;, - 0.214097;0.668101;-0.712603;, - 0.214097;0.668101;-0.712603;, - 0.923596;0.269341;-0.272812;, - 0.490059;0.496470;-0.716492;, - 0.490059;0.496470;-0.716492;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.964991;-0.262282;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.964991;-0.262282;, - -1.000000;0.000000;0.000000;, - 0.000000;0.773957;-0.633238;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-0.897668;-0.440673;, - 0.000000;0.773957;-0.633238;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.964991;-0.262282;, - -1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - -0.001183;-0.449065;-0.893498;, - -0.001183;-0.449065;-0.893498;, - 0.000000;-0.450375;-0.892840;, - 0.000000;-0.450375;-0.892840;, - -1.000000;0.000000;0.000000;, - 0.001183;-0.449065;-0.893498;, - 0.001183;-0.449065;-0.893498;, - 0.783932;-0.598346;0.165629;, - 0.922670;-0.345728;-0.170740;, - 0.382376;-0.569938;0.727296;, - 0.000000;-0.378105;0.925763;, - 0.643705;-0.753560;-0.133384;, - 0.000000;0.000000;1.000000;, - 0.643705;-0.753560;-0.133384;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-0.184987;-0.982741;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.184987;-0.982741;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.659309;-0.751872;0.000000;, - 0.659309;-0.751872;0.000000;, - 0.000000;1.000000;0.000000;, - 0.991432;-0.130624;0.000000;, - 0.456239;0.854986;0.246667;, - 0.456239;0.854986;0.246667;, - 0.456239;0.854986;0.246667;, - 0.405203;0.686558;-0.603696;, - 0.405203;0.686558;-0.603696;, - 0.405203;0.686558;-0.603696;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.071029;-0.568445;-0.819650;, - 0.071029;-0.568445;-0.819650;, - 0.813177;-0.579468;-0.054409;, - 0.813177;-0.579468;-0.054409;, - 0.813177;-0.579468;-0.054409;, - 0.813177;-0.579468;-0.054409;, - 0.608486;-0.622828;-0.491763;, - 0.608486;-0.622828;-0.491763;, - 0.608486;-0.622828;-0.491763;, - 0.165797;-0.985639;-0.032041;, - 0.165797;-0.985639;-0.032041;, - 0.148332;-0.907977;-0.391886;, - 0.148332;-0.907977;-0.391886;, - 0.148332;-0.907977;-0.391886;, - 0.229863;-0.512566;-0.827308;, - 0.549758;-0.282120;-0.786241;, - 0.549758;-0.282120;-0.786241;, - 0.901537;-0.408133;-0.143730;, - 0.901537;-0.408133;-0.143730;, - 0.901537;-0.408133;-0.143730;, - 0.324502;-0.896254;-0.302369;, - 0.324502;-0.896254;-0.302369;, - 0.324502;-0.896254;-0.302369;, - 1.000000;0.000000;0.000000;, - 0.913099;-0.363269;-0.185167;, - 0.913099;-0.363269;-0.185167;, - 1.000000;0.000000;0.000000;, - 0.350617;-0.836690;-0.420734;, - 0.350617;-0.836690;-0.420734;, - 0.350617;-0.836690;-0.420734;, - 0.350617;-0.836690;-0.420734;, - -0.142002;-0.523952;-0.839827;, - -0.142002;-0.523952;-0.839827;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.999568;-0.029404;, - 0.000000;-0.999568;-0.029404;, - -0.477824;-0.715291;-0.509944;, - -0.477824;-0.715291;-0.509944;, - -0.477824;-0.715291;-0.509944;, - -0.477824;-0.715291;-0.509944;, - 0.093017;-0.036036;-0.995012;, - 0.845563;0.464159;-0.263779;, - 0.845563;0.464159;-0.263779;, - 0.845563;0.464159;-0.263779;, - 0.845563;0.464159;-0.263779;, - 0.695672;0.222611;-0.682997;, - 0.695672;0.222611;-0.682997;, - 0.232657;0.873824;-0.426968;, - 0.232657;0.873824;-0.426968;, - 0.194237;0.693443;-0.693836;, - 0.194237;0.693443;-0.693836;, - 0.264427;-0.221960;-0.938516;, - 1.000000;0.000000;0.000000;, - 0.719556;0.465442;-0.515366;, - 0.719556;0.465442;-0.515366;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.839393;0.476139;-0.262127;, - 0.839393;0.476139;-0.262127;, - 0.209199;0.856636;-0.471604;, - 0.924952;0.375115;0.061252;, - 0.682450;0.721378;0.117794;, - -0.152278;-0.112636;-0.981898;, - 0.000000;0.901820;-0.432111;, - -1.000000;0.000000;0.000000;, - 0.000000;0.901820;-0.432111;, - 0.000000;0.746324;-0.665583;, - -0.632618;0.043851;-0.773222;, - -0.839416;-0.217607;-0.498024;, - -0.173513;0.437151;-0.882492;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - 1.000000;0.000000;0.000000;, - 0.000000;0.978200;-0.207665;, - 0.000000;-0.897668;-0.440673;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.978200;-0.207665;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.657933;0.281340;-0.698550;, - 0.000000;-0.987330;-0.158678;, - 0.657933;0.281340;-0.698550;, - 0.000000;0.978200;-0.207665;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.352088;-0.935967;, - 0.000000;-0.987330;-0.158678;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.897668;-0.440673;, - -1.000000;0.000000;0.000000;, - 0.000000;0.978200;-0.207665;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - -0.657933;0.281340;-0.698550;, - 0.000000;-0.987330;-0.158678;, - -0.657933;0.281340;-0.698550;, - 0.000000;-0.371391;-0.928477;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.919145;-0.393919;, - 0.704085;-0.354065;-0.615550;, - 0.704085;-0.354065;-0.615550;, - 0.704085;-0.354065;-0.615550;, - 0.000000;-0.481363;-0.876521;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.481363;-0.876521;, - 0.000000;-0.371391;-0.928477;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.919145;-0.393919;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.371391;-0.928477;, - 0.000000;-0.919145;-0.393919;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.919145;-0.393919;, - 0.000000;-0.481363;-0.876521;, - 0.000000;-0.481363;-0.876521;, - 1.000000;0.000000;0.000000;, - -0.704085;-0.354065;-0.615550;, - -0.704085;-0.354065;-0.615550;, - -0.704085;-0.354065;-0.615550;, - 0.000000;0.404553;-0.914514;, - 0.765120;0.576310;-0.287155;, - 0.345860;0.589303;-0.730139;, - 0.946660;0.322234;0.000000;, - 0.946660;0.322234;0.000000;, - 0.946660;0.322234;0.000000;, - 0.671803;0.000000;-0.740730;, - 0.000000;1.000000;0.000000;, - 0.671803;0.000000;-0.740730;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.262974;-0.511171;-0.818259;, - 0.262974;-0.511171;-0.818259;, - 0.262974;0.511173;-0.818258;, - 0.262974;0.511173;-0.818258;, - 0.000000;0.618986;-0.785402;, - 0.000000;0.618986;-0.785402;, - -0.815811;0.578319;0.000000;, - 0.815811;0.578319;0.000000;, - 0.000000;0.508835;-0.860864;, - 0.000000;0.508835;-0.860864;, - 0.000000;-0.508833;-0.860865;, - 0.000000;-0.508833;-0.860865;, - 0.000000;0.404553;-0.914514;, - -0.946660;0.322234;0.000000;, - -0.765120;0.576310;-0.287155;, - -0.345860;0.589303;-0.730139;, - -0.946660;0.322234;0.000000;, - -0.946660;0.322234;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - -0.262974;-0.511171;-0.818259;, - -0.262974;-0.511171;-0.818259;, - -0.262974;0.511173;-0.818258;, - -0.262974;0.511173;-0.818258;, - -0.671803;0.000000;-0.740730;, - -0.671803;0.000000;-0.740730;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - -0.002643;-0.988024;-0.154279;, - -0.002643;-0.988024;-0.154279;, - 0.000000;-0.196037;-0.980597;, - 0.992902;-0.118932;0.000000;, - 0.308346;0.914546;-0.261780;, - 0.308346;0.914546;-0.261780;, - 0.441536;0.897244;0.000000;, - 0.441536;0.897244;0.000000;, - 0.308346;0.914546;0.261780;, - 0.308346;0.914546;0.261780;, - 0.000000;-0.946157;-0.323708;, - 0.000000;-0.946157;-0.323708;, - 0.000000;-0.196037;-0.980597;, - -0.996514;-0.083420;0.000000;, - -0.320176;0.909831;-0.263999;, - -0.459174;0.888346;0.000000;, - -0.320176;0.909831;0.263999;, - -1.000000;0.000000;0.000000;, - 0.002643;-0.988024;-0.154279;, - 0.002643;-0.988024;-0.154279;, - -0.308346;0.914546;-0.261780;, - -0.308346;0.914546;-0.261780;, - -0.441536;0.897244;0.000000;, - -0.441536;0.897244;0.000000;, - -0.308346;0.914546;0.261780;, - -0.308346;0.914546;0.261780;, - 0.812034;-0.553973;0.183615;, - 0.946603;-0.281034;-0.157994;, - 0.000000;-0.378105;0.925763;, - 0.382376;-0.569938;0.727296;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.710283;-0.703916;, - 1.000000;0.000000;0.000000;, - 0.000000;0.946563;-0.322518;, - 0.000000;0.946563;-0.322518;, - 1.000000;0.000000;0.000000;, - 0.000000;0.555569;-0.831470;, - 0.000000;0.764153;-0.645035;, - 0.000000;0.764153;-0.645035;, - 0.000000;0.710283;-0.703916;, - 0.000000;0.555569;-0.831470;, - -1.000000;0.000000;0.000000;, - 0.000000;0.710283;-0.703916;, - -1.000000;0.000000;0.000000;, - 0.000000;0.946563;-0.322518;, - 0.000000;0.946563;-0.322518;, - -1.000000;0.000000;0.000000;, - 0.000000;0.555569;-0.831470;, - 0.542285;0.325571;-0.774552;, - 0.000000;-1.000000;0.000000;, - 0.542285;0.325571;-0.774552;, - 0.573119;0.023866;-0.819124;, - 0.573119;0.023866;-0.819124;, - 0.961193;0.164049;-0.221802;, - 0.961193;0.164049;-0.221802;, - 0.000000;0.216852;0.976204;, - 0.980187;0.000000;-0.198074;, - 0.980187;0.000000;-0.198074;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.928011;-0.372552;, - 0.915407;-0.402528;0.001330;, - 0.915407;-0.402528;0.001330;, - 0.362628;-0.931929;0.003080;, - 0.362628;-0.931929;0.003080;, - 0.932383;0.105681;0.345678;, - 0.932383;0.105681;0.345678;, - 0.939177;-0.277805;0.201919;, - 0.939177;-0.277805;0.201919;, - 0.939177;-0.277805;0.201919;, - 0.423043;-0.726679;0.541270;, - 0.423043;-0.726679;0.541270;, - 0.510845;0.042579;0.858618;, - 0.510845;0.042579;0.858618;, - 0.297759;0.272112;0.915038;, - 0.297759;0.272112;0.915038;, - 0.886619;0.124974;0.445295;, - 0.886619;0.124974;0.445295;, - 0.886619;0.124974;0.445295;, - 0.229087;0.702960;0.673325;, - 0.229087;0.702960;0.673325;, - 0.864236;0.368497;0.342501;, - 0.864236;0.368497;0.342501;, - 0.713439;0.698664;-0.053601;, - 0.713439;0.698664;-0.053601;, - 0.204500;0.976588;-0.066752;, - 0.987857;-0.005063;-0.155282;, - 0.987857;-0.005063;-0.155282;, - 0.582078;-0.000864;-0.813132;, - 0.582078;-0.000864;-0.813132;, - 0.582078;-0.000864;-0.813132;, - 0.582078;-0.000864;-0.813132;, - 0.581799;-0.016819;-0.813159;, - 0.581799;-0.016819;-0.813159;, - 0.581799;-0.016819;-0.813159;, - 0.581799;-0.016819;-0.813159;, - 0.987819;-0.010866;-0.155226;, - 0.987819;-0.010866;-0.155226;, - -0.113771;0.245370;-0.962730;, - -0.113771;0.245370;-0.962730;, - 0.171571;0.921590;-0.348189;, - 0.520068;0.319591;-0.792081;, - 0.520068;0.319591;-0.792081;, - 0.520068;0.319591;-0.792081;, - 0.800913;0.509642;-0.314332;, - 0.800913;0.509642;-0.314332;, - 0.153552;-0.920031;-0.360507;, - -0.118314;-0.167948;-0.978670;, - -0.118314;-0.167948;-0.978670;, - 0.787478;-0.534510;-0.306884;, - 0.787478;-0.534510;-0.306884;, - 0.491605;-0.323829;-0.808368;, - 0.491605;-0.323829;-0.808368;, - 0.491605;-0.323829;-0.808368;, - -0.379424;-0.028718;-0.924777;, - -0.379424;-0.028718;-0.924777;, - -0.261457;-0.285374;-0.922064;, - -0.376619;0.054435;-0.924768;, - -0.376619;0.054435;-0.924768;, - -0.386721;-0.025977;-0.921831;, - -0.386721;-0.025977;-0.921831;, - -0.386721;-0.025977;-0.921831;, - -0.383931;0.053652;-0.921802;, - -0.383931;0.053652;-0.921802;, - -0.383931;0.053652;-0.921802;, - -0.254652;0.321336;-0.912083;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.250841;0.968028;, - 1.000000;0.000000;0.000000;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.861871;0.507128;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.250841;0.968028;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.250841;0.968028;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.250841;0.968028;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.861871;0.507128;, - 0.000000;-0.861871;0.507128;, - 0.000000;0.606555;0.795041;, - 0.000000;0.606555;0.795041;, - 0.997088;-0.076255;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.703016;-0.711174;0.000000;, - 0.703016;-0.711174;0.000000;, - 0.703016;-0.711174;0.000000;, - -1.000000;0.000000;0.000000;, - 0.688808;0.146582;-0.709970;, - 0.688808;0.146582;-0.709970;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.178932;-0.983862;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.688808;0.146582;-0.709970;, - -0.688808;0.146582;-0.709970;, - -0.703016;-0.711174;0.000000;, - -0.703016;-0.711174;0.000000;, - -0.703016;-0.711174;0.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.673085;0.543157;-0.501933;, - 0.673085;0.543157;-0.501933;, - 0.673085;0.543157;-0.501933;, - 0.681821;-0.000000;-0.731519;, - 0.681821;-0.000000;-0.731519;, - 0.673085;-0.543157;-0.501933;, - 0.673085;-0.543157;-0.501933;, - 0.673085;-0.543157;-0.501933;, - 0.665741;-0.746183;0.000000;, - 0.665741;-0.746183;0.000000;, - 1.000000;-0.000000;-0.000000;, - 0.297521;-0.752416;-0.587666;, - 0.297521;-0.752416;-0.587666;, - 0.297521;-0.752416;-0.587666;, - 0.946660;0.322234;0.000000;, - 0.000000;0.404553;0.914514;, - 0.765120;0.576310;0.287155;, - 0.345860;0.589303;0.730139;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.961703;0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - 0.961703;0.274094;0.000000;, - 0.408026;0.782721;-0.469960;, - 0.408026;0.782721;-0.469960;, - 0.408026;0.782721;-0.469960;, - 0.961703;-0.274094;0.000000;, - 0.961703;-0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;-0.000000;, - 0.408026;-0.782720;-0.469961;, - 0.408026;-0.782720;-0.469961;, - 0.408026;-0.782720;-0.469961;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-0.734960;-0.678111;, - 0.709688;-0.575075;-0.406979;, - 0.709688;-0.575075;-0.406979;, - 0.709688;-0.575075;-0.406979;, - 0.812989;-0.582279;0.000000;, - 0.812989;-0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - 0.812989;0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - 0.812989;0.582279;0.000000;, - 0.709688;0.575076;-0.406978;, - 0.709688;0.575076;-0.406978;, - 0.709688;0.575076;-0.406978;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - -0.525821;-0.675119;-0.517422;, - -0.525821;-0.675119;-0.517422;, - -0.525821;-0.675119;-0.517422;, - 0.000000;0.618986;0.785402;, - 0.000000;0.618986;0.785402;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.682437;-0.730944;, - 0.000000;0.682437;-0.730944;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-1.000000;-0.000000;, - 0.000000;-0.682436;-0.730946;, - 0.000000;-0.682436;-0.730946;, - -0.673085;0.543157;-0.501933;, - -0.673085;0.543157;-0.501933;, - -0.673085;0.543157;-0.501933;, - -0.681820;-0.000000;-0.731520;, - -0.681820;-0.000000;-0.731520;, - -0.673085;-0.543157;-0.501933;, - -0.673085;-0.543157;-0.501933;, - -0.673085;-0.543157;-0.501933;, - -0.665741;-0.746183;0.000000;, - -0.665741;-0.746183;0.000000;, - -0.946660;0.322234;0.000000;, - 0.000000;0.404553;0.914514;, - -0.345860;0.589303;0.730139;, - -0.765120;0.576310;0.287155;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - -0.961703;0.274094;0.000000;, - -0.961703;0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - -0.408026;0.782721;-0.469960;, - -0.408026;0.782721;-0.469960;, - -0.408026;0.782721;-0.469960;, - -0.961703;-0.274094;0.000000;, - 0.000000;0.000000;1.000000;, - -0.961703;-0.274094;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;-0.000000;, - -0.408026;-0.782720;-0.469961;, - -0.408026;-0.782720;-0.469961;, - -0.408026;-0.782720;-0.469961;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.734960;-0.678111;, - 0.000000;-0.734960;-0.678111;, - -0.709688;-0.575075;-0.406979;, - -0.709688;-0.575075;-0.406979;, - -0.709688;-0.575075;-0.406979;, - -0.812989;-0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - -0.812989;-0.582279;0.000000;, - -0.812989;0.582279;0.000000;, - 0.000000;0.000000;1.000000;, - -0.812989;0.582279;0.000000;, - -0.709688;0.575076;-0.406978;, - -0.709688;0.575076;-0.406978;, - -0.709688;0.575076;-0.406978;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.665741;0.746183;0.000000;, - 0.665741;0.746183;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;-0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.734960;-0.678111;, - 0.000000;0.734960;-0.678111;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;-0.000000;, - 0.000000;0.734960;-0.678111;, - 0.000000;0.734960;-0.678111;, - -0.665741;0.746183;0.000000;, - -0.665741;0.746183;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;-0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.734960;-0.678111;, - 0.000000;0.734960;-0.678111;, - 0.000000;-1.000000;0.000000;, - -0.006548;0.000000;-0.999979;, - -0.999860;0.000000;0.016754;, - -0.006548;0.000000;-0.999979;, - 0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.974062;0.193186;-0.117820;, - 0.990365;0.035316;-0.133904;, - 1.000000;0.000000;0.000000;, - 0.067354;-0.443547;0.893716;, - 0.067354;-0.443547;0.893716;, - 0.817977;-0.560175;0.130831;, - 0.817977;-0.560175;0.130831;, - 0.817977;-0.560175;0.130831;, - 0.143343;-0.948306;0.283140;, - 0.575371;-0.360864;0.733979;, - 0.575371;-0.360864;0.733979;, - 0.575371;-0.360864;0.733979;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.237889;-0.660874;-0.711797;, - 0.237889;-0.660874;-0.711797;, - 0.225248;-0.235329;-0.945454;, - 0.694911;-0.059586;-0.716623;, - 0.694911;-0.059586;-0.716623;, - 0.724776;-0.636464;-0.263843;, - 0.724776;-0.636464;-0.263843;, - 0.724776;-0.636464;-0.263843;, - 0.724776;-0.636464;-0.263843;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.981599;-0.122465;-0.146514;, - 0.921060;-0.243934;0.303554;, - 0.921060;-0.243934;0.303554;, - 0.921060;-0.243934;0.303554;, - 0.591008;-0.180066;0.786312;, - 0.590930;-0.729027;0.345429;, - 0.339709;0.184859;0.922185;, - 0.356763;-0.934190;0.003088;, - 0.000000;-0.447847;0.894110;, - 0.000000;-0.447847;0.894110;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.957775;0.287517;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.724776;-0.636464;-0.263843;, - -0.724776;-0.636464;-0.263843;, - -0.724776;-0.636464;-0.263843;, - -0.724776;-0.636464;-0.263843;, - -0.694911;-0.059586;-0.716623;, - -0.694911;-0.059586;-0.716623;, - -0.225248;-0.235329;-0.945454;, - -0.237889;-0.660874;-0.711797;, - -0.237889;-0.660874;-0.711797;, - 0.306622;-0.892935;-0.329622;, - 0.306622;-0.892935;-0.329622;, - 0.306622;-0.892935;-0.329622;, - 0.767964;-0.531687;-0.357126;, - 0.938714;-0.344697;0.000000;, - 0.328658;-0.526006;-0.784412;, - -0.000000;-0.300372;-0.953822;, - 0.328661;0.526000;-0.784415;, - 0.938716;0.344692;0.000000;, - -0.000000;0.300367;-0.953824;, - 0.767968;0.531681;-0.357129;, - 0.306626;0.892932;-0.329625;, - 0.306626;0.892932;-0.329625;, - 0.306626;0.892932;-0.329625;, - 0.901160;-0.433486;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.887308;-0.461177;0.000000;, - 0.000000;1.000000;0.000000;, - -0.198966;0.000000;-0.980006;, - 0.000000;-1.000000;0.000000;, - -0.198966;0.000000;-0.980006;, - 0.505754;-0.862678;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.505754;-0.862678;0.000000;, - -0.198966;0.000000;-0.980006;, - -0.334945;0.942238;0.000000;, - -0.163134;-0.084068;-0.983016;, - -0.334945;0.942238;0.000000;, - 0.631267;0.775565;0.000000;, - 0.631267;0.775565;0.000000;, - -0.163134;-0.084068;-0.983016;, - 0.986099;0.166158;0.000000;, - -0.356869;-0.669712;-0.651253;, - -0.356869;-0.669712;-0.651253;, - -0.953833;0.300339;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.953833;0.300339;0.000000;, - -0.712537;0.701634;0.000000;, - 0.682801;0.730605;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.682801;0.730605;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.712526;-0.701646;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.985989;-0.166808;0.000000;, - 0.712526;-0.701646;0.000000;, - -0.933289;-0.359126;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.933289;-0.359126;0.000000;, - -0.797086;0.603866;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.337034;0.941492;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.997575;-0.069594;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.693605;-0.720355;0.000000;, - 0.997575;-0.069594;0.000000;, - -0.000000;-0.300371;-0.953822;, - -0.000000;-0.300371;-0.953822;, - -0.000000;-0.886849;-0.462059;, - -0.000000;-0.886849;-0.462059;, - -0.000000;0.300367;-0.953824;, - -0.000000;0.300367;-0.953824;, - 0.000000;0.886847;-0.462064;, - 0.000000;0.886847;-0.462064;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - 0.007275;0.000000;-0.999974;, - 0.000000;-1.000000;0.000000;, - 0.007275;0.000000;-0.999974;, - 0.999860;0.000000;-0.016753;, - -0.006063;-0.377782;-0.925875;, - -0.999860;0.000000;0.016754;, - -0.006063;-0.377782;-0.925875;, - 0.999860;0.000001;-0.016752;, - -0.006063;-0.377782;-0.925875;, - -0.999860;0.000000;0.016754;, - -0.006063;-0.377782;-0.925875;, - 0.999860;0.000001;-0.016753;, - -0.999860;0.000000;0.016754;, - 0.999860;0.000001;-0.016753;, - -0.845995;-0.382332;-0.371638;, - -0.845995;-0.382332;-0.371638;, - -0.845995;-0.382332;-0.371638;, - -0.845995;-0.382332;-0.371638;, - -0.128250;-0.917776;-0.375819;, - -0.128250;-0.917776;-0.375819;, - -0.315649;-0.364073;-0.876251;, - -0.315649;-0.364073;-0.876251;, - -0.000000;-0.886848;-0.462062;, - -0.000000;-0.886848;-0.462062;, - -0.000000;-0.929961;-0.367658;, - -0.000000;-0.300370;-0.953823;, - -0.000000;-0.300370;-0.953823;, - -0.000000;-0.300369;-0.953823;, - -0.000000;-0.300369;-0.953823;, - -0.845995;0.382332;-0.371638;, - -0.845995;0.382332;-0.371638;, - -0.845995;0.382332;-0.371638;, - -0.845995;0.382332;-0.371638;, - -0.315649;0.364073;-0.876251;, - -0.315649;0.364073;-0.876251;, - -0.128250;0.917776;-0.375819;, - -0.128250;0.917776;-0.375819;, - -0.000000;0.886848;-0.462062;, - -0.000000;0.886848;-0.462062;, - -0.000000;0.300369;-0.953823;, - -0.000000;0.300369;-0.953823;, - -0.000000;0.300368;-0.953823;, - -0.000000;0.300368;-0.953823;, - 0.000000;0.929961;-0.367659;, - 0.000000;1.000000;0.000000;, - -0.009877;0.000000;-0.999951;, - 0.000000;-1.000000;0.000000;, - -0.009877;0.000000;-0.999951;, - -0.999860;0.000000;0.016753;, - 0.007275;0.000000;-0.999974;, - 0.000000;-1.000000;0.000000;, - -0.999860;0.000000;0.016753;, - 0.000000;1.000000;0.000000;, - 0.007275;0.000000;-0.999974;, - 0.000000;-1.000000;0.000000;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - 0.000000;1.000000;0.000000;, - 0.444792;0.000000;-0.895634;, - 0.444792;0.000000;-0.895634;, - -0.225238;0.000000;-0.974304;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.225238;0.000000;-0.974304;, - 0.225236;-0.000001;-0.974304;, - 0.000000;1.000000;0.000000;, - 0.225236;-0.000001;-0.974304;, - 0.000000;-1.000000;0.000000;, - 0.952657;0.000000;-0.304046;, - 0.952657;0.000000;-0.304046;, - 1.000000;0.000000;-0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.897253;-0.281640;-0.340023;, - 0.897253;-0.281640;-0.340023;, - 0.943629;-0.331006;0.000000;, - 0.000000;0.000000;1.000000;, - 0.428060;-0.799374;-0.421624;, - 0.428060;-0.799374;-0.421624;, - 0.428060;-0.799374;-0.421624;, - 0.428060;-0.799374;-0.421624;, - 0.433190;-0.901303;0.000000;, - 0.000000;-0.000000;1.000000;, - 0.433190;-0.901303;0.000000;, - 0.410415;-0.110414;-0.905190;, - 0.410415;-0.110414;-0.905190;, - 0.000000;-0.000000;1.000000;, - 0.458637;0.000000;-0.888624;, - 0.458637;0.000000;-0.888624;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - -0.999835;0.000000;-0.018151;, - -0.009877;0.000000;-0.999951;, - 0.000000;-1.000000;0.000000;, - -0.999835;0.000000;-0.018151;, - 0.000000;1.000000;0.000000;, - -0.009877;0.000000;-0.999951;, - -0.008295;0.000000;-0.999966;, - 0.739674;0.429300;-0.518250;, - 0.739674;0.429300;-0.518250;, - 0.739674;0.429300;-0.518250;, - -0.003774;0.861001;-0.508589;, - -0.003774;0.861001;-0.508589;, - -0.003774;0.861001;-0.508589;, - 0.739674;-0.429300;-0.518250;, - 0.739674;-0.429300;-0.518250;, - 0.739674;-0.429300;-0.518250;, - -0.003774;-0.861001;-0.508589;, - -0.003774;-0.861001;-0.508589;, - -0.003774;-0.861001;-0.508589;, - -0.751445;-0.431739;-0.498932;, - -0.751445;-0.431739;-0.498932;, - -0.751445;-0.431739;-0.498932;, - -0.751445;0.431739;-0.498932;, - -0.751445;0.431739;-0.498932;, - -0.751445;0.431739;-0.498932;, - 0.000000;-1.000000;0.000000;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - 0.000000;1.000000;0.000000;, - -0.444792;0.000000;-0.895634;, - -0.444792;0.000000;-0.895634;, - -0.492699;-0.870200;0.000000;, - 0.000000;-0.000000;1.000000;, - -0.418146;-0.801329;-0.427815;, - -0.418146;-0.801329;-0.427815;, - -0.418146;-0.801329;-0.427815;, - -0.421913;-0.784056;-0.455242;, - -0.421913;-0.784056;-0.455242;, - -0.421913;-0.784056;-0.455242;, - -0.492699;-0.870200;0.000000;, - 0.000000;-0.000000;1.000000;, - -0.492699;-0.870200;0.000000;, - -0.000000;-0.000000;-1.000000;, - -0.115463;-0.249286;-0.961522;, - -0.115463;-0.249286;-0.961522;, - 0.000000;0.000000;1.000000;, - -0.100988;-0.994888;0.000000;, - -0.000000;-0.000000;-1.000000;, - 0.179157;-0.288632;-0.940529;, - 0.179157;-0.288632;-0.940529;, - -0.191831;-0.385043;-0.902742;, - -0.000000;-0.000000;-1.000000;, - -0.292367;-0.866429;-0.404750;, - -0.292367;-0.866429;-0.404750;, - -0.292367;-0.866429;-0.404750;, - -0.331004;-0.943629;0.000000;, - 0.000000;0.000000;1.000000;, - -0.830569;-0.387539;-0.399961;, - -0.830569;-0.387539;-0.399961;, - -0.830569;-0.387539;-0.399961;, - -0.830569;-0.387539;-0.399961;, - -0.901302;-0.433191;0.000000;, - -0.901302;-0.433191;0.000000;, - 0.000000;0.000000;1.000000;, - -0.000000;0.000000;-1.000000;, - -0.109902;-0.344862;-0.932197;, - -0.109902;-0.344862;-0.932197;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.945889;0.000000;-0.324489;, - -0.945889;0.000000;-0.324489;, - -0.439396;0.000000;-0.898293;, - -0.439396;0.000000;-0.898293;, - -0.442680;-0.198092;-0.874525;, - -0.442680;-0.198092;-0.874525;, - 0.000000;0.000000;1.000000;, - -0.100988;-0.994888;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.222802;0.267250;-0.937516;, - 0.694990;0.067591;-0.715836;, - 0.694990;0.067591;-0.715836;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.182865;0.983138;0.000000;, - 0.841860;0.510164;-0.176079;, - 0.841860;0.510164;-0.176079;, - 0.841860;0.510164;-0.176079;, - 0.212237;0.942309;-0.258861;, - 0.824489;0.565879;0.000000;, - 0.824489;0.565879;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.694990;0.067591;-0.715836;, - -0.694990;0.067591;-0.715836;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - -0.222803;0.267250;-0.937516;, - 0.643961;0.458788;-0.612232;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.965546;-0.260232;, - -1.000000;0.000000;0.000000;, - 0.000000;0.951870;-0.306503;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;0.016754;, - -0.006548;0.000000;-0.999979;, - 0.000000;1.000000;0.000000;, - -0.006548;0.000000;-0.999979;, - 0.999860;0.000000;-0.016752;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - -0.999860;0.000000;0.016754;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;0.016754;, - 0.006548;0.000000;0.999979;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - 0.006548;0.000000;0.999979;, - -0.006548;0.000000;-0.999979;, - 0.999860;0.000000;-0.016752;, - -0.006548;0.000000;-0.999979;, - -0.999860;0.000000;0.016754;, - -0.999860;0.000000;0.016754;, - -0.006548;0.000000;-0.999979;, - -0.999860;0.000000;0.016754;, - 0.006548;0.000000;0.999979;, - 0.000000;-1.000000;0.000000;, - 0.006548;0.000000;0.999979;, - 0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - -0.006548;0.000000;-0.999979;, - 0.999860;0.000000;-0.016752;, - 0.894428;0.447212;-0.000000;, - 0.894428;0.447212;-0.000000;, - 0.831040;0.403243;-0.383102;, - 0.831040;0.403243;-0.383102;, - 0.831040;0.403243;-0.383102;, - 0.831040;0.403243;-0.383102;, - 0.316229;0.948683;-0.000000;, - 0.282244;0.875709;-0.391756;, - 0.282244;0.875709;-0.391756;, - 0.282244;0.875709;-0.391756;, - 0.457151;0.212943;-0.863521;, - 0.457151;0.212943;-0.863521;, - -0.000000;0.933082;-0.359664;, - -0.000000;0.933082;-0.359664;, - 0.000000;1.000000;0.000000;, - -0.000000;0.405468;-0.914109;, - -0.000000;0.405468;-0.914109;, - 0.109882;0.357779;-0.927319;, - 0.109882;0.357779;-0.927319;, - -0.349235;0.855784;-0.381665;, - -0.349235;0.855784;-0.381665;, - -0.349235;0.855784;-0.381665;, - -0.349235;0.855784;-0.381665;, - -0.382684;0.923879;0.000000;, - -0.382684;0.923879;0.000000;, - -0.923880;0.382683;0.000000;, - -0.859819;0.357289;-0.364767;, - -0.859819;0.357289;-0.364767;, - -0.859819;0.357289;-0.364767;, - -0.142369;0.355966;-0.923590;, - -0.142369;0.355966;-0.923590;, - -0.486422;0.202974;-0.849820;, - -0.486422;0.202974;-0.849820;, - 0.231732;0.696563;-0.679043;, - 0.231732;0.696563;-0.679043;, - 0.718710;0.648693;-0.250309;, - 0.718710;0.648693;-0.250309;, - 0.718710;0.648693;-0.250309;, - 0.718710;0.648693;-0.250309;, - -0.718710;0.648692;-0.250309;, - -0.718710;0.648692;-0.250309;, - -0.718710;0.648692;-0.250309;, - -0.718710;0.648692;-0.250309;, - -0.231732;0.696563;-0.679043;, - -0.231732;0.696563;-0.679043;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.220606;-0.975363;, - 0.000000;0.781219;-0.624257;, - 1.000000;0.000000;0.000000;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.781219;-0.624257;, - 0.000000;0.220606;-0.975363;, - 0.000000;-1.000000;0.000000;, - 0.999563;0.015174;-0.025377;, - 0.999563;0.015174;-0.025377;, - 0.999715;0.000062;-0.023881;, - 0.999715;0.000062;-0.023881;, - 0.999670;0.005731;-0.025038;, - 0.999670;0.005731;-0.025038;, - 0.999698;0.006980;-0.023542;, - 0.999698;0.006980;-0.023542;, - 0.186111;0.981867;-0.036054;, - 0.817235;0.575047;-0.038051;, - 0.817235;0.575047;-0.038051;, - 0.821447;0.564406;-0.081677;, - 0.821447;0.564406;-0.081677;, - 0.185128;0.976271;-0.112354;, - 0.817690;-0.575000;-0.027537;, - 0.817690;-0.575000;-0.027537;, - 0.164892;-0.986122;-0.019346;, - 0.164920;-0.986307;0.000000;, - 0.813788;-0.580936;-0.016218;, - 0.813788;-0.580936;-0.016218;, - -0.417231;-0.749047;-0.514632;, - -0.417231;-0.749047;-0.514632;, - 0.901271;0.000000;-0.433257;, - 0.266525;-0.707134;-0.654925;, - 0.697396;-0.282082;-0.658839;, - 0.000000;-0.910249;-0.414061;, - -0.417231;0.749047;-0.514632;, - -0.417231;0.749047;-0.514632;, - 0.000000;0.910249;-0.414061;, - 0.266525;0.707134;-0.654925;, - 0.697396;0.282082;-0.658839;, - 0.901271;0.000000;-0.433257;, - -0.381399;-0.271517;-0.883636;, - 0.232012;-0.244096;-0.941588;, - 0.232012;0.244096;-0.941588;, - -0.381399;0.271517;-0.883636;, - 0.491030;-0.830349;-0.263459;, - 0.491030;-0.830349;-0.263459;, - 0.783289;0.222369;-0.580526;, - 0.000000;0.960955;-0.276705;, - 0.950288;-0.070780;-0.303222;, - 0.272426;0.849198;-0.452379;, - 0.326957;0.115768;-0.937921;, - 0.326957;0.115768;-0.937921;, - 0.326957;0.115768;-0.937921;, - 0.327272;-0.520278;-0.788799;, - 0.327272;-0.520278;-0.788799;, - 0.327272;-0.520278;-0.788799;, - 0.000000;-0.818404;-0.574643;, - 0.999257;0.038532;0.001036;, - 0.000000;0.317049;-0.948409;, - 0.999257;0.038532;0.001036;, - 0.000000;0.317049;-0.948409;, - 0.000000;-1.000000;0.000000;, - 0.996327;0.038419;0.076524;, - 0.511973;0.849126;0.129878;, - 0.996327;0.038420;0.076524;, - 0.863785;0.365054;0.347291;, - 0.000000;0.998092;0.061747;, - 0.996327;0.038419;0.076524;, - 0.994571;0.104035;-0.002266;, - 0.000000;-0.995327;0.096563;, - 0.000000;0.317049;-0.948409;, - 0.000000;0.317049;-0.948409;, - 0.000000;-0.818404;-0.574643;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.998092;0.061747;, - 0.000000;-0.995327;0.096563;, - 0.000000;-0.818404;-0.574643;, - -0.999257;0.038532;0.001036;, - -0.999257;0.038532;0.001036;, - 0.000000;0.317049;-0.948409;, - 0.000000;0.317049;-0.948409;, - 0.000000;-1.000000;0.000000;, - -0.996327;0.038419;0.076524;, - -0.511973;0.849126;0.129878;, - -0.996327;0.038420;0.076524;, - -0.863785;0.365054;0.347291;, - 0.000000;0.998092;0.061747;, - -0.994571;0.104035;-0.002266;, - 0.000000;-0.995327;0.096563;, - 0.998651;0.051906;-0.001130;, - 0.673085;0.543157;0.501933;, - 0.673085;0.543157;0.501933;, - 0.673085;0.543157;0.501933;, - 0.681821;-0.000000;0.731519;, - 0.681821;-0.000000;0.731519;, - 0.673085;-0.543157;0.501933;, - 0.673085;-0.543157;0.501933;, - 0.673085;-0.543157;0.501933;, - 0.599172;-0.557346;0.574768;, - 0.599172;-0.557346;0.574768;, - 0.599172;-0.557346;0.574768;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.215555;0.976492;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.734960;0.678111;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.000000;1.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - -0.601258;-0.745604;0.287339;, - -0.601258;-0.745604;0.287339;, - -0.601258;-0.745604;0.287339;, - 0.000000;1.000000;0.000000;, - 0.000000;0.215555;0.976492;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.215556;0.976492;, - -0.673085;0.543157;0.501933;, - -0.673085;0.543157;0.501933;, - -0.673085;0.543157;0.501933;, - -0.681820;-0.000000;0.731520;, - -0.681820;-0.000000;0.731520;, - -0.673085;-0.543157;0.501933;, - -0.673085;-0.543157;0.501933;, - -0.673085;-0.543157;0.501933;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.215555;0.976492;, - -1.000000;0.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.734960;0.678111;, - 0.000000;-0.734960;0.678111;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.215556;0.976492;, - 0.000000;-0.215556;0.976492;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.999984;0.005657;, - 1.000000;0.000000;0.000000;, - 0.000000;0.734960;0.678111;, - 0.000000;0.734960;0.678111;, - 0.000000;-0.999941;0.010885;, - 0.000000;0.734960;0.678111;, - 0.000000;0.734960;0.678111;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.999984;0.005657;, - -1.000000;0.000000;0.000000;, - 0.000000;0.734960;0.678111;, - 0.000000;0.734960;0.678111;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.877728;-0.330691;0.346751;, - 0.877728;-0.330691;0.346751;, - 0.877728;-0.330691;0.346751;, - 0.877728;-0.330691;0.346751;, - 0.395322;-0.904274;0.161270;, - 0.395322;-0.904274;0.161270;, - 0.395322;-0.904274;0.161270;, - 0.420034;-0.907509;0.000000;, - 0.420034;-0.907509;0.000000;, - 0.420034;-0.907509;0.000000;, - 0.938714;-0.344697;0.000000;, - 0.938714;-0.344697;0.000000;, - 0.938714;-0.344697;0.000000;, - 0.938714;-0.344697;0.000000;, - 0.877730;0.330686;0.346752;, - 0.877730;0.330686;0.346752;, - 0.877730;0.330686;0.346752;, - 0.877730;0.330686;0.346752;, - 0.395326;0.904272;0.161272;, - 0.395326;0.904272;0.161272;, - 0.395326;0.904272;0.161272;, - 0.420038;0.907506;0.000000;, - 0.420038;0.907506;0.000000;, - 0.420038;0.907506;0.000000;, - 0.938716;0.344692;0.000000;, - 0.938716;0.344692;0.000000;, - 0.938716;0.344692;0.000000;, - 0.938716;0.344692;0.000000;, - 0.887308;-0.461177;0.000000;, - 0.000000;0.000000;1.000000;, - 0.901160;-0.433486;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -0.852367;0.000000;0.522944;, - -0.852367;0.000000;0.522944;, - -0.833659;0.000000;-0.552279;, - -0.833659;0.000000;-0.552279;, - -0.833659;0.000000;-0.552279;, - 0.000000;1.000000;0.000000;, - -0.833659;0.000000;-0.552279;, - -0.852367;0.000000;0.522944;, - -0.852367;0.000000;0.522944;, - 0.000000;1.000000;0.000000;, - -0.232937;0.000000;0.972492;, - 0.000000;1.000000;0.000000;, - -0.232937;0.000000;0.972492;, - 0.000000;-1.000000;0.000000;, - -0.833659;0.000000;-0.552279;, - -0.833659;0.000000;-0.552279;, - 0.000000;-1.000000;0.000000;, - -0.852367;0.000000;0.522944;, - -0.852367;0.000000;0.522944;, - 0.000000;-1.000000;0.000000;, - -0.232937;0.000000;0.972492;, - 0.505754;-0.862678;0.000000;, - 0.000000;0.000000;1.000000;, - 0.505754;-0.862678;0.000000;, - -0.334945;0.942238;0.000000;, - -0.163134;-0.084065;0.983016;, - -0.334945;0.942238;0.000000;, - -0.163134;-0.084065;0.983016;, - 0.631267;0.775565;0.000000;, - 0.631267;0.775565;0.000000;, - -0.356870;-0.669711;0.651254;, - -0.356870;-0.669711;0.651254;, - 0.986099;0.166158;0.000000;, - -0.601679;0.798738;0.000000;, - -0.356870;-0.669711;0.651254;, - -0.356870;-0.669711;0.651254;, - -0.356869;-0.669712;-0.651253;, - -0.601679;0.798738;0.000000;, - -0.356869;-0.669712;-0.651253;, - -0.953833;0.300339;0.000000;, - 0.000000;0.000000;1.000000;, - -0.953833;0.300339;0.000000;, - 0.000000;0.000000;1.000000;, - 0.682801;0.730605;0.000000;, - -0.712537;0.701634;0.000000;, - 0.000000;0.000000;1.000000;, - 0.712526;-0.701646;0.000000;, - 0.682801;0.730605;0.000000;, - -0.985989;-0.166808;0.000000;, - 0.712526;-0.701646;0.000000;, - 0.000000;0.000000;1.000000;, - -0.933289;-0.359126;0.000000;, - 0.000000;0.000000;1.000000;, - -0.933289;-0.359126;0.000000;, - 0.000000;0.000000;1.000000;, - -0.797086;0.603866;0.000000;, - 0.000000;0.000000;1.000000;, - 0.997575;-0.069594;0.000000;, - -0.337034;0.941492;0.000000;, - -0.693605;-0.720355;0.000000;, - 0.997575;-0.069594;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.747101;0.000000;0.664711;, - 0.747101;0.000000;0.664711;, - 0.000000;-1.000000;0.000000;, - 0.747101;0.000000;0.664711;, - 0.747101;0.000000;0.664711;, - 0.000000;1.000000;0.000000;, - 1.000000;-0.000001;-0.000002;, - 0.000000;1.000000;0.000000;, - 1.000000;-0.000001;-0.000002;, - 0.000000;-1.000000;0.000000;, - 0.747099;-0.000002;-0.664713;, - 0.000000;-1.000000;0.000000;, - 0.747099;-0.000002;-0.664713;, - 0.747099;-0.000002;-0.664713;, - 0.000000;1.000000;0.000000;, - 0.747099;-0.000002;-0.664713;, - -0.502197;-0.844060;0.188043;, - -0.502197;-0.844060;0.188043;, - -0.872012;-0.358050;0.333759;, - -0.872012;-0.358050;0.333759;, - -0.872012;-0.358050;0.333759;, - -0.467763;-0.861860;-0.195947;, - -0.467763;-0.861860;-0.195947;, - -0.445914;-0.895076;0.000000;, - -0.445914;-0.895076;0.000000;, - -0.445914;-0.895076;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.445914;-0.895076;0.000000;, - -0.445914;-0.895076;0.000000;, - -0.445914;-0.895076;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.948223;-0.317605;0.000000;, - -0.948223;-0.317605;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.872012;0.358050;0.333759;, - -0.872012;0.358050;0.333759;, - -0.872012;0.358050;0.333759;, - -0.502197;0.844060;0.188043;, - -0.502197;0.844060;0.188043;, - -0.467763;0.861860;-0.195947;, - -0.467763;0.861860;-0.195947;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.445914;0.895076;0.000000;, - -0.445914;0.895076;0.000000;, - -0.445914;0.895076;0.000000;, - -0.948223;0.317605;0.000000;, - -0.948223;0.317605;0.000000;, - -0.948223;0.317605;0.000000;, - -0.948223;0.317605;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.445914;0.895076;0.000000;, - -0.445914;0.895076;0.000000;, - -0.445914;0.895076;0.000000;, - -0.948223;0.317605;0.000000;, - -0.948223;0.317605;0.000000;, - -0.948223;0.317605;0.000000;, - -0.948223;0.317605;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.009641;0.000000;0.999954;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.009641;0.000000;0.999954;, - -0.007275;0.000000;0.999974;, - -0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - -0.007275;0.000000;0.999974;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - 0.947824;0.000000;-0.318793;, - 0.000000;-1.000000;0.000000;, - 0.444793;0.000000;0.895634;, - 0.444793;0.000000;0.895634;, - 0.947824;0.000000;0.318793;, - 0.000000;-1.000000;0.000000;, - 0.947824;0.000000;0.318793;, - 0.947824;0.000000;-0.318793;, - 0.444793;0.000000;0.895634;, - 0.444793;0.000000;0.895634;, - 0.000000;1.000000;0.000000;, - 0.947824;0.000000;-0.318793;, - 0.000000;1.000000;0.000000;, - 0.947824;0.000000;0.318793;, - 0.000000;1.000000;0.000000;, - 0.444793;0.000000;0.895634;, - 0.444793;0.000000;0.895634;, - -0.812847;0.000000;0.582477;, - 0.000000;-1.000000;0.000000;, - -0.812847;0.000000;0.582477;, - -0.920207;0.000000;-0.391432;, - 0.000000;-1.000000;0.000000;, - -0.920207;0.000000;-0.391432;, - 0.000000;1.000000;0.000000;, - -0.812847;0.000000;0.582477;, - 0.000000;1.000000;0.000000;, - -0.812847;0.000000;0.582477;, - -0.519988;0.000000;-0.854174;, - -0.519988;0.000000;-0.854174;, - 0.000000;-1.000000;0.000000;, - -0.519988;0.000000;-0.854174;, - -0.519988;0.000000;-0.854174;, - 0.000000;1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - 0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - 0.225237;0.000000;0.974304;, - 0.000000;1.000000;0.000000;, - 0.009641;0.000000;0.999954;, - -0.999835;0.000000;-0.018151;, - 0.000000;-1.000000;0.000000;, - 0.009641;0.000000;0.999954;, - 0.000000;1.000000;0.000000;, - -0.999835;0.000000;-0.018151;, - 0.003775;0.861001;0.508589;, - 0.003775;0.861001;0.508589;, - 0.003775;0.861001;0.508589;, - 0.751444;0.431738;0.498932;, - 0.751444;0.431738;0.498932;, - 0.751444;0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.003775;-0.861001;0.508589;, - 0.003775;-0.861001;0.508589;, - 0.003775;-0.861001;0.508589;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.943629;-0.331006;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.433190;-0.901303;0.000000;, - 0.433190;-0.901303;0.000000;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.000000;-1.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.444792;0.000000;0.895634;, - -0.444792;0.000000;0.895634;, - 0.000000;-1.000000;0.000000;, - -0.947824;0.000000;-0.318793;, - 0.000000;-1.000000;0.000000;, - -0.947824;0.000000;0.318794;, - -0.444792;0.000000;0.895634;, - -0.444792;0.000000;0.895634;, - -0.947824;0.000000;0.318794;, - -0.947824;0.000000;-0.318793;, - 0.000000;1.000000;0.000000;, - -0.444792;0.000000;0.895634;, - -0.444792;0.000000;0.895634;, - 0.000000;1.000000;0.000000;, - -0.947824;0.000000;0.318794;, - -0.947824;0.000000;-0.318793;, - 0.000000;1.000000;0.000000;, - -0.739674;-0.429301;0.518250;, - -0.739674;-0.429301;0.518250;, - -0.739674;-0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - 0.923880;0.382683;0.000000;, - 0.923880;0.382683;0.000000;, - 0.000000;0.000000;1.000000;, - 0.923880;0.382683;0.000000;, - -0.000000;0.000000;-1.000000;, - 0.923880;0.382683;0.000000;, - 0.923880;-0.382683;0.000000;, - 0.923880;-0.382683;0.000000;, - 0.000000;-0.000000;1.000000;, - 0.923880;-0.382683;0.000000;, - -0.000000;-0.000000;-1.000000;, - 0.923880;-0.382683;0.000000;, - -0.100988;-0.994888;-0.000000;, - -0.492699;-0.870200;0.000000;, - 0.000000;-0.000000;-1.000000;, - -0.492699;-0.870200;0.000000;, - 0.000000;-0.000000;-1.000000;, - -0.492699;-0.870200;0.000000;, - -0.100988;-0.994888;-0.000000;, - 0.000000;0.000000;-1.000000;, - 0.382683;0.923880;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -0.000000;0.000000;-1.000000;, - 0.382683;0.923880;0.000000;, - -0.000000;0.000000;-1.000000;, - 0.382683;-0.923880;0.000000;, - 0.000000;-0.000000;1.000000;, - 0.382683;-0.923880;0.000000;, - -0.000000;-0.000000;-1.000000;, - -0.382683;-0.923880;0.000000;, - -0.000000;-0.000000;-1.000000;, - 0.000000;-0.000000;1.000000;, - -0.382683;-0.923880;0.000000;, - -0.410296;0.911952;0.000000;, - -0.000000;-0.000000;-1.000000;, - -0.410296;0.911952;0.000000;, - 0.000000;-0.000000;1.000000;, - 0.000000;-0.000000;1.000000;, - -0.000000;-0.000000;-1.000000;, - -1.000000;0.000000;-0.000000;, - 0.000000;-1.000000;0.000000;, - -0.100988;-0.994888;-0.000000;, - -0.331004;-0.943629;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.901302;-0.433191;-0.000000;, - -0.901302;-0.433191;-0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;-0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.100988;-0.994888;-0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - -0.922348;0.386359;0.000000;, - 0.701454;-0.712715;0.000000;, - 0.000000;0.000000;1.000000;, - -0.922348;0.386359;0.000000;, - -0.000000;0.000000;-1.000000;, - 0.701454;-0.712715;0.000000;, - -0.934971;0.354724;0.000000;, - -0.934971;0.354724;0.000000;, - -0.000000;-0.000000;-1.000000;, - -0.934971;0.354724;0.000000;, - 0.000000;-0.000000;1.000000;, - -0.934971;0.354724;0.000000;, - 0.000000;-0.000000;1.000000;, - 0.701454;-0.712715;0.000000;, - -0.701454;0.712715;0.000000;, - -0.707107;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.000000;-0.000000;-1.000000;, - -0.000000;-0.000000;-1.000000;, - 0.701454;-0.712715;0.000000;, - -0.701454;0.712715;0.000000;, - -0.707107;-0.707107;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.894428;0.447212;0.000000;, - 0.894428;0.447212;0.000000;, - 0.316229;0.948683;0.000000;, - 0.894428;0.447212;0.000000;, - 0.894428;0.447212;0.000000;, - 0.316229;0.948683;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.382684;0.923879;-0.000000;, - -0.382684;0.923879;-0.000000;, - -0.923880;0.382683;-0.000000;, - -0.382684;0.923879;-0.000000;, - -0.382684;0.923879;-0.000000;, - -0.923880;0.382683;-0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.467971;0.748047;0.470562;, - 0.467971;0.748047;0.470562;, - 0.448202;0.785835;-0.426119;, - 0.448202;0.785835;-0.426119;, - 0.734898;0.095942;-0.671356;, - 0.734898;0.095942;-0.671356;, - 1.000000;0.000000;0.000000;, - 0.000216;0.747545;-0.664211;, - 0.000216;0.747545;-0.664211;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.780420;0.375853;-0.499679;, - 0.780420;0.375853;-0.499679;, - 0.780420;0.375853;-0.499679;, - 0.255331;0.610630;-0.749625;, - 0.255331;0.610630;-0.749625;, - 0.000100;0.382250;-0.924059;, - 0.000100;0.382250;-0.924059;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.999885;0.015182;0.000000;, - 0.999885;0.015182;0.000000;, - 0.999956;-0.009391;0.000000;, - 0.999956;-0.009391;0.000000;, - 0.186216;0.982509;0.000000;, - 0.817769;0.575546;0.000000;, - 0.817769;0.575546;0.000000;, - 0.164920;-0.986307;0.000000;, - 0.808550;-0.588427;0.000000;, - 0.808550;-0.588427;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.486044;-0.714149;0.503739;, - 0.486044;-0.714149;0.503739;, - 0.486044;-0.714149;0.503739;, - 0.729011;0.129146;0.672209;, - 0.729011;0.129146;0.672209;, - 0.729011;0.129146;0.672209;, - 0.535202;-0.323949;0.780138;, - 0.535202;-0.323949;0.780138;, - 0.535202;-0.323949;0.780138;, - 0.000000;-0.862942;0.505302;, - 0.000000;-0.862942;0.505302;, - 0.000000;0.177449;0.984130;, - 0.000000;0.177449;0.984130;, - 0.000000;-0.483412;0.875393;, - 0.000000;-0.483412;0.875393;, - -0.486044;-0.714149;0.503739;, - -0.486044;-0.714149;0.503739;, - -0.486044;-0.714149;0.503739;, - -0.729011;0.129146;0.672209;, - -0.729011;0.129146;0.672209;, - -0.729011;0.129146;0.672209;, - -0.535202;-0.323949;0.780138;, - -0.535202;-0.323949;0.780138;, - -0.535202;-0.323949;0.780138;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.481363;0.876521;, - 0.000000;-0.481363;0.876521;, - 0.704085;-0.354065;0.615550;, - 0.704085;-0.354065;0.615550;, - 0.704085;-0.354065;0.615550;, - 0.683829;0.118010;0.720036;, - 0.683829;0.118010;0.720036;, - 0.000000;0.104270;0.994549;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.481363;0.876521;, - 0.000000;-0.481363;0.876521;, - -0.683829;0.118010;0.720036;, - -0.683829;0.118010;0.720036;, - -0.704085;-0.354065;0.615550;, - -0.704085;-0.354065;0.615550;, - -0.704085;-0.354065;0.615550;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.671803;0.000000;0.740730;, - 0.671803;0.000000;0.740730;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -0.671803;0.000000;0.740730;, - -0.671803;0.000000;0.740730;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.575435;0.817848;, - 0.000000;-0.575435;0.817848;, - 0.000000;-0.304659;0.952461;, - 0.992902;-0.118932;0.000000;, - 0.000000;-0.912569;0.408924;, - 0.000000;-0.912569;0.408924;, - 0.000000;-0.304659;0.952461;, - -0.996514;-0.083420;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.575435;0.817848;, - 0.000000;-0.575435;0.817848;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.712713;-0.627305;0.313893;, - 0.712713;-0.627305;0.313893;, - 0.712713;-0.627305;0.313893;, - 0.995295;-0.096836;-0.003218;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - 0.006548;0.000000;0.999979;, - -0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - 0.006548;0.000000;0.999979;, - 1.000000;0.000000;0.000000;, - 0.000000;0.175892;0.984409;, - 1.000000;0.000000;0.000000;, - 0.000000;0.821703;0.569915;, - 0.000000;0.821703;0.569915;, - 0.000000;-0.010682;0.999943;, - 0.000000;0.821703;0.569915;, - 0.000000;0.821703;0.569915;, - -1.000000;0.000000;0.000000;, - 0.000000;0.175892;0.984409;, - -1.000000;0.000000;0.000000;, - 0.000000;0.821703;0.569915;, - 0.000000;0.821703;0.569915;, - 0.000000;-1.000000;0.000000;, - 0.623102;0.286079;0.727944;, - 0.623102;0.286079;0.727944;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.964942;0.262464;, - 0.999551;-0.028922;-0.007867;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.855810;0.517291;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.491279;0.871002;, - 0.000000;-0.494957;-0.868917;, - 0.000000;-0.494957;-0.868917;, - 0.414336;-0.420954;-0.806922;, - 0.414336;-0.420954;-0.806922;, - 0.414336;-0.420954;-0.806922;, - 0.414336;-0.420954;-0.806922;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;1.000000;0.000000;, - 0.225248;-0.235329;0.945454;, - 0.237889;-0.660874;0.711797;, - 0.237889;-0.660874;0.711797;, - 0.694911;-0.059586;0.716623;, - 0.694911;-0.059586;0.716623;, - 0.724776;-0.636464;0.263843;, - 0.724776;-0.636464;0.263843;, - 0.724776;-0.636464;0.263843;, - 0.724776;-0.636464;0.263843;, - 0.656366;-0.210294;0.724542;, - 0.656366;-0.210294;0.724542;, - 0.660218;0.043171;0.749833;, - 0.660218;0.043171;0.749833;, - 0.000000;-0.855810;0.517291;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.491279;0.871002;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.694911;-0.059586;0.716623;, - -0.694911;-0.059586;0.716623;, - -0.724776;-0.636464;0.263843;, - -0.724776;-0.636464;0.263843;, - -0.724776;-0.636464;0.263843;, - -0.724776;-0.636464;0.263843;, - -0.225248;-0.235329;0.945454;, - -0.237889;-0.660874;0.711797;, - -0.237889;-0.660874;0.711797;, - 0.181527;-0.897955;0.400904;, - 0.181527;-0.897955;0.400904;, - 0.181527;-0.897955;0.400904;, - 0.388340;-0.313507;0.866548;, - 0.388340;-0.313507;0.866548;, - 0.388340;-0.313507;0.866548;, - 0.388340;-0.313507;0.866548;, - 0.388341;0.313505;0.866548;, - 0.388341;0.313505;0.866548;, - 0.388341;0.313505;0.866548;, - 0.388341;0.313505;0.866548;, - 0.181529;0.897954;0.400905;, - 0.181529;0.897954;0.400905;, - 0.181529;0.897954;0.400905;, - -0.007275;0.000000;0.999974;, - 0.999860;0.000000;-0.016753;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - -0.007275;0.000000;0.999974;, - -0.999860;0.000000;0.016753;, - -0.999860;0.000000;0.016753;, - 0.999860;0.000000;-0.016753;, - 0.999860;0.000000;-0.016753;, - -0.999860;0.000000;0.016753;, - 0.006548;0.000000;0.999979;, - -0.999860;0.000000;0.016753;, - 0.006548;0.000000;0.999979;, - 0.999860;0.000000;-0.016753;, - 0.006548;0.000000;0.999979;, - 0.999860;0.000000;-0.016753;, - 0.006548;0.000000;0.999979;, - -0.368706;-0.354448;0.859315;, - -0.368706;-0.354448;0.859315;, - -0.368706;-0.354448;0.859315;, - -0.368706;-0.354448;0.859315;, - -0.155472;-0.914282;0.374054;, - 0.000000;-0.300369;0.953823;, - 0.000000;-0.300369;0.953823;, - 0.000000;-0.300369;0.953823;, - 0.000000;-0.300369;0.953823;, - -0.000000;-0.929961;0.367659;, - -0.000000;-0.929961;0.367659;, - 0.000000;-0.886848;0.462062;, - 0.000000;-0.886848;0.462062;, - -0.368706;0.354448;0.859315;, - -0.368706;0.354448;0.859315;, - -0.368706;0.354448;0.859315;, - -0.155472;0.914282;0.374054;, - 0.000000;0.300369;0.953823;, - 0.000000;0.300369;0.953823;, - 0.000000;0.886848;0.462062;, - 0.000000;0.886848;0.462062;, - 0.000000;0.929961;0.367659;, - 0.000000;0.929961;0.367659;, - 0.000000;0.300369;0.953823;, - 0.000000;0.300369;0.953823;, - 0.008294;0.000000;0.999966;, - 0.952657;0.000000;0.304046;, - 0.952657;0.000000;0.304046;, - 0.897253;-0.281640;0.340023;, - 0.897253;-0.281640;0.340023;, - 0.428060;-0.799374;0.421624;, - 0.428060;-0.799374;0.421624;, - 0.428060;-0.799374;0.421624;, - 0.428060;-0.799374;0.421624;, - 0.410415;-0.110414;0.905189;, - 0.410415;-0.110414;0.905189;, - 0.458637;0.000000;0.888624;, - 0.458637;0.000000;0.888624;, - -0.418146;-0.801329;0.427815;, - -0.418146;-0.801329;0.427815;, - -0.418146;-0.801329;0.427815;, - -0.421913;-0.784056;0.455242;, - -0.421913;-0.784056;0.455242;, - -0.421913;-0.784056;0.455242;, - -0.000000;-0.000000;1.000000;, - -0.115463;-0.249286;0.961522;, - -0.115463;-0.249286;0.961522;, - 0.179157;-0.288632;0.940529;, - 0.179157;-0.288632;0.940529;, - -0.000000;0.000000;1.000000;, - -0.191832;-0.385043;0.902742;, - -0.000000;-0.000000;1.000000;, - -0.292367;-0.866429;0.404750;, - -0.292367;-0.866429;0.404750;, - -0.292367;-0.866429;0.404750;, - -0.830569;-0.387539;0.399961;, - -0.830569;-0.387539;0.399961;, - -0.830569;-0.387539;0.399961;, - -0.830569;-0.387539;0.399961;, - -0.000000;0.000000;1.000000;, - -0.109902;-0.344862;0.932197;, - -0.109902;-0.344862;0.932197;, - -0.945889;0.000000;0.324489;, - -0.945889;0.000000;0.324489;, - -0.439396;0.000000;0.898293;, - -0.439396;0.000000;0.898293;, - -0.442680;-0.198092;0.874525;, - -0.442680;-0.198092;0.874525;, - 0.000000;0.445625;0.895220;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.797864;0.602838;, - 0.410381;0.364278;-0.835996;, - 0.410381;0.364278;-0.835996;, - 0.410381;0.364278;-0.835996;, - 0.410381;0.364278;-0.835996;, - 0.000000;0.435777;-0.900055;, - 0.000000;0.435777;-0.900055;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.222802;0.267250;0.937516;, - 0.694989;0.067591;0.715836;, - 0.694989;0.067591;0.715836;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.656242;0.365940;0.659875;, - 0.000000;0.445625;0.895220;, - 0.000000;0.797864;0.602838;, - 0.000000;0.000000;-1.000000;, - 0.598854;-0.729241;-0.331031;, - 0.598854;-0.729241;-0.331031;, - 0.598854;-0.729241;-0.331031;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.948481;0.316834;, - -1.000000;0.000000;0.000000;, - 0.294926;-0.896305;0.331144;, - 0.294926;-0.896305;0.331144;, - 0.458630;0.558096;-0.691511;, - 0.458630;0.558096;-0.691511;, - 0.000000;0.803358;-0.595497;, - 0.920337;-0.258232;-0.293762;, - 0.843584;0.257465;-0.471252;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.999619;0.027602;, - 0.912505;0.010391;-0.408934;, - 0.912505;0.010391;-0.408934;, - 0.665236;0.018966;-0.746392;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.694990;0.067591;0.715836;, - -0.694990;0.067591;0.715836;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -0.222802;0.267250;0.937516;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;-1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;-0.016753;, - -0.006548;0.000000;-0.999979;, - -0.999860;0.000000;0.016753;, - -0.006548;0.000000;-0.999979;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;0.016753;, - 0.000000;1.000000;0.000000;, - 0.999860;0.000000;-0.016754;, - 0.000000;1.000000;0.000000;, - 0.006548;0.000000;0.999979;, - 0.999860;0.000000;-0.016753;, - -0.999860;0.000000;0.016753;, - 0.006548;0.000000;0.999979;, - 0.000000;1.000000;0.000000;, - -0.999860;0.000000;0.016753;, - 0.006548;0.000000;0.999979;, - 0.999860;0.000000;-0.016753;, - 0.006548;0.000000;0.999979;, - -0.999860;0.000000;0.016753;, - 0.000000;-1.000000;0.000000;, - -0.006548;0.000000;-0.999979;, - -0.999860;0.000000;0.016753;, - 0.006548;0.000000;0.999979;, - 0.006548;0.000000;0.999979;, - 0.999860;0.000000;-0.016753;, - -0.006548;0.000000;-0.999979;, - 0.999860;0.000000;-0.016753;, - 0.000000;-1.000000;0.000000;, - 0.831040;0.403243;0.383102;, - 0.831040;0.403243;0.383102;, - 0.831040;0.403243;0.383102;, - 0.831040;0.403243;0.383102;, - 0.282244;0.875709;0.391756;, - 0.282244;0.875709;0.391756;, - 0.282244;0.875709;0.391756;, - 0.457151;0.212943;0.863521;, - 0.457151;0.212943;0.863521;, - -0.000000;0.933082;0.359664;, - -0.000000;0.933082;0.359664;, - -0.000000;0.405468;0.914109;, - -0.000000;0.405468;0.914109;, - 0.109882;0.357779;0.927319;, - 0.109882;0.357779;0.927319;, - -0.349235;0.855784;0.381665;, - -0.349235;0.855784;0.381665;, - -0.349235;0.855784;0.381665;, - -0.349235;0.855784;0.381665;, - -0.859819;0.357289;0.364767;, - -0.859819;0.357289;0.364767;, - -0.859819;0.357289;0.364767;, - -0.142369;0.355966;0.923590;, - -0.142369;0.355966;0.923590;, - -0.486422;0.202974;0.849820;, - -0.486422;0.202974;0.849820;, - 0.231731;0.696564;0.679043;, - 0.231731;0.696564;0.679043;, - 0.718709;0.648693;0.250309;, - 0.718709;0.648693;0.250309;, - 0.718709;0.648693;0.250309;, - 0.718709;0.648693;0.250309;, - 1.000000;0.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.919279;0.393601;-0.001941;, - 0.919279;0.393601;-0.001941;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.834468;0.551056;, - 0.370322;0.928840;-0.010859;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.000000;-0.834468;0.551056;, - 0.999885;0.015182;0.000000;, - 0.999885;0.015182;0.000000;, - 0.999956;-0.009391;0.000000;, - 0.999956;-0.009391;0.000000;, - 0.186216;0.982509;0.000000;, - 0.817769;0.575546;0.000000;, - 0.817769;0.575546;0.000000;, - 0.164920;-0.986307;0.000000;, - 0.808550;-0.588427;0.000000;, - 0.808550;-0.588427;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.999519;-0.012421;0.028413;, - 0.000000;-0.975913;0.218160;, - -0.718710;0.648693;0.250309;, - -0.718710;0.648693;0.250309;, - -0.718710;0.648693;0.250309;, - -0.718710;0.648693;0.250309;, - -0.231732;0.696564;0.679043;, - -0.231732;0.696564;0.679043;, - 0.996793;-0.079877;-0.004828;, - 0.879287;-0.284211;0.382202;, - 0.000000;-0.249931;0.968264;, - 0.449264;-0.278514;0.848877;, - 0.000000;0.607263;0.794501;, - 0.999551;-0.028922;-0.007867;, - 0.920795;-0.364979;-0.137577;, - 0.920795;-0.364979;-0.137577;, - 0.924846;-0.329505;0.189965;, - 0.924846;-0.329505;0.189965;, - 0.924846;-0.329505;0.189965;, - 0.868861;-0.198793;-0.453389;, - 0.868861;-0.198793;-0.453389;, - 0.374350;-0.888608;-0.265025;, - 0.374350;-0.888608;-0.265025;, - 0.000000;-0.964405;-0.264430;, - 0.000000;-0.869582;0.493788;, - 0.000000;-0.869582;0.493788;, - 0.379211;-0.803330;0.459195;, - 0.379211;-0.803330;0.459195;, - 0.379211;-0.803330;0.459195;, - 1.000000;0.000000;0.000000;, - 0.910502;0.394198;0.124877;, - 0.918267;0.364101;-0.155619;, - 0.918267;0.364101;-0.155619;, - 0.852588;-0.139808;0.503535;, - 0.852588;-0.139808;0.503535;, - 0.881297;0.207501;0.424568;, - 0.881297;0.207501;0.424568;, - 0.867287;0.166714;-0.469062;, - 0.867287;0.166714;-0.469062;, - 0.000000;-0.265726;0.964049;, - 0.369966;-0.247588;0.895447;, - 0.369966;-0.247588;0.895447;, - 0.000000;0.441670;0.897178;, - 0.000000;0.441670;0.897178;, - 0.413389;0.401188;0.817410;, - 0.413389;0.401188;0.817410;, - 0.413389;0.401188;0.817410;, - 0.413389;0.401188;0.817410;, - 0.000000;0.946708;0.322092;, - 0.345924;0.891018;0.293977;, - 0.345924;0.891018;0.293977;, - 0.000000;0.944576;-0.328294;, - 0.363628;0.875934;-0.317041;, - 0.363628;0.875934;-0.317041;, - 0.892669;-0.416427;0.172425;, - 0.892669;-0.416427;0.172425;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.999666;0.025839;, - 1.000000;0.000000;0.000000;, - 0.365213;0.930924;0.000867;, - 0.916507;0.400018;0.000880;, - 0.916507;0.400018;0.000880;, - 0.916507;-0.400018;0.000881;, - 0.916507;-0.400018;0.000881;, - 0.365213;-0.930924;0.000867;, - 0.747129;-0.554595;0.366363;, - 0.747129;-0.554595;0.366363;, - 0.747129;-0.554595;0.366363;, - 0.947248;0.154288;0.280921;, - 0.947248;0.154288;0.280921;, - 0.947248;0.154288;0.280921;, - 0.196577;-0.789407;0.581544;, - 0.196577;-0.789407;0.581544;, - 0.313397;-0.205419;0.927138;, - 0.550087;0.653417;0.520048;, - 0.540165;0.139016;0.829998;, - 0.360386;0.905749;0.223026;, - 0.999519;-0.012421;0.028413;, - 0.000000;-0.694243;0.719740;, - 0.999519;-0.012421;0.028413;, - 0.000000;-0.182834;0.983144;, - 0.297687;0.906393;-0.299723;, - 0.297687;0.906393;-0.299723;, - 0.000000;0.949568;-0.313562;, - 0.888768;0.435110;-0.144120;, - 0.888768;0.435110;-0.144120;, - 0.000000;-0.629060;0.777357;, - 0.000000;-0.629060;0.777357;, - -1.000000;0.000000;0.000000;, - 0.253225;-0.608206;0.752305;, - 0.253225;-0.608206;0.752305;, - 0.253225;-0.608206;0.752305;, - 0.253225;-0.608206;0.752305;, - 0.346801;-0.205807;0.915080;, - 0.346801;-0.205807;0.915080;, - 0.000000;-0.143364;0.989670;, - 0.000000;-0.432176;0.901789;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.827784;0.561046;, - 0.867484;-0.312547;0.387021;, - 0.867484;-0.312547;0.387021;, - 0.867484;-0.312547;0.387021;, - 0.909236;-0.093398;0.405669;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.999215;0.039615;, - 1.000000;0.000000;0.000000;, - 0.993070;0.000000;0.117523;, - 0.000000;-0.976749;0.214388;, - 0.515284;-0.506815;0.691102;, - 0.515284;-0.506815;0.691102;, - 0.515284;-0.506815;0.691102;, - 0.523532;0.520184;0.674777;, - 0.523532;0.520184;0.674777;, - 0.523532;0.520184;0.674777;, - 0.000000;0.986719;0.162438;, - 0.993070;0.000000;0.117523;, - 0.356854;0.918943;0.167923;, - 0.264647;0.688916;0.674802;, - 0.264647;0.688916;0.674802;, - 0.903543;0.390832;0.175672;, - 0.903543;0.390832;0.175672;, - 0.505677;0.216655;0.835075;, - 0.505677;0.216655;0.835075;, - 0.505677;0.216655;0.835075;, - 0.903542;-0.390835;0.175672;, - 0.903542;-0.390835;0.175672;, - 0.505675;-0.216658;0.835076;, - 0.505675;-0.216658;0.835076;, - 0.505675;-0.216658;0.835076;, - 0.356852;-0.918945;0.167922;, - 0.264644;-0.688919;0.674800;, - 0.264644;-0.688919;0.674800;, - 0.000000;0.493245;0.869891;, - 0.000000;0.493245;0.869891;, - 0.415843;0.444085;0.793639;, - 0.415843;0.444085;0.793639;, - 0.415843;0.444085;0.793639;, - 0.415843;0.444085;0.793639;, - 0.342656;0.907349;0.243524;, - 0.342656;0.907349;0.243524;, - 0.000000;0.963882;0.266329;, - 0.908555;0.404498;0.104448;, - 0.908555;0.404498;0.104448;, - 0.882298;0.226639;0.412534;, - -1.000000;-0.000000;-0.000000;, - 0.689334;0.531821;-0.491919;, - 0.689334;0.531821;-0.491919;, - 0.689334;0.531821;-0.491919;, - 0.697330;-0.000000;-0.716750;, - 0.697330;-0.000000;-0.716750;, - 0.689334;-0.531822;-0.491919;, - 0.689334;-0.531822;-0.491919;, - 0.689334;-0.531822;-0.491919;, - 0.682700;-0.730699;0.000000;, - 0.682700;-0.730699;0.000000;, - 1.000000;-0.000000;-0.000000;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - -0.689334;0.531821;-0.491919;, - -0.689334;0.531821;-0.491919;, - -0.689334;0.531821;-0.491919;, - -0.697330;-0.000000;-0.716750;, - -0.697330;-0.000000;-0.716750;, - -0.689334;-0.531822;-0.491919;, - -0.689334;-0.531822;-0.491919;, - -0.689334;-0.531822;-0.491919;, - -0.682700;-0.730699;0.000000;, - -0.682700;-0.730699;0.000000;, - 0.682700;0.730699;0.000000;, - 0.682700;0.730699;0.000000;, - 0.000000;1.000000;0.000000;, - -0.682700;0.730699;0.000000;, - -0.682700;0.730699;0.000000;, - 0.689334;0.531821;0.491919;, - 0.689334;0.531821;0.491919;, - 0.689334;0.531821;0.491919;, - 0.697331;-0.000000;0.716750;, - 0.697331;-0.000000;0.716750;, - 0.689334;-0.531822;0.491919;, - 0.689334;-0.531822;0.491919;, - 0.689334;-0.531822;0.491919;, - 0.000000;-0.000000;1.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - -0.689334;0.531821;0.491919;, - -0.689334;0.531821;0.491919;, - -0.689334;0.531821;0.491919;, - -0.697331;-0.000000;0.716750;, - -0.697331;-0.000000;0.716750;, - -0.689334;-0.531822;0.491919;, - -0.689334;-0.531822;0.491919;, - -0.689334;-0.531822;0.491919;, - 0.365213;0.930924;0.000867;, - 0.916507;0.400018;0.000881;, - 0.916507;0.400018;0.000881;, - 0.916507;-0.400018;0.000881;, - 0.916507;-0.400018;0.000881;, - 0.365213;-0.930924;0.000867;, - 0.993070;0.000000;0.117523;, - 0.000000;-0.976748;0.214391;, - 0.515283;-0.506814;0.691102;, - 0.515283;-0.506814;0.691102;, - 0.515283;-0.506814;0.691102;, - 0.523532;0.520184;0.674776;, - 0.523532;0.520184;0.674776;, - 0.523532;0.520184;0.674776;, - 0.000000;0.986719;0.162435;, - 0.993070;0.000000;0.117523;, - 0.356851;0.918944;0.167924;, - 0.264643;0.688917;0.674802;, - 0.264643;0.688917;0.674802;, - 0.903541;0.390835;0.175673;, - 0.903541;0.390835;0.175673;, - 0.505675;0.216658;0.835076;, - 0.505675;0.216658;0.835076;, - 0.505675;0.216658;0.835076;, - 0.903543;-0.390832;0.175672;, - 0.903543;-0.390832;0.175672;, - 0.505677;-0.216655;0.835075;, - 0.505677;-0.216655;0.835075;, - 0.505677;-0.216655;0.835075;, - 0.356854;-0.918943;0.167923;, - 0.264647;-0.688916;0.674802;, - 0.264647;-0.688916;0.674802;, - -0.414336;-0.420954;-0.806922;, - -0.414336;-0.420954;-0.806922;, - -0.414336;-0.420954;-0.806922;, - -0.414336;-0.420954;-0.806922;, - -0.410381;0.364278;-0.835996;, - -0.410381;0.364278;-0.835996;, - -0.410381;0.364278;-0.835996;, - -0.410381;0.364278;-0.835996;, - -0.920795;-0.364979;-0.137577;, - -0.920795;-0.364979;-0.137577;, - -0.924846;-0.329505;0.189965;, - -0.924846;-0.329505;0.189965;, - -0.924846;-0.329505;0.189965;, - -0.868862;-0.198793;-0.453388;, - -0.868862;-0.198793;-0.453388;, - -0.374350;-0.888608;-0.265025;, - -0.374350;-0.888608;-0.265025;, - -0.379211;-0.803330;0.459195;, - -0.379211;-0.803330;0.459195;, - -0.379211;-0.803330;0.459195;, - -0.910502;0.394198;0.124877;, - -0.918267;0.364101;-0.155618;, - -0.918267;0.364101;-0.155618;, - -0.852588;-0.139808;0.503534;, - -0.852588;-0.139808;0.503534;, - -0.881298;0.207501;0.424568;, - -0.881298;0.207501;0.424568;, - -0.867287;0.166715;-0.469062;, - -0.867287;0.166715;-0.469062;, - -0.369966;-0.247588;0.895447;, - -0.369966;-0.247588;0.895447;, - -0.413389;0.401187;0.817410;, - -0.413389;0.401187;0.817410;, - -0.413389;0.401187;0.817410;, - -0.413389;0.401187;0.817410;, - -0.345924;0.891018;0.293977;, - -0.345924;0.891018;0.293977;, - -0.363628;0.875934;-0.317041;, - -0.363628;0.875934;-0.317041;, - 0.000000;0.520825;0.853663;, - -0.983435;-0.159487;0.086139;, - 0.000000;0.520825;0.853663;, - 0.000000;0.999161;-0.040963;, - 0.000000;0.999161;-0.040963;, - -0.983435;-0.159487;0.086139;, - 0.000000;0.699533;-0.714601;, - -0.653421;-0.748902;-0.110393;, - -0.653421;-0.748902;-0.110393;, - 0.000000;-0.332036;0.943267;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.332036;0.943267;, - 0.000000;0.098302;0.995157;, - 0.000000;0.990031;-0.140848;, - -1.000000;0.000000;0.000000;, - 0.000000;0.990031;-0.140848;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.098305;-0.995156;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.699991;0.714152;, - 0.000000;-0.098305;-0.995156;, - 0.000000;-0.832489;0.554042;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.832489;0.554042;, - 0.000000;-0.008043;0.999968;, - -1.000000;0.000000;0.000000;, - 0.000000;0.511880;0.859057;, - -1.000000;0.000000;0.000000;, - 0.000000;0.525640;-0.850707;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.987687;0.156440;, - 0.000000;0.525640;-0.850707;, - 0.000000;0.520825;0.853663;, - 0.983434;-0.159485;0.086147;, - 0.000000;0.520825;0.853663;, - 0.983434;-0.159485;0.086147;, - 0.000000;0.999161;-0.040963;, - 0.000000;0.999161;-0.040963;, - 0.653422;-0.748902;-0.110387;, - 0.653422;-0.748902;-0.110387;, - 0.000000;0.699533;-0.714601;, - 0.000000;0.236676;0.971589;, - 0.653422;-0.748902;-0.110387;, - 0.653422;-0.748902;-0.110387;, - -0.653421;-0.748902;-0.110393;, - 0.000000;0.236676;0.971589;, - -0.653421;-0.748902;-0.110393;, - 0.000000;-0.332036;0.943267;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.332036;0.943267;, - 1.000000;0.000000;0.000000;, - 0.000000;0.990031;-0.140848;, - 0.000000;0.098302;0.995157;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.098305;-0.995156;, - 0.000000;0.990031;-0.140848;, - 0.000000;-0.699991;0.714152;, - 0.000000;-0.098305;-0.995156;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.832489;0.554042;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.832489;0.554042;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.008043;0.999968;, - 1.000000;0.000000;0.000000;, - 0.000000;0.525640;-0.850707;, - 0.000000;0.511880;0.859057;, - 0.000000;-0.987687;0.156440;, - 0.000000;0.525640;-0.850707;, - 1.000000;0.000000;0.000000;, - -0.348514;0.937303;0.000000;, - -0.152110;-0.074173;-0.985576;, - -0.348514;0.937303;0.000000;, - 0.633860;0.773448;0.000000;, - 0.633860;0.773448;0.000000;, - -0.152110;-0.074173;-0.985576;, - 0.987527;0.157450;0.000000;, - -0.363340;-0.661392;-0.656159;, - -0.363340;-0.661392;-0.656159;, - -0.956602;0.291397;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.956602;0.291397;0.000000;, - -0.731614;0.681719;0.000000;, - 0.702697;0.711489;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.702697;0.711489;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.731621;-0.681712;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.987428;-0.158070;0.000000;, - 0.731621;-0.681712;0.000000;, - -0.937513;-0.347951;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.937513;-0.347951;0.000000;, - -0.803579;0.595198;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.353851;0.935302;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.997828;-0.065872;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.713241;-0.700918;0.000000;, - 0.997828;-0.065872;0.000000;, - -0.348514;0.937303;0.000000;, - -0.152109;-0.074175;0.985576;, - -0.348514;0.937303;0.000000;, - -0.152109;-0.074175;0.985576;, - 0.633860;0.773448;0.000000;, - 0.633860;0.773448;0.000000;, - -0.363339;-0.661393;0.656158;, - -0.363339;-0.661393;0.656158;, - 0.987527;0.157450;0.000000;, - -0.622827;0.782360;0.000000;, - -0.363339;-0.661393;0.656158;, - -0.363339;-0.661393;0.656158;, - -0.363340;-0.661392;-0.656159;, - -0.622827;0.782360;0.000000;, - -0.363340;-0.661392;-0.656159;, - -0.956602;0.291397;0.000000;, - 0.000000;0.000000;1.000000;, - -0.956602;0.291397;0.000000;, - 0.000000;0.000000;1.000000;, - 0.702697;0.711489;0.000000;, - -0.731614;0.681719;0.000000;, - 0.000000;0.000000;1.000000;, - 0.731621;-0.681712;0.000000;, - 0.702697;0.711489;0.000000;, - -0.987428;-0.158070;0.000000;, - 0.731621;-0.681712;0.000000;, - 0.000000;0.000000;1.000000;, - -0.937513;-0.347951;0.000000;, - 0.000000;0.000000;1.000000;, - -0.937513;-0.347951;0.000000;, - 0.000000;0.000000;1.000000;, - -0.803579;0.595198;0.000000;, - 0.000000;0.000000;1.000000;, - 0.997828;-0.065872;0.000000;, - -0.353851;0.935302;0.000000;, - -0.713241;-0.700918;0.000000;, - 0.997828;-0.065872;0.000000;, - 0.000000;0.000000;1.000000;, - -0.334945;0.942238;0.000000;, - -0.163134;-0.084068;-0.983016;, - -0.334945;0.942238;0.000000;, - 0.631267;0.775565;0.000000;, - 0.631267;0.775565;0.000000;, - -0.163134;-0.084068;-0.983016;, - 0.986099;0.166158;0.000000;, - -0.356869;-0.669712;-0.651253;, - -0.356869;-0.669712;-0.651253;, - -0.953833;0.300339;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.953833;0.300339;0.000000;, - -0.712537;0.701634;0.000000;, - 0.682801;0.730605;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.682801;0.730605;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.712526;-0.701646;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.985989;-0.166808;0.000000;, - 0.712526;-0.701646;0.000000;, - -0.933289;-0.359126;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.933289;-0.359126;0.000000;, - -0.797086;0.603866;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.337034;0.941492;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.997575;-0.069594;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.693605;-0.720355;0.000000;, - 0.997575;-0.069594;0.000000;, - -0.334945;0.942238;0.000000;, - -0.163134;-0.084064;0.983016;, - -0.334945;0.942238;0.000000;, - -0.163134;-0.084064;0.983016;, - 0.631267;0.775565;0.000000;, - 0.631267;0.775565;0.000000;, - -0.356870;-0.669710;0.651254;, - -0.356870;-0.669710;0.651254;, - 0.986099;0.166158;0.000000;, - -0.601679;0.798738;0.000000;, - -0.356870;-0.669710;0.651254;, - -0.356870;-0.669710;0.651254;, - -0.356869;-0.669712;-0.651253;, - -0.601679;0.798738;0.000000;, - -0.356869;-0.669712;-0.651253;, - -0.953833;0.300339;0.000000;, - 0.000000;0.000000;1.000000;, - -0.953833;0.300339;0.000000;, - 0.000000;0.000000;1.000000;, - 0.682801;0.730605;0.000000;, - -0.712537;0.701634;0.000000;, - 0.000000;0.000000;1.000000;, - 0.712526;-0.701646;0.000000;, - 0.682801;0.730605;0.000000;, - -0.985989;-0.166808;0.000000;, - 0.712526;-0.701646;0.000000;, - 0.000000;0.000000;1.000000;, - -0.933289;-0.359126;0.000000;, - 0.000000;0.000000;1.000000;, - -0.933289;-0.359126;0.000000;, - 0.000000;0.000000;1.000000;, - -0.797086;0.603866;0.000000;, - 0.000000;0.000000;1.000000;, - 0.997575;-0.069594;0.000000;, - -0.337034;0.941492;0.000000;, - -0.693605;-0.720355;0.000000;, - 0.997575;-0.069594;0.000000;, - 0.000000;0.000000;1.000000;, - -0.348514;0.937303;0.000000;, - -0.152109;-0.074174;-0.985576;, - -0.348514;0.937303;0.000000;, - 0.633860;0.773448;0.000000;, - 0.633860;0.773448;0.000000;, - -0.152109;-0.074174;-0.985576;, - 0.987527;0.157450;0.000000;, - -0.363340;-0.661393;-0.656159;, - -0.363340;-0.661393;-0.656159;, - -0.956602;0.291397;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.956602;0.291397;0.000000;, - -0.731614;0.681719;0.000000;, - 0.702697;0.711489;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.702697;0.711489;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.731621;-0.681712;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.987428;-0.158070;0.000000;, - 0.731621;-0.681712;0.000000;, - -0.937513;-0.347951;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.937513;-0.347951;0.000000;, - -0.803579;0.595198;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.353851;0.935302;0.000000;, - 0.000000;0.000000;-1.000000;, - 0.997828;-0.065872;0.000000;, - 0.000000;0.000000;-1.000000;, - -0.713241;-0.700918;0.000000;, - 0.997828;-0.065872;0.000000;, - -0.348514;0.937303;0.000000;, - -0.152109;-0.074173;0.985577;, - -0.348514;0.937303;0.000000;, - -0.152109;-0.074173;0.985577;, - 0.633860;0.773448;0.000000;, - 0.633860;0.773448;0.000000;, - -0.363340;-0.661392;0.656159;, - -0.363340;-0.661392;0.656159;, - 0.987527;0.157450;0.000000;, - -0.622827;0.782360;0.000000;, - -0.363340;-0.661392;0.656159;, - -0.363340;-0.661392;0.656159;, - -0.363340;-0.661393;-0.656159;, - -0.622827;0.782360;0.000000;, - -0.363340;-0.661393;-0.656159;, - -0.956602;0.291397;0.000000;, - 0.000000;0.000000;1.000000;, - -0.956602;0.291397;0.000000;, - 0.000000;0.000000;1.000000;, - 0.702697;0.711489;0.000000;, - -0.731614;0.681719;0.000000;, - 0.000000;0.000000;1.000000;, - 0.731621;-0.681712;0.000000;, - 0.702697;0.711489;0.000000;, - -0.987428;-0.158070;0.000000;, - 0.731621;-0.681712;0.000000;, - 0.000000;0.000000;1.000000;, - -0.937513;-0.347951;0.000000;, - 0.000000;0.000000;1.000000;, - -0.937513;-0.347951;0.000000;, - 0.000000;0.000000;1.000000;, - -0.803579;0.595198;0.000000;, - 0.000000;0.000000;1.000000;, - 0.997828;-0.065872;0.000000;, - -0.353851;0.935302;0.000000;, - -0.713241;-0.700918;0.000000;, - 0.997828;-0.065872;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.732950;-0.680283;, - 0.000000;0.000000;-1.000000;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-0.732950;-0.680283;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;0.000000;1.000000;, - 0.000000;0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;0.732950;0.680283;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.732950;0.680283;, - 0.000000;-0.732950;0.680283;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.732950;-0.680282;, - 0.000000;0.732950;-0.680282;, - 0.000000;-0.000000;-1.000000;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-0.732950;-0.680282;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.000000;1.000000;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.000000;1.000000;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;0.732950;0.680282;, - 0.000000;-0.000000;1.000000;, - 0.000000;-0.732950;0.680282;, - 0.000000;-0.732950;0.680282;, - -0.225238;0.000000;-0.974304;, - 0.000000;-1.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.225238;0.000000;-0.974304;, - 0.225236;-0.000000;-0.974304;, - 0.000000;1.000000;0.000000;, - 0.225236;-0.000000;-0.974304;, - 0.000000;-1.000000;0.000000;, - 0.747100;0.000000;0.664711;, - 0.747100;0.000000;0.664711;, - 0.000000;-1.000000;0.000000;, - 0.747100;0.000000;0.664711;, - 0.747100;0.000000;0.664711;, - 0.000000;1.000000;0.000000;, - 1.000000;-0.000001;-0.000001;, - 0.000000;1.000000;0.000000;, - 1.000000;-0.000001;-0.000001;, - 0.000000;-1.000000;0.000000;, - 0.747099;-0.000001;-0.664712;, - 0.000000;-1.000000;0.000000;, - 0.747099;-0.000001;-0.664712;, - 0.747099;-0.000001;-0.664712;, - 0.000000;1.000000;0.000000;, - 0.747099;-0.000001;-0.664712;, - -0.747100;0.000000;0.664712;, - 0.000000;-1.000000;0.000000;, - -0.747100;0.000000;0.664712;, - -1.000000;0.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;1.000000;0.000000;, - -0.747100;0.000000;0.664712;, - 0.000000;1.000000;0.000000;, - -0.747100;0.000000;0.664712;, - -0.747100;0.000000;-0.664711;, - -0.747100;0.000000;-0.664711;, - 0.000000;-1.000000;0.000000;, - -0.747100;0.000000;-0.664711;, - -0.747100;0.000000;-0.664711;, - 0.000000;1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;1.000000;0.000000;, - -0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - 0.225237;0.000000;0.974304;, - 0.000000;-1.000000;0.000000;, - 0.225237;0.000000;0.974304;, - 0.000000;1.000000;0.000000;, - -0.008295;0.000000;-0.999966;, - 0.739674;0.429301;-0.518250;, - 0.739674;0.429301;-0.518250;, - 0.739674;0.429301;-0.518250;, - -0.003775;0.861001;-0.508589;, - -0.003775;0.861001;-0.508589;, - -0.003775;0.861001;-0.508589;, - 0.739674;-0.429301;-0.518250;, - 0.739674;-0.429301;-0.518250;, - 0.739674;-0.429301;-0.518250;, - -0.003775;-0.861001;-0.508589;, - -0.003775;-0.861001;-0.508589;, - -0.003775;-0.861001;-0.508589;, - -0.751445;-0.431738;-0.498932;, - -0.751445;-0.431738;-0.498932;, - -0.751445;-0.431738;-0.498932;, - -0.751445;0.431738;-0.498932;, - -0.751445;0.431738;-0.498932;, - -0.751445;0.431738;-0.498932;, - 0.003774;0.861001;0.508589;, - 0.003774;0.861001;0.508589;, - 0.003774;0.861001;0.508589;, - 0.751445;0.431738;0.498932;, - 0.751445;0.431738;0.498932;, - 0.751445;0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.003774;-0.861001;0.508589;, - 0.003774;-0.861001;0.508589;, - 0.003774;-0.861001;0.508589;, - -0.739674;-0.429301;0.518250;, - -0.739674;-0.429301;0.518250;, - -0.739674;-0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - 0.008295;0.000000;0.999966;, - -0.008295;0.000000;-0.999966;, - 0.739674;0.429300;-0.518250;, - 0.739674;0.429300;-0.518250;, - 0.739674;0.429300;-0.518250;, - -0.003774;0.861001;-0.508589;, - -0.003774;0.861001;-0.508589;, - -0.003774;0.861001;-0.508589;, - 0.739674;-0.429300;-0.518250;, - 0.739674;-0.429300;-0.518250;, - 0.739674;-0.429300;-0.518250;, - -0.003774;-0.861001;-0.508589;, - -0.003774;-0.861001;-0.508589;, - -0.003774;-0.861001;-0.508589;, - -0.751445;-0.431739;-0.498932;, - -0.751445;-0.431739;-0.498932;, - -0.751445;-0.431739;-0.498932;, - -0.751445;0.431739;-0.498932;, - -0.751445;0.431739;-0.498932;, - -0.751445;0.431739;-0.498932;, - 0.003775;0.861001;0.508589;, - 0.003775;0.861001;0.508589;, - 0.003775;0.861001;0.508589;, - 0.751444;0.431738;0.498932;, - 0.751444;0.431738;0.498932;, - 0.751444;0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.751445;-0.431738;0.498932;, - 0.003775;-0.861001;0.508589;, - 0.003775;-0.861001;0.508589;, - 0.003775;-0.861001;0.508589;, - -0.739674;-0.429301;0.518250;, - -0.739674;-0.429301;0.518250;, - -0.739674;-0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - -0.739674;0.429301;0.518250;, - 0.008294;0.000000;0.999966;, - -0.223484;-0.878060;-0.423161;, - -0.223484;-0.878060;-0.423161;, - -0.267818;-0.029603;-0.963015;, - -0.267818;-0.029603;-0.963015;, - -0.831748;-0.535907;-0.144912;, - -0.831748;-0.535907;-0.144912;, - -0.831748;-0.535907;-0.144912;, - -0.823105;-0.251757;-0.509035;, - -0.823105;-0.251757;-0.509035;, - -0.823105;-0.251757;-0.509035;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.924838;-0.380361;, - 0.000000;-0.924838;-0.380361;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.422375;-0.906421;, - 0.000000;-0.422375;-0.906421;, - -0.321009;0.873103;-0.366938;, - -0.321009;0.873103;-0.366938;, - -0.851870;0.335310;-0.402349;, - -0.851870;0.335310;-0.402349;, - -0.851870;0.335310;-0.402349;, - 1.000000;0.000000;0.000000;, - 0.000000;0.657334;-0.753599;, - 0.000000;0.657334;-0.753599;, - -0.289072;-0.847857;0.444496;, - -0.289072;-0.847857;0.444496;, - -0.277574;-0.261929;0.924308;, - -0.277574;-0.261929;0.924308;, - -0.945889;-0.101973;0.308053;, - -0.945889;-0.101973;0.308053;, - -0.700118;-0.566886;0.434137;, - -0.700118;-0.566886;0.434137;, - -0.700118;-0.566886;0.434137;, - -0.700118;-0.566886;0.434137;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.425050;0.905170;, - 0.000000;-0.425050;0.905170;, - 1.000000;0.000000;0.000000;, - 0.000000;-0.956622;0.291332;, - 0.000000;-0.956622;0.291332;, - -1.000000;0.000001;0.000000;, - -1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - -0.257683;0.000000;0.966230;, - -0.294879;0.955535;0.000000;, - -0.464897;0.799763;0.379802;, - -0.461274;0.358979;0.811394;, - -0.793473;0.419778;0.440667;, - -0.793473;0.419778;0.440667;, - -0.793473;0.419778;0.440667;, - -0.707107;0.707106;0.000000;, - -0.707107;0.707106;0.000000;, - -0.707107;0.707106;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707106;0.000000;, - -0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.000000;1.000000;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -0.000000;-1.000000;0.000000;, - -0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000001;0.000000;, - 1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - -1.000000;0.000001;0.000000;, - -1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707106;0.000000;, - -0.707107;0.707106;0.000000;, - -0.707107;0.707106;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707106;0.000000;, - -0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.000000;1.000000;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -0.000000;-1.000000;0.000000;, - -0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000001;0.000000;, - 1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000001;0.000000;, - -1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707106;0.000000;, - -0.707107;0.707106;0.000000;, - -0.707107;0.707106;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707106;0.000000;, - -0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.000000;1.000000;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -0.000000;-1.000000;0.000000;, - -0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000001;0.000000;, - 1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;0.000000;1.000000;, - 0.223484;-0.878060;-0.423161;, - 0.223484;-0.878060;-0.423161;, - 0.267818;-0.029603;-0.963015;, - 0.267818;-0.029603;-0.963015;, - 0.831748;-0.535907;-0.144912;, - 0.831748;-0.535907;-0.144912;, - 0.831748;-0.535907;-0.144912;, - 0.823105;-0.251757;-0.509035;, - 0.823105;-0.251757;-0.509035;, - 0.823105;-0.251757;-0.509035;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.924838;-0.380361;, - 0.000000;-0.924838;-0.380361;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.422375;-0.906421;, - 0.000000;-0.422375;-0.906421;, - 0.321009;0.873103;-0.366938;, - 0.321009;0.873103;-0.366938;, - 0.851870;0.335310;-0.402349;, - 0.851870;0.335310;-0.402349;, - 0.851870;0.335310;-0.402349;, - -1.000000;0.000000;0.000000;, - 0.000000;0.657334;-0.753599;, - 0.000000;0.657334;-0.753599;, - 0.289072;-0.847857;0.444496;, - 0.289072;-0.847857;0.444496;, - 0.277574;-0.261929;0.924308;, - 0.277574;-0.261929;0.924308;, - 0.945889;-0.101973;0.308053;, - 0.945889;-0.101973;0.308053;, - 0.700118;-0.566886;0.434137;, - 0.700118;-0.566886;0.434137;, - 0.700118;-0.566886;0.434137;, - 0.700118;-0.566886;0.434137;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.425050;0.905170;, - 0.000000;-0.425050;0.905170;, - -1.000000;0.000000;0.000000;, - 0.000000;-0.956622;0.291332;, - 0.000000;-0.956622;0.291332;, - 1.000000;0.000001;0.000000;, - 1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - 0.257683;0.000000;0.966230;, - 0.294879;0.955535;0.000000;, - 0.464897;0.799763;0.379802;, - 0.461274;0.358979;0.811394;, - 0.793473;0.419778;0.440667;, - 0.793473;0.419778;0.440667;, - 0.793473;0.419778;0.440667;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -1.000000;0.000001;0.000000;, - -1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707107;0.000000;, - -0.707107;0.707107;0.000000;, - -0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -1.000000;0.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 1.000000;0.000001;0.000000;, - 1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -1.000000;0.000001;0.000000;, - -1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707107;0.000000;, - -0.707107;0.707107;0.000000;, - -0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 1.000000;0.000001;0.000000;, - 1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.707107;0.707106;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;1.000000;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;-1.000000;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - -0.707106;-0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707106;-0.707107;0.000000;, - -1.000000;0.000001;0.000000;, - -1.000000;0.000001;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707107;0.000000;, - -0.707107;0.707107;0.000000;, - -0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - -0.707107;0.707107;0.000000;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.999619;0.027602;, - 0.000000;0.803358;-0.595497;, - -0.038545;0.132170;-0.990477;, - 0.000000;0.123112;-0.992393;, - 0.038545;0.132170;-0.990477;, - 0.000000;-0.999666;0.025839;, - 0.000000;-0.999215;0.039615;, - 0.000000;0.000000;1.000000;, - 0.000000;-0.998478;0.055145;, - 0.000000;0.949568;-0.313562;, - 0.000000;0.963882;0.266329;, - 0.000000;0.493245;0.869891;, - 0.000000;0.493245;0.869891;; - 4816; - 3;5614,5579,5576;, - 3;1063,1747,1729;, - 3;1068,1035,1038;, - 3;1064,1705,1041;, - 3;1074,1152,1162;, - 3;1045,1042,1154;, - 3;1042,1745,1154;, - 3;1069,1046,1066;, - 3;1039,1042,1045;, - 3;1071,1043,1036;, - 3;1070,1063,1072;, - 3;1066,1044,1074;, - 3;1066,1162,1158;, - 3;1163,1155,1159;, - 3;1046,1152,1044;, - 3;1746,1160,1156;, - 3;1047,0,1;, - 3;740,2279,1047;, - 3;2,1936,740;, - 3;446,764,447;, - 3;762,5,765;, - 3;446,6,7;, - 3;420,737,422;, - 3;1958,1959,1961;, - 3;425,193,9;, - 3;426,766,194;, - 3;1917,737,736;, - 3;1962,766,739;, - 3;421,427,425;, - 3;738,426,423;, - 3;738,1962,739;, - 3;1918,1961,1919;, - 3;1075,1749,1751;, - 3;90,195,234;, - 3;90,234,92;, - 3;196,94,198;, - 3;91,96,95;, - 3;767,463,465;, - 3;466,468,470;, - 3;93,97,96;, - 3;470,478,472;, - 3;467,448,768;, - 3;237,195,448;, - 3;471,237,467;, - 3;238,234,237;, - 3;471,239,238;, - 3;238,235,92;, - 3;770,449,450;, - 3;199,449,197;, - 3;478,240,472;, - 3;241,236,240;, - 3;452,201,454;, - 3;202,454,201;, - 3;242,201,452;, - 3;84,201,204;, - 3;242,99,204;, - 3;204,99,84;, - 3;455,459,453;, - 3;456,205,457;, - 3;452,243,242;, - 3;202,86,206;, - 3;99,243,100;, - 3;84,100,87;, - 3;178,244,209;, - 3;180,227,184;, - 3;229,248,231;, - 3;245,214,249;, - 3;211,189,215;, - 3;185,187,181;, - 3;192,222,178;, - 3;228,229,231;, - 3;210,190,179;, - 3;209,250,216;, - 3;244,232,251;, - 3;178,186,192;, - 3;233,232,222;, - 3;192,227,233;, - 3;774,1048,741;, - 3;743,223,182;, - 3;1053,246,230;, - 3;1079,212,245;, - 3;777,188,213;, - 3;744,188,746;, - 3;224,1053,230;, - 3;747,1048,1054;, - 3;775,746,777;, - 3;1076,1053,1049;, - 3;776,1079,1077;, - 3;748,1050,745;, - 3;1055,1053,1051;, - 3;742,744,746;, - 3;72,163,166;, - 3;61,385,63;, - 3;65,137,61;, - 3;386,76,63;, - 3;431,73,77;, - 3;144,169,172;, - 3;173,434,10;, - 3;146,435,170;, - 3;145,389,147;, - 3;391,1922,436;, - 3;1874,394,1877;, - 3;1923,1878,1925;, - 3;1881,1926,1879;, - 3;1924,439,437;, - 3;1929,440,1927;, - 3;438,395,392;, - 3;442,395,441;, - 3;12,151,154;, - 3;400,1880,396;, - 3;13,1879,1882;, - 3;155,397,398;, - 3;149,396,152;, - 3;2214,2315,2318;, - 3;2218,2214,2318;, - 3;2214,1755,2215;, - 3;1758,2215,1755;, - 3;2218,1753,2214;, - 3;1164,1755,1167;, - 3;1760,6191,1754;, - 3;1765,6191,1763;, - 3;2219,1764,1761;, - 3;2223,1764,2222;, - 3;2319,2321,2323;, - 3;2327,2324,2321;, - 3;2224,2322,2226;, - 3;2316,2226,2322;, - 3;1754,1767,1756;, - 3;6192,1767,6191;, - 3;2329,2222,2325;, - 3;2219,2326,2222;, - 3;1770,2230,1772;, - 3;2220,1773,2231;, - 3;2216,2231,2227;, - 3;2229,2228,2230;, - 3;1168,1172,1165;, - 3;1757,1170,1169;, - 3;1759,1173,1773;, - 3;1767,1771,1774;, - 3;479,485,489;, - 3;1775,1176,1777;, - 3;2232,1777,2234;, - 3;1176,1178,1180;, - 3;479,1180,1178;, - 3;1182,1779,1780;, - 3;1184,1779,1183;, - 3;1780,2236,14;, - 3;1781,2236,1779;, - 3;15,1783,1784;, - 3;2240,1783,2239;, - 3;491,495,496;, - 3;495,497,500;, - 3;502,505,506;, - 3;508,506,505;, - 3;513,515,517;, - 3;514,519,515;, - 3;486,521,524;, - 3;527,519,518;, - 3;1186,495,500;, - 3;1189,495,1188;, - 3;1189,1183,1182;, - 3;1186,1183,1188;, - 3;1190,1193,1194;, - 3;1196,1193,1192;, - 3;1196,505,504;, - 3;1190,505,1192;, - 3;1197,1783,1193;, - 3;1785,1193,1783;, - 3;513,493,492;, - 3;520,522,516;, - 3;503,528,527;, - 3;1179,501,480;, - 3;480,498,481;, - 3;482,493,523;, - 3;523,517,515;, - 3;1174,1187,1179;, - 3;1776,1185,1174;, - 3;2233,1782,1776;, - 3;1181,1195,1177;, - 3;1177,1786,1778;, - 3;1778,2241,2235;, - 3;490,1191,1181;, - 3;487,509,490;, - 3;525,510,488;, - 3;519,507,525;, - 3;1198,1789,1200;, - 3;1787,1794,1790;, - 3;1204,1795,1792;, - 3;1210,1212,1213;, - 3;1201,1796,1206;, - 3;1199,1211,1210;, - 3;1199,1213,1205;, - 3;1213,1207,1205;, - 3;1202,1212,1211;, - 3;1214,2244,1216;, - 3;1214,1220,1223;, - 3;1221,1228,1224;, - 3;2245,1230,1217;, - 3;2242,1232,2247;, - 3;1217,2246,1230;, - 3;2242,1232,2247;, - 3;1215,1229,1232;, - 3;1231,1222,1218;, - 3;2248,2333,16;, - 3;2331,17,2334;, - 3;2249,2335,2331;, - 3;78,68,64;, - 3;82,167,174;, - 3;164,175,168;, - 3;428,176,165;, - 3;387,445,432;, - 3;401,138,156;, - 3;156,141,157;, - 3;158,66,69;, - 3;62,70,67;, - 3;64,71,62;, - 3;74,80,79;, - 3;432,444,428;, - 3;1081,19,20;, - 3;21,1082,1081;, - 3;2108,1797,1749;, - 3;24,1751,1799;, - 3;469,529,478;, - 3;771,476,463;, - 3;94,218,198;, - 3;96,102,95;, - 3;241,529,252;, - 3;458,25,459;, - 3;207,461,458;, - 3;88,220,208;, - 3;101,89,88;, - 3;464,474,468;, - 3;97,104,96;, - 3;241,105,98;, - 3;1750,1800,1752;, - 3;451,219,462;, - 3;451,779,772;, - 3;1963,1967,1968;, - 3;1968,2109,2110;, - 3;2111,2109,2113;, - 3;1964,2114,1965;, - 3;1937,1968,1939;, - 3;1939,2110,2081;, - 3;2081,2111,2082;, - 3;1938,2112,1964;, - 3;1884,2256,2257;, - 3;1931,2263,1934;, - 3;1932,2258,2261;, - 3;1889,1885,2259;, - 3;2263,2260,2256;, - 3;1935,1890,1933;, - 3;159,1889,161;, - 3;27,1891,1892;, - 3;28,1886,160;, - 3;1552,1554,1557;, - 3;916,1626,1554;, - 3;980,1631,1626;, - 3;1558,1560,1553;, - 3;1555,1559,1558;, - 3;1627,1561,1556;, - 3;1632,1633,1628;, - 3;1632,1636,1635;, - 3;1629,983,1636;, - 3;981,919,984;, - 3;917,1560,920;, - 3;1563,1567,921;, - 3;921,1637,985;, - 3;985,1640,1642;, - 3;1565,1560,1559;, - 3;1568,1559,1562;, - 3;1638,1561,1634;, - 3;1641,1633,1635;, - 3;1641,1636,1643;, - 3;1643,983,986;, - 3;987,919,922;, - 3;923,1560,1564;, - 3;1570,1575,1577;, - 3;1580,1575,1573;, - 3;1578,1588,1571;, - 3;1583,924,926;, - 3;1446,1452,1454;, - 3;1456,1452,1459;, - 3;1449,1590,1592;, - 3;1460,930,1457;, - 3;925,1591,931;, - 3;1588,1592,1590;, - 3;1586,928,1593;, - 3;926,930,929;, - 3;852,793,796;, - 3;1341,1981,1984;, - 3;2013,1462,1464;, - 3;876,880,882;, - 3;880,1469,1472;, - 3;794,1436,1348;, - 3;1351,795,1349;, - 3;877,1470,1467;, - 3;1471,1481,1473;, - 3;2017,1478,1462;, - 3;1439,1982,1345;, - 3;1437,1346,1350;, - 3;1350,1342,1352;, - 3;1483,1463,1479;, - 3;1474,1480,1471;, - 3;884,887,889;, - 3;2018,2022,2024;, - 3;1487,886,885;, - 3;1488,1494,1489;, - 3;2025,1495,1492;, - 3;852,886,854;, - 3;2020,1983,2022;, - 3;1490,1497,886;, - 3;855,1497,1436;, - 3;1496,1498,1491;, - 3;1438,1499,1440;, - 3;2023,1500,1495;, - 3;1439,2023,1982;, - 3;882,884,889;, - 3;880,1487,885;, - 3;1473,1493,1488;, - 3;1482,2025,1492;, - 3;2017,2018,2024;, - 3;856,804,858;, - 3;1355,1992,1359;, - 3;2026,1504,2029;, - 3;891,897,1506;, - 3;897,1510,1506;, - 3;805,1442,859;, - 3;1365,806,800;, - 3;892,1511,1513;, - 3;1512,1517,1519;, - 3;2029,1520,1518;, - 3;1444,1360,1993;, - 3;1443,1361,1445;, - 3;1362,1356,1361;, - 3;1522,1505,1501;, - 3;1514,1519,1523;, - 3;899,903,905;, - 3;2030,2034,2036;, - 3;1526,905,1528;, - 3;1527,1531,1534;, - 3;2032,1532,2035;, - 3;856,905,903;, - 3;2036,1994,1988;, - 3;1528,905,1536;, - 3;859,1536,905;, - 3;1533,1537,1539;, - 3;1443,1540,1538;, - 3;2035,1532,1541;, - 3;1444,2035,1541;, - 3;895,899,898;, - 3;897,1526,1508;, - 3;1509,1534,1517;, - 3;1518,2032,2029;, - 3;2029,2030,2026;, - 3;904,890,888;, - 3;901,883,890;, - 3;896,878,883;, - 3;893,1475,879;, - 3;1515,1484,1476;, - 3;1524,1465,1485;, - 3;1502,2014,1465;, - 3;2027,2019,2015;, - 3;2031,2021,2019;, - 3;2037,1985,2021;, - 3;1989,1343,1986;, - 3;1357,1353,1344;, - 3;1366,797,1354;, - 3;801,853,798;, - 3;857,888,853;, - 3;1138,1133,1142;, - 3;1009,988,990;, - 3;1009,1018,1012;, - 3;1139,1144,1145;, - 3;993,988,996;, - 3;999,1148,1021;, - 3;1022,999,1021;, - 3;1144,1027,1145;, - 3;1019,1027,1024;, - 3;1119,932,934;, - 3;937,934,932;, - 3;1148,1029,1021;, - 3;1021,1031,1022;, - 3;1033,989,1013;, - 3;1033,1020,1025;, - 3;1120,1126,1121;, - 3;1133,1126,1125;, - 3;939,941,945;, - 3;994,946,942;, - 3;948,1004,1005;, - 3;1000,1005,1004;, - 3;950,940,947;, - 3;997,950,947;, - 3;999,1136,1134;, - 3;951,1136,1008;, - 3;951,1004,948;, - 3;999,1004,1008;, - 3;940,953,935;, - 3;989,953,950;, - 3;1149,1131,1140;, - 3;1023,991,1001;, - 3;1030,1146,1028;, - 3;1150,1141,1147;, - 3;1022,1014,1010;, - 3;1032,1028,1015;, - 3;1006,938,949;, - 3;1007,943,1005;, - 3;1007,992,995;, - 3;1135,1127,1131;, - 3;1129,1128,1136;, - 3;952,1122,1130;, - 3;949,933,952;, - 3;1267,1288,1289;, - 3;711,1290,718;, - 3;589,718,641;, - 3;592,642,643;, - 3;594,643,644;, - 3;597,645,646;, - 3;1272,646,1291;, - 3;1270,1292,1288;, - 3;1273,1271,599;, - 3;598,1273,599;, - 3;598,599,595;, - 3;595,599,593;, - 3;593,599,590;, - 3;590,599,712;, - 3;1268,712,599;, - 3;1271,1268,599;, - 3;1320,735,402;, - 3;735,404,402;, - 3;1320,1904,735;, - 3;1320,1862,1904;, - 3;735,1906,404;, - 3;735,1904,1906;, - 3;358,402,129;, - 3;358,1320,402;, - 3;129,402,407;, - 3;369,359,130;, - 3;369,130,132;, - 3;1321,1867,1863;, - 3;1325,1867,1321;, - 3;1864,1909,1905;, - 3;1868,1909,1864;, - 3;1905,1910,1907;, - 3;1909,1910,1905;, - 3;405,1908,1911;, - 3;409,405,1911;, - 3;403,406,410;, - 3;411,403,410;, - 3;131,408,412;, - 3;133,131,412;, - 3;360,1325,1321;, - 3;370,1325,360;, - 3;412,408,403;, - 3;412,403,411;, - 3;1293,1869,1275;, - 3;1275,1869,1865;, - 3;647,600,371;, - 3;600,361,371;, - 3;648,372,1294;, - 3;1294,372,1870;, - 3;649,1295,601;, - 3;601,1295,1276;, - 3;602,1277,362;, - 3;1277,1866,362;, - 3;304,318,334;, - 3;373,365,374;, - 3;293,322,319;, - 3;304,295,294;, - 3;374,367,375;, - 3;296,603,322;, - 3;305,561,297;, - 3;573,604,562;, - 3;335,374,336;, - 3;320,366,363;, - 3;335,364,373;, - 3;336,375,650;, - 3;650,367,605;, - 3;323,368,366;, - 3;564,298,301;, - 3;302,324,327;, - 3;565,303,570;, - 3;303,607,570;, - 3;328,587,608;, - 3;299,588,325;, - 3;299,567,560;, - 3;565,570,1825;, - 3;570,1842,1825;, - 3;608,1845,1843;, - 3;560,1846,588;, - 3;560,567,1828;, - 3;566,1829,568;, - 3;1826,1847,1830;, - 3;1233,1247,1249;, - 3;1238,1249,1250;, - 3;1238,1810,1801;, - 3;1240,1812,1251;, - 3;1244,1234,1239;, - 3;1241,1235,1244;, - 3;1244,1802,1804;, - 3;1242,1244,1804;, - 3;1236,1251,1248;, - 3;1803,1813,1805;, - 3;107,253,255;, - 3;253,532,255;, - 3;254,110,257;, - 3;116,257,110;, - 3;535,260,538;, - 3;30,538,260;, - 3;533,540,541;, - 3;545,541,540;, - 3;534,261,256;, - 3;546,261,542;, - 3;256,111,108;, - 3;271,111,261;, - 3;539,530,536;, - 3;258,531,253;, - 3;543,540,539;, - 3;53,112,48;, - 3;53,50,54;, - 3;55,114,119;, - 3;118,262,112;, - 3;119,265,274;, - 3;272,266,263;, - 3;49,115,51;, - 3;113,267,115;, - 3;1594,1542,1544;, - 3;1595,958,1597;, - 3;1598,906,1543;, - 3;1596,908,955;, - 3;956,907,959;, - 3;2038,1600,1603;, - 3;2038,1603,1606;, - 3;2038,1606,1609;, - 3;1609,1644,2038;, - 3;1644,1647,2038;, - 3;1647,1600,2038;, - 3;961,962,965;, - 3;961,968,962;, - 3;961,971,968;, - 3;971,961,974;, - 3;974,961,977;, - 3;977,961,965;, - 3;963,1607,1604;, - 3;969,1610,1608;, - 3;972,1645,1611;, - 3;975,1648,1646;, - 3;978,1601,1649;, - 3;966,1605,1602;, - 3;1546,1995,1998;, - 3;1547,913,1549;, - 3;1550,860,1996;, - 3;1999,861,863;, - 3;1548,864,910;, - 3;911,862,914;, - 3;1089,1095,1097;, - 3;1099,2152,2155;, - 3;729,1896,732;, - 3;2158,2162,2165;, - 3;1894,1901,1896;, - 3;1105,866,868;, - 3;870,868,866;, - 3;1100,867,1107;, - 3;874,871,867;, - 3;1102,869,875;, - 3;869,872,875;, - 3;2156,874,1100;, - 3;2002,874,2001;, - 3;2153,875,2003;, - 3;872,2003,875;, - 3;2168,2001,2156;, - 3;2007,2001,2005;, - 3;2170,2003,2009;, - 3;2004,2009,2003;, - 3;2171,2006,2169;, - 3;2011,2006,2010;, - 3;730,873,870;, - 3;733,2004,872;, - 3;731,2002,1895;, - 3;1897,2012,2004;, - 3;1898,2011,1902;, - 3;1895,2007,1899;, - 3;1107,1111,1100;, - 3;1101,1114,1103;, - 3;1106,1115,1117;, - 3;1108,1118,1109;, - 3;2156,2175,2168;, - 3;2169,2177,2171;, - 3;2153,2178,2179;, - 3;2157,2180,2172;, - 3;1110,1098,1111;, - 3;1117,1096,1092;, - 3;1109,1093,1090;, - 3;2173,2166,2175;, - 3;2176,2163,2177;, - 3;2179,2164,2160;, - 3;1112,2181,1116;, - 3;1115,2160,1096;, - 3;1097,2161,2158;, - 3;1111,2159,2173;, - 3;1369,807,810;, - 3;1374,1378,1381;, - 3;1382,1386,1375;, - 3;1371,1386,1384;, - 3;1379,1385,1383;, - 3;808,1385,812;, - 3;1387,1393,814;, - 3;1395,814,1393;, - 3;1380,819,813;, - 3;811,813,819;, - 3;815,1376,1388;, - 3;1394,1375,1386;, - 3;1389,1374,1390;, - 3;1396,1386,1370;, - 3;816,819,815;, - 3;1397,810,817;, - 3;1398,823,1401;, - 3;1399,1404,1407;, - 3;1402,826,1405;, - 3;820,827,824;, - 3;1400,1410,821;, - 3;1408,828,1411;, - 3;1413,832,1416;, - 3;1414,1419,1422;, - 3;1417,835,1420;, - 3;829,836,833;, - 3;1415,838,830;, - 3;1423,837,839;, - 3;1425,844,1428;, - 3;1426,1430,1433;, - 3;1428,846,1431;, - 3;841,847,845;, - 3;1427,849,842;, - 3;1434,848,850;, - 3;927,1586,1584;, - 3;1576,1586,1579;, - 3;1584,1586,1576;, - 3;925,1581,1589;, - 3;1581,1574,1589;, - 3;1574,1572,1589;, - 3;928,1450,1593;, - 3;928,1461,1453;, - 3;928,1453,1450;, - 3;931,1591,1458;, - 3;1455,1591,1447;, - 3;1458,1591,1455;, - 3;1670,1674,1676;, - 3;1650,1676,1653;, - 3;1656,1654,1659;, - 3;1678,1660,1680;, - 3;1678,1682,1684;, - 3;1707,1713,1716;, - 3;1717,1686,1688;, - 3;1690,1672,1671;, - 3;1690,1671,1651;, - 3;1690,1651,1657;, - 3;1690,1657,1679;, - 3;1679,1685,1690;, - 3;1685,1719,1690;, - 3;1719,1723,1690;, - 3;1723,1672,1690;, - 3;1691,1675,1724;, - 3;1691,1724,1725;, - 3;1691,1725,1683;, - 3;1691,1683,1681;, - 3;1681,1661,1691;, - 3;1661,1655,1691;, - 3;1655,1677,1691;, - 3;1677,1675,1691;, - 3;1708,1726,1710;, - 3;1711,1724,1714;, - 3;1709,1723,1719;, - 3;1714,1675,1687;, - 3;1688,1674,1673;, - 3;1718,1672,1723;, - 3;2264,2280,2281;, - 3;2266,2285,2280;, - 3;2264,2287,2269;, - 3;2271,2274,2276;, - 3;2277,2289,2290;, - 3;2290,2292,2294;, - 3;2295,2298,2299;, - 3;2299,2301,2302;, - 3;2084,1940,1942;, - 3;2273,1943,1941;, - 3;2302,2088,2085;, - 3;2265,2276,2267;, - 3;2282,2300,2303;, - 3;2268,2291,2283;, - 3;2283,2296,2286;, - 3;2285,2300,2280;, - 3;2287,2303,2086;, - 3;2270,2087,1944;, - 3;2264,1945,2272;, - 3;571,1278,609;, - 3;268,1266,571;, - 3;1266,1848,1278;, - 3;1245,1831,1266;, - 3;610,575,572;, - 3;1279,652,611;, - 3;1849,1296,1279;, - 3;1832,1851,1850;, - 3;1807,1833,1832;, - 3;1246,1814,1808;, - 3;1252,269,276;, - 3;277,572,575;, - 3;612,715,615;, - 3;612,1322,713;, - 3;618,1282,1285;, - 3;618,626,621;, - 3;1285,612,618;, - 3;629,635,638;, - 3;330,639,332;, - 3;623,632,630;, - 3;619,636,633;, - 3;616,637,613;, - 3;616,333,640;, - 3;623,630,331;, - 3;714,720,716;, - 3;1280,1326,1323;, - 3;717,654,617;, - 3;622,656,658;, - 3;1283,1300,1286;, - 3;624,657,627;, - 3;332,340,330;, - 3;1287,1297,1280;, - 3;1324,719,714;, - 3;622,1298,1284;, - 3;331,659,623;, - 3;616,338,333;, - 3;1712,1720,1707;, - 3;1727,1684,1682;, - 3;2115,2120,2122;, - 3;2122,2341,2344;, - 3;2348,2399,2401;, - 3;2124,2338,2126;, - 3;2336,2407,2338;, - 3;2400,2405,2402;, - 3;2304,2345,2354;, - 3;2339,2406,2337;, - 3;2127,2123,2304;, - 3;2128,2337,2125;, - 3;2357,2403,2410;, - 3;2408,2404,2406;, - 3;2306,2118,2129;, - 3;2121,2358,2342;, - 3;2308,2409,2340;, - 3;2305,2360,2308;, - 3;2340,2131,2308;, - 3;2308,2127,2305;, - 3;2346,2350,2348;, - 3;2342,2358,2351;, - 3;2409,2357,2410;, - 3;2355,2357,2360;, - 3;2125,2132,2128;, - 3;2127,2133,2116;, - 3;2347,2357,2356;, - 3;6189,2307,2130;, - 3;6190,2338,6198;, - 3;6198,2407,6199;, - 3;6194,2359,2307;, - 3;6199,2400,6200;, - 3;6196,2399,2352;, - 3;6195,2353,2359;, - 3;2361,2366,2369;, - 3;2362,2371,2363;, - 3;2364,2373,2367;, - 3;2370,2374,32;, - 3;2375,2378,2380;, - 3;2376,2381,2383;, - 3;2309,2380,33;, - 3;2310,2375,2309;, - 3;2386,2384,2382;, - 3;2391,2393,2395;, - 3;2391,2388,2387;, - 3;2312,2382,2311;, - 3;2314,2392,2391;, - 3;2314,2387,2313;, - 3;2385,2379,2377;, - 3;2398,2396,2394;, - 3;2398,2385,2389;, - 3;934,1731,1119;, - 3;1120,1733,1125;, - 3;1125,1737,1133;, - 3;1133,1739,1142;, - 3;1143,1741,1144;, - 3;1144,1692,1024;, - 3;1694,1026,1693;, - 3;1002,1694,1662;, - 3;954,1662,1614;, - 3;936,1614,1612;, - 3;2197,1738,2191;, - 3;2065,1663,1695;, - 3;2065,1697,2068;, - 3;2198,1744,1742;, - 3;2054,1663,2051;, - 3;2057,2204,2193;, - 3;2073,2057,2058;, - 3;1744,2075,1700;, - 3;1698,2075,2069;, - 3;1734,2039,2182;, - 3;2041,1615,1618;, - 3;2204,2077,2206;, - 3;2072,2079,2077;, - 3;1703,1664,1668;, - 3;1703,1699,1696;, - 3;1735,2186,1736;, - 3;1738,2186,2191;, - 3;1618,2043,2041;, - 3;2055,1620,1665;, - 3;2047,2060,2062;, - 3;2058,2060,2063;, - 3;1623,1621,1619;, - 3;1666,1623,1664;, - 3;2057,2195,2064;, - 3;2049,2195,2189;, - 3;2049,2062,2064;, - 3;2057,2062,2058;, - 3;1619,1624,1623;, - 3;1664,1624,1668;, - 3;2205,2192,2194;, - 3;2074,2052,2066;, - 3;2078,2201,2207;, - 3;2206,2199,2204;, - 3;2073,2070,2079;, - 3;2080,2076,2078;, - 3;2061,2042,2044;, - 3;2063,2045,2056;, - 3;2063,2053,2058;, - 3;2194,2187,2196;, - 3;2189,2188,2183;, - 3;2050,2184,2040;, - 3;2048,2040,2042;, - 3;1615,1731,1613;, - 3;1735,1733,1732;, - 3;1736,1737,1733;, - 3;1738,1739,1737;, - 3;1742,1741,1740;, - 3;1744,1692,1741;, - 3;1694,1701,1704;, - 3;1669,1694,1704;, - 3;1625,1662,1669;, - 3;1616,1614,1625;, - 3;2134,2250,2137;, - 3;2134,1747,2250;, - 3;2139,2093,2142;, - 3;2135,1705,1730;, - 3;2145,2208,2099;, - 3;2100,2210,2096;, - 3;2096,1745,1706;, - 3;2140,2101,2090;, - 3;2091,2096,2094;, - 3;2143,2097,2136;, - 3;2141,2134,2137;, - 3;2138,2099,2101;, - 3;2138,2254,2145;, - 3;2255,2211,2209;, - 3;2101,2208,2212;, - 3;1746,2251,1748;, - 3;781,784,788;, - 3;781,1339,784;, - 3;1083,1060,1086;, - 3;782,1333,1337;, - 3;790,753,755;, - 3;756,758,750;, - 3;750,1335,1334;, - 3;1084,757,1057;, - 3;1058,750,1061;, - 3;1087,751,783;, - 3;1085,781,788;, - 3;789,755,757;, - 3;789,791,790;, - 3;792,759,754;, - 3;757,753,760;, - 3;1336,785,1340;, - 3;1969,1972,1974;, - 3;1969,1339,1338;, - 3;2146,2102,2105;, - 3;1970,1333,1946;, - 3;1978,1950,1979;, - 3;1952,1947,1954;, - 3;1947,1335,1954;, - 3;2147,1953,1973;, - 3;2106,1947,1952;, - 3;2149,1948,2103;, - 3;2148,1969,2150;, - 3;1973,1949,1978;, - 3;1973,1979,1975;, - 3;1980,1955,1976;, - 3;1953,1950,1949;, - 3;1336,1977,1956;, - 3;1302,1288,1305;, - 3;722,1290,1303;, - 3;661,718,722;, - 3;664,642,662;, - 3;666,643,664;, - 3;669,645,667;, - 3;1307,646,669;, - 3;1305,1292,1308;, - 3;1309,35,1306;, - 3;670,35,1309;, - 3;670,668,35;, - 3;668,665,35;, - 3;665,663,35;, - 3;663,723,35;, - 3;1304,35,723;, - 3;1306,35,1304;, - 3;1328,413,36;, - 3;36,413,415;, - 3;1328,36,1912;, - 3;1328,1912,1871;, - 3;36,415,1914;, - 3;36,1914,1912;, - 3;376,134,413;, - 3;376,413,1328;, - 3;134,418,413;, - 3;369,135,377;, - 3;369,132,135;, - 3;1329,1872,1867;, - 3;1325,1329,1867;, - 3;1873,1913,1909;, - 3;1868,1873,1909;, - 3;1913,1915,1910;, - 3;1909,1913,1910;, - 3;416,1911,1916;, - 3;409,1911,416;, - 3;414,410,417;, - 3;411,410,414;, - 3;136,412,419;, - 3;133,412,136;, - 3;378,1329,1325;, - 3;370,378,1325;, - 3;412,414,419;, - 3;412,411,414;, - 3;304,342,307;, - 3;37,381,379;, - 3;308,346,309;, - 3;304,310,306;, - 3;38,383,381;, - 3;309,671,576;, - 3;305,577,574;, - 3;573,672,651;, - 3;335,38,37;, - 3;343,382,347;, - 3;335,379,344;, - 3;337,39,38;, - 3;650,383,39;, - 3;347,384,673;, - 3;579,315,584;, - 3;312,355,316;, - 3;580,40,313;, - 3;313,675,348;, - 3;349,709,356;, - 3;317,710,41;, - 3;317,41,585;, - 3;580,1834,40;, - 3;40,1853,675;, - 3;676,1859,709;, - 3;41,1860,1839;, - 3;41,1839,585;, - 3;581,1840,1835;, - 3;1836,1861,1854;, - 3;1253,1247,1255;, - 3;1258,1249,1253;, - 3;1258,1810,1250;, - 3;1260,1812,1819;, - 3;42,1254,1256;, - 3;1261,42,1256;, - 3;42,1816,1259;, - 3;1262,1820,42;, - 3;1257,1251,1263;, - 3;1817,1813,1811;, - 3;120,280,278;, - 3;278,550,548;, - 3;279,123,121;, - 3;116,43,29;, - 3;553,44,282;, - 3;30,556,544;, - 3;551,45,549;, - 3;545,558,547;, - 3;552,46,559;, - 3;546,46,271;, - 3;281,124,46;, - 3;271,124,117;, - 3;557,549,45;, - 3;283,548,554;, - 3;543,45,545;, - 3;53,125,118;, - 3;53,58,56;, - 3;55,127,59;, - 3;118,284,273;, - 3;119,287,127;, - 3;272,288,275;, - 3;57,128,126;, - 3;126,289,285;, - 3;582,1310,47;, - 3;290,47,1264;, - 3;47,1856,1837;, - 3;1264,1837,1822;, - 3;677,575,653;, - 3;1311,652,1296;, - 3;1857,1296,1852;, - 3;1838,1851,1833;, - 3;1823,1833,1815;, - 3;1265,1814,1252;, - 3;1252,291,1265;, - 3;277,583,292;, - 3;680,726,724;, - 3;680,1330,1312;, - 3;686,1314,689;, - 3;686,694,691;, - 3;1317,680,1312;, - 3;697,703,700;, - 3;351,706,698;, - 3;692,701,687;, - 3;688,704,681;, - 3;683,705,707;, - 3;683,707,353;, - 3;692,352,699;, - 3;725,720,719;, - 3;1313,1326,1297;, - 3;727,654,721;, - 3;690,656,695;, - 3;1315,1300,1299;, - 3;693,657,660;, - 3;354,340,339;, - 3;1318,1297,1301;, - 3;1331,719,1327;, - 3;690,1298,658;, - 3;352,659,341;, - 3;683,338,655;, - 3;2444,2452,2453;, - 3;2439,2454,2441;, - 3;2412,2441,2423;, - 3;2415,2424,2425;, - 3;2417,2425,2426;, - 3;2420,2427,2428;, - 3;2449,2428,2455;, - 3;2447,2456,2452;, - 3;2450,2448,2422;, - 3;2421,2450,2422;, - 3;2421,2422,2418;, - 3;2418,2422,2416;, - 3;2416,2422,2413;, - 3;2413,2422,2440;, - 3;2445,2440,2422;, - 3;2448,2445,2422;, - 3;2457,2452,2460;, - 3;2442,2454,2458;, - 3;2429,2441,2442;, - 3;2432,2424,2430;, - 3;2434,2425,2432;, - 3;2437,2427,2435;, - 3;2462,2428,2437;, - 3;2460,2456,2463;, - 3;2464,2411,2461;, - 3;2438,2411,2464;, - 3;2438,2436,2411;, - 3;2436,2433,2411;, - 3;2433,2431,2411;, - 3;2431,2443,2411;, - 3;2459,2411,2443;, - 3;2461,2411,2459;, - 3;2475,2480,2483;, - 3;2476,2485,2477;, - 3;2478,2487,2481;, - 3;2484,2488,2466;, - 3;2489,2492,2494;, - 3;2490,2495,2497;, - 3;2469,2494,2467;, - 3;2470,2489,2469;, - 3;2500,2498,2496;, - 3;2505,2507,2509;, - 3;2505,2502,2501;, - 3;2472,2496,2471;, - 3;2474,2506,2505;, - 3;2474,2501,2473;, - 3;2499,2493,2491;, - 3;2512,2510,2508;, - 3;2512,2499,2503;, - 3;2521,2533,2523;, - 3;2523,2538,2536;, - 3;2521,2540,2534;, - 3;2528,2274,2273;, - 3;2530,2289,2275;, - 3;2542,2292,2289;, - 3;2544,2298,2293;, - 3;2548,2301,2298;, - 3;2517,1940,2089;, - 3;2273,2513,2528;, - 3;2550,2088,2301;, - 3;2522,2531,2528;, - 3;2535,2549,2533;, - 3;2524,2543,2532;, - 3;2537,2545,2543;, - 3;2538,2549,2546;, - 3;2540,2551,2534;, - 3;2526,2518,2541;, - 3;2521,2514,2527;, - 3;2584,2555,2587;, - 3;2585,2590,2593;, - 3;2588,2558,2591;, - 3;2552,2559,2556;, - 3;2586,2596,2553;, - 3;2594,2560,2597;, - 3;2599,2564,2602;, - 3;2600,2605,2608;, - 3;2603,2567,2606;, - 3;2561,2568,2565;, - 3;2601,2570,2562;, - 3;2609,2569,2571;, - 3;2611,2576,2614;, - 3;2612,2616,2619;, - 3;2614,2578,2617;, - 3;2573,2579,2577;, - 3;2613,2581,2574;, - 3;2620,2580,2582;, - 3;2654,2625,2657;, - 3;2655,2660,2663;, - 3;2658,2628,2661;, - 3;2622,2629,2626;, - 3;2656,2666,2623;, - 3;2664,2630,2667;, - 3;2669,2634,2672;, - 3;2670,2675,2678;, - 3;2673,2637,2676;, - 3;2631,2638,2635;, - 3;2671,2640,2632;, - 3;2679,2639,2641;, - 3;2681,2646,2684;, - 3;2682,2686,2689;, - 3;2684,2648,2687;, - 3;2643,2649,2647;, - 3;2683,2651,2644;, - 3;2690,2650,2652;, - 3;2724,2695,2727;, - 3;2725,2730,2733;, - 3;2728,2698,2731;, - 3;2692,2699,2696;, - 3;2726,2736,2693;, - 3;2734,2700,2737;, - 3;2739,2704,2742;, - 3;2740,2745,2748;, - 3;2743,2707,2746;, - 3;2701,2708,2705;, - 3;2741,2710,2702;, - 3;2749,2709,2711;, - 3;2751,2716,2754;, - 3;2752,2756,2759;, - 3;2754,2718,2757;, - 3;2713,2719,2717;, - 3;2753,2721,2714;, - 3;2760,2720,2722;, - 3;2794,2765,2797;, - 3;2795,2800,2803;, - 3;2798,2768,2801;, - 3;2762,2769,2766;, - 3;2796,2806,2763;, - 3;2804,2770,2807;, - 3;2809,2774,2812;, - 3;2810,2815,2818;, - 3;2813,2777,2816;, - 3;2771,2778,2775;, - 3;2811,2780,2772;, - 3;2819,2779,2781;, - 3;2821,2786,2824;, - 3;2822,2826,2829;, - 3;2824,2788,2827;, - 3;2783,2789,2787;, - 3;2823,2791,2784;, - 3;2830,2790,2792;, - 3;2853,2858,2859;, - 3;2850,2860,2851;, - 3;2832,2851,2838;, - 3;2834,2839,2840;, - 3;2835,2840,2841;, - 3;2837,2842,2843;, - 3;2856,2843,2861;, - 3;2855,2862,2858;, - 3;2863,2858,2865;, - 3;2852,2860,2864;, - 3;2844,2851,2852;, - 3;2846,2839,2845;, - 3;2847,2840,2846;, - 3;2849,2842,2848;, - 3;2866,2843,2849;, - 3;2865,2862,2867;, - 3;2889,2894,2895;, - 3;2886,2896,2887;, - 3;2868,2887,2874;, - 3;2870,2875,2876;, - 3;2871,2876,2877;, - 3;2873,2878,2879;, - 3;2892,2879,2897;, - 3;2891,2898,2894;, - 3;2899,2894,2901;, - 3;2888,2896,2900;, - 3;2880,2887,2888;, - 3;2882,2875,2881;, - 3;2883,2876,2882;, - 3;2885,2878,2884;, - 3;2902,2879,2885;, - 3;2901,2898,2903;, - 3;2928,2933,2935;, - 3;2938,2933,2931;, - 3;2936,2946,2929;, - 3;2941,2904,2906;, - 3;2912,2918,2920;, - 3;2922,2918,2925;, - 3;2915,2948,2950;, - 3;2926,2910,2923;, - 3;2905,2949,2911;, - 3;2946,2950,2948;, - 3;2944,2908,2951;, - 3;2906,2910,2909;, - 3;2907,2944,2942;, - 3;2934,2944,2937;, - 3;2942,2944,2934;, - 3;2905,2939,2947;, - 3;2939,2932,2947;, - 3;2932,2930,2947;, - 3;2908,2916,2951;, - 3;2908,2927,2919;, - 3;2908,2919,2916;, - 3;2911,2949,2924;, - 3;2921,2949,2913;, - 3;2924,2949,2921;, - 3;2989,2971,2974;, - 3;2989,2974,2977;, - 3;2989,2977,2980;, - 3;2980,2983,2989;, - 3;2983,2986,2989;, - 3;2986,2971,2989;, - 3;2952,2953,2956;, - 3;2952,2959,2953;, - 3;2952,2962,2959;, - 3;2962,2952,2965;, - 3;2965,2952,2968;, - 3;2968,2952,2956;, - 3;2954,2978,2975;, - 3;2960,2981,2979;, - 3;2963,2984,2982;, - 3;2966,2987,2985;, - 3;2969,2972,2988;, - 3;2957,2976,2973;, - 3;3027,3009,3012;, - 3;3027,3012,3015;, - 3;3027,3015,3018;, - 3;3018,3021,3027;, - 3;3021,3024,3027;, - 3;3024,3009,3027;, - 3;2990,2991,2994;, - 3;2990,2997,2991;, - 3;2990,3000,2997;, - 3;3000,2990,3003;, - 3;3003,2990,3006;, - 3;3006,2990,2994;, - 3;2992,3016,3013;, - 3;2998,3019,3017;, - 3;3001,3022,3020;, - 3;3004,3025,3023;, - 3;3007,3010,3026;, - 3;2995,3014,3011;, - 3;4008,4102,4011;, - 3;4008,4680,4102;, - 3;4013,3980,4016;, - 3;4009,4638,4662;, - 3;4019,4096,3989;, - 3;3990,4098,3986;, - 3;3986,4678,4639;, - 3;4014,3991,3983;, - 3;3984,3986,3981;, - 3;4017,3987,4010;, - 3;4015,4008,4011;, - 3;4012,3989,3991;, - 3;4012,4106,4019;, - 3;4107,4099,4097;, - 3;3991,4096,4100;, - 3;4679,4103,4681;, - 3;3992,3028,5175;, - 3;3689,5175,4847;, - 3;3030,4847,3031;, - 3;446,3711,763;, - 3;762,3032,4;, - 3;446,3033,3414;, - 3;420,3686,736;, - 3;1958,4869,8;, - 3;425,3176,3398;, - 3;3399,3713,3688;, - 3;1917,3686,4834;, - 3;4871,3713,4870;, - 3;421,3398,3395;, - 3;3687,3399,3688;, - 3;3687,4871,4835;, - 3;1918,4872,1958;, - 3;4020,4682,5015;, - 3;3087,3213,3178;, - 3;3087,3089,3213;, - 3;3179,3091,3088;, - 3;3088,3093,3090;, - 3;3714,3428,3717;, - 3;3430,3433,3429;, - 3;3090,3094,3214;, - 3;3435,3439,3434;, - 3;3431,3415,3216;, - 3;3216,3178,3213;, - 3;3436,3216,3217;, - 3;3217,3213,3089;, - 3;3436,3218,3437;, - 3;3217,3215,3218;, - 3;3718,3416,3715;, - 3;3181,3416,3417;, - 3;3439,3219,3220;, - 3;3220,3214,3095;, - 3;3419,3421,3184;, - 3;3185,3184,3421;, - 3;3221,3184,3187;, - 3;3082,3184,3185;, - 3;3221,3187,3096;, - 3;3187,3082,3096;, - 3;3422,3426,3424;, - 3;3423,3188,3186;, - 3;3419,3222,3427;, - 3;3185,3084,3083;, - 3;3096,3222,3221;, - 3;3082,3097,3096;, - 3;3161,3223,3201;, - 3;3163,3206,3202;, - 3;3208,3227,3224;, - 3;3225,3197,3194;, - 3;3195,3172,3170;, - 3;3167,3170,3172;, - 3;3175,3201,3212;, - 3;3207,3208,3203;, - 3;3192,3173,3198;, - 3;3193,3228,3223;, - 3;3223,3210,3201;, - 3;3161,3168,3174;, - 3;3212,3210,3206;, - 3;3175,3206,3168;, - 3;3721,3993,4021;, - 3;3692,3204,3995;, - 3;3998,3226,4024;, - 3;4025,3194,3724;, - 3;3725,3171,3695;, - 3;3693,3171,3164;, - 3;3205,3998,3996;, - 3;3696,3993,3690;, - 3;3722,3695,3691;, - 3;4022,3998,4024;, - 3;3723,4025,3724;, - 3;3697,3997,3999;, - 3;4000,3998,3994;, - 3;3691,3693,3698;, - 3;3074,3150,3400;, - 3;3067,3363,3129;, - 3;3071,3130,3133;, - 3;3364,3078,3403;, - 3;3404,3075,3401;, - 3;3136,3156,3138;, - 3;3159,3406,3157;, - 3;3139,3407,3367;, - 3;3137,3368,3035;, - 3;3369,4837,4796;, - 3;4797,3372,3370;, - 3;4838,4799,4798;, - 3;1881,4840,1930;, - 3;4839,3411,4841;, - 3;1929,3412,443;, - 3;3408,3373,3413;, - 3;442,3373,399;, - 3;12,3143,3141;, - 3;3376,4800,4803;, - 3;13,4801,1881;, - 3;155,3374,3144;, - 3;3142,3375,3376;, - 3;5118,5211,5119;, - 3;5122,5214,5118;, - 3;5118,4688,4686;, - 3;4691,5119,5124;, - 3;5122,4686,4693;, - 3;4108,4688,4691;, - 3;4694,6193,4696;, - 3;1765,6193,6192;, - 3;5123,4697,5126;, - 3;2223,4697,1766;, - 3;5215,5217,5212;, - 3;2327,5219,2330;, - 3;2224,5218,2328;, - 3;5213,5127,5120;, - 3;4687,4698,6193;, - 3;6192,4698,1769;, - 3;2329,5126,2223;, - 3;5123,5220,5216;, - 3;1770,5130,2229;, - 3;5125,4700,4692;, - 3;5121,5131,5125;, - 3;2229,5128,2225;, - 3;4111,4116,4114;, - 3;4689,4115,4699;, - 3;4692,4117,4109;, - 3;4698,1771,1769;, - 3;3440,3446,3442;, - 3;4703,4120,4118;, - 3;5132,4705,4703;, - 3;4120,4122,4118;, - 3;3440,4124,3450;, - 3;1182,4707,4126;, - 3;4127,4707,4708;, - 3;1780,5136,4707;, - 3;4708,5136,5137;, - 3;15,4710,5139;, - 3;5140,4710,4711;, - 3;491,3454,3452;, - 3;3454,3455,3452;, - 3;502,3460,504;, - 3;3463,3461,3465;, - 3;513,3468,514;, - 3;514,3471,518;, - 3;3447,3473,3443;, - 3;527,3471,3479;, - 3;4129,3454,4131;, - 3;1189,3454,496;, - 3;1189,4126,4131;, - 3;4129,4126,4127;, - 3;4132,4135,4134;, - 3;1196,4135,1197;, - 3;1196,3460,4134;, - 3;4132,3460,3463;, - 3;1197,4710,1784;, - 3;4711,4135,4136;, - 3;513,3453,3470;, - 3;3472,3474,3476;, - 3;503,3479,3462;, - 3;4123,3458,4130;, - 3;3441,3456,3458;, - 3;3444,3453,3457;, - 3;3475,3470,3453;, - 3;4119,4130,4128;, - 3;4704,4128,4709;, - 3;5133,4709,5138;, - 3;4125,4137,4133;, - 3;4121,4712,4137;, - 3;4706,5141,4712;, - 3;3451,4133,3464;, - 3;3448,3464,3466;, - 3;3477,3467,3462;, - 3;3471,3462,3479;, - 3;4138,4715,4713;, - 3;4714,4720,4718;, - 3;4144,4721,4146;, - 3;4150,4152,4151;, - 3;4140,4722,4716;, - 3;4139,4151,4141;, - 3;4139,4153,4150;, - 3;4153,4147,4152;, - 3;4142,4152,4148;, - 3;4154,5144,5142;, - 3;4154,4160,4156;, - 3;4161,1228,1226;, - 3;5145,1230,2246;, - 3;5143,1232,4155;, - 3;4157,2246,5145;, - 3;5143,1232,4155;, - 3;4155,1229,4163;, - 3;1231,4162,1227;, - 3;5146,5225,5223;, - 3;5224,17,2335;, - 3;5147,2335,18;, - 3;3079,68,81;, - 3;82,3153,3076;, - 3;3151,175,177;, - 3;3402,176,444;, - 3;3365,445,401;, - 3;401,3131,3366;, - 3;156,3134,3132;, - 3;158,3072,3135;, - 3;3068,70,71;, - 3;3069,71,68;, - 3;3077,80,83;, - 3;3405,444,445;, - 3;4026,19,1082;, - 3;3038,1082,22;, - 3;5015,1797,23;, - 3;24,4684,4020;, - 3;3434,529,475;, - 3;3719,476,780;, - 3;3091,218,103;, - 3;3093,102,104;, - 3;3220,529,3439;, - 3;3424,25,461;, - 3;3189,461,221;, - 3;3085,220,89;, - 3;3098,89,26;, - 3;3429,474,477;, - 3;3094,104,106;, - 3;3220,105,252;, - 3;4683,1800,1798;, - 3;3418,219,3182;, - 3;3418,779,462;, - 3;4873,1967,1966;, - 3;4875,2109,1967;, - 3;5017,2109,5016;, - 3;4874,2114,5018;, - 3;4848,4875,4873;, - 3;4850,5016,4875;, - 3;4988,5017,5016;, - 3;4849,5018,4989;, - 3;4805,2256,1887;, - 3;4844,2263,5158;, - 3;4845,5154,4808;, - 3;4808,5155,4806;, - 3;2263,5156,5158;, - 3;1935,4809,1893;, - 3;3146,4808,4806;, - 3;27,4810,3148;, - 3;28,4807,1888;, - 3;4485,4487,3861;, - 3;3861,4559,3925;, - 3;3925,4564,4562;, - 3;4490,4493,4492;, - 3;4488,4492,4494;, - 3;4560,4495,4566;, - 3;4565,4567,4568;, - 3;4565,4569,4563;, - 3;4563,3928,3926;, - 3;3927,3864,3862;, - 3;3863,4493,4486;, - 3;4496,4500,4498;, - 3;3866,4570,4500;, - 3;3930,4573,4570;, - 3;4499,4493,4497;, - 3;4501,4492,4499;, - 3;4571,4495,4502;, - 3;4574,4567,4572;, - 3;4574,4569,4568;, - 3;4575,3928,4569;, - 3;3931,3864,3929;, - 3;3867,4493,3865;, - 3;4503,4508,4506;, - 3;4513,4508,4516;, - 3;4510,4521,4519;, - 3;4517,3869,4514;, - 3;4379,4385,4382;, - 3;4389,4385,4387;, - 3;4383,4523,4380;, - 3;4392,3875,3873;, - 3;3870,4524,4522;, - 3;4521,4525,4519;, - 3;4520,3874,3871;, - 3;3872,3875,3869;, - 3;3797,3738,3799;, - 3;4274,4888,4278;, - 3;4920,4395,4924;, - 3;3821,3825,4400;, - 3;3825,4402,4400;, - 3;3739,4369,3800;, - 3;4284,3740,3741;, - 3;3822,4403,4407;, - 3;4404,4414,4411;, - 3;4924,4412,4415;, - 3;4372,4279,4889;, - 3;4370,4280,4373;, - 3;4281,4275,4280;, - 3;4416,4396,4397;, - 3;4408,4411,4417;, - 3;3829,3832,3831;, - 3;4925,4929,4927;, - 3;4420,3831,4422;, - 3;4421,4427,4425;, - 3;4931,4428,4930;, - 3;3797,3831,3832;, - 3;4927,4890,4891;, - 3;4422,3831,4430;, - 3;3800,4430,3831;, - 3;4429,4431,4432;, - 3;4371,4432,4431;, - 3;4930,4428,4433;, - 3;4372,4930,4433;, - 3;3827,3829,3826;, - 3;3825,4420,4405;, - 3;4406,4425,4414;, - 3;4415,4931,4924;, - 3;4924,4925,4921;, - 3;3801,3749,3745;, - 3;4288,4899,4895;, - 3;4933,4437,4434;, - 3;3836,3842,3840;, - 3;3842,4443,4441;, - 3;3750,4375,4295;, - 3;4298,3751,4296;, - 3;3837,4444,4439;, - 3;4445,4450,4442;, - 3;4936,4452,4437;, - 3;4377,4900,4292;, - 3;4376,4293,4297;, - 3;4297,4289,4299;, - 3;4455,4438,4453;, - 3;4446,4454,4445;, - 3;3844,3848,3846;, - 3;4937,4941,4939;, - 3;4459,3850,3845;, - 3;4460,4464,4461;, - 3;4940,4465,4467;, - 3;3801,3850,3803;, - 3;4943,4901,4941;, - 3;4462,4469,3850;, - 3;3804,4469,4375;, - 3;4466,4470,4463;, - 3;4376,4472,4378;, - 3;4942,4473,4465;, - 3;4377,4942,4900;, - 3;3840,3844,3846;, - 3;3842,4459,3845;, - 3;4442,4468,4460;, - 3;4451,4940,4467;, - 3;4936,4937,4939;, - 3;3849,3834,3847;, - 3;3847,3828,3841;, - 3;3841,3823,3838;, - 3;3839,4409,4447;, - 3;4448,4418,4456;, - 3;4457,4398,4435;, - 3;4435,4922,4934;, - 3;4935,4926,4938;, - 3;4938,4928,4944;, - 3;4944,4892,4896;, - 3;4897,4276,4290;, - 3;4291,4285,4300;, - 3;4301,3742,3746;, - 3;3747,3798,3802;, - 3;3802,3833,3849;, - 3;4082,4077,4075;, - 3;3954,3933,3957;, - 3;3954,3963,3959;, - 3;4083,4088,4086;, - 3;3938,3933,3935;, - 3;3944,4092,4078;, - 3;3967,3944,3945;, - 3;4088,3972,3969;, - 3;3964,3972,3960;, - 3;4063,3877,4065;, - 3;3882,3879,3884;, - 3;4092,3974,4094;, - 3;3966,3976,3974;, - 3;3978,3934,3947;, - 3;3978,3965,3958;, - 3;4064,4070,4069;, - 3;4077,4070,4075;, - 3;3884,3886,3882;, - 3;3939,3890,3941;, - 3;3893,3950,3949;, - 3;3945,3950,3952;, - 3;3895,3891,3885;, - 3;3942,3895,3934;, - 3;3944,4080,3953;, - 3;3896,4080,4073;, - 3;3896,3949,3953;, - 3;3944,3949,3945;, - 3;3885,3898,3895;, - 3;3934,3898,3947;, - 3;4093,4076,4079;, - 3;3968,3936,3955;, - 3;3975,4089,4095;, - 3;4094,4084,4092;, - 3;3967,3961,3976;, - 3;3977,3973,3975;, - 3;3951,3883,3887;, - 3;3952,3888,3940;, - 3;3952,3937,3945;, - 3;4079,4071,4081;, - 3;4073,4072,4066;, - 3;3897,4067,3878;, - 3;3894,3878,3883;, - 3;4200,4221,4203;, - 3;3661,4222,4201;, - 3;3539,3668,3661;, - 3;3542,3591,3540;, - 3;3544,3593,3542;, - 3;3547,3594,3545;, - 3;4205,3596,3547;, - 3;4203,4224,4206;, - 3;4207,3549,4204;, - 3;3548,3549,4207;, - 3;3548,3546,3549;, - 3;3546,3543,3549;, - 3;3543,3541,3549;, - 3;3541,3662,3549;, - 3;4202,3549,3662;, - 3;4204,3549,4202;, - 3;4253,3377,3685;, - 3;3685,3377,3379;, - 3;4253,3685,4821;, - 3;4253,4821,4784;, - 3;3685,3379,4823;, - 3;3685,4823,4821;, - 3;3336,3121,3377;, - 3;3336,3377,4253;, - 3;3121,3382,3377;, - 3;3347,3122,3337;, - 3;3347,3124,3122;, - 3;4254,4785,4789;, - 3;4258,4254,4789;, - 3;4786,4822,4826;, - 3;4790,4786,4826;, - 3;4822,4824,4827;, - 3;4826,4822,4827;, - 3;3380,4828,4825;, - 3;3384,4828,3380;, - 3;3378,3385,3381;, - 3;3386,3385,3378;, - 3;3123,3387,3383;, - 3;3125,3387,3123;, - 3;3338,4254,4258;, - 3;3348,3338,4258;, - 3;3387,3378,3383;, - 3;3387,3386,3378;, - 3;4226,4208,4791;, - 3;4208,4787,4791;, - 3;3597,3349,3550;, - 3;3550,3349,3339;, - 3;3598,4227,3350;, - 3;4227,4792,3350;, - 3;3599,3551,4228;, - 3;3551,4209,4228;, - 3;3552,3340,4210;, - 3;4210,3340,4788;, - 3;3282,3296,3271;, - 3;3351,3343,3341;, - 3;3272,3300,3273;, - 3;3282,3274,3283;, - 3;3352,3345,3343;, - 3;3273,3553,3511;, - 3;3284,3512,3523;, - 3;3524,3554,3600;, - 3;3312,3352,3351;, - 3;3297,3344,3301;, - 3;3312,3341,3298;, - 3;3314,3353,3352;, - 3;3601,3345,3353;, - 3;3301,3346,3555;, - 3;3514,3276,3517;, - 3;3279,3302,3277;, - 3;3515,3520,3280;, - 3;3280,3557,3305;, - 3;3306,3537,3303;, - 3;3278,3538,3510;, - 3;3278,3510,3518;, - 3;3515,4747,3520;, - 3;3520,4764,3557;, - 3;3558,4767,3537;, - 3;3510,4768,4750;, - 3;3510,4750,3518;, - 3;3516,4751,4748;, - 3;4749,4769,4765;, - 3;4166,4180,4168;, - 3;4171,4182,4166;, - 3;4171,4732,4183;, - 3;4173,4734,4726;, - 3;4177,4167,4169;, - 3;4174,4177,4169;, - 3;4177,4723,4172;, - 3;4175,4727,4177;, - 3;4170,4184,4176;, - 3;4724,4735,4733;, - 3;3099,3233,3231;, - 3;3231,3482,3480;, - 3;3232,3102,3100;, - 3;3108,3235,3039;, - 3;3485,3238,3236;, - 3;3040,3488,3493;, - 3;3483,3490,3481;, - 3;3495,3491,3496;, - 3;3484,3239,3492;, - 3;3497,3239,3249;, - 3;3234,3103,3239;, - 3;3249,3103,3109;, - 3;3489,3481,3490;, - 3;3237,3480,3486;, - 3;3494,3490,3495;, - 3;3059,3104,3110;, - 3;3059,3056,3054;, - 3;3060,3106,3057;, - 3;3110,3240,3250;, - 3;3111,3243,3106;, - 3;3251,3244,3252;, - 3;3055,3107,3105;, - 3;3105,3245,3241;, - 3;4527,4475,4530;, - 3;4528,3903,3900;, - 3;4531,3851,3904;, - 3;4529,3853,4477;, - 3;3901,3852,3854;, - 3;4945,4536,4533;, - 3;4945,4539,4536;, - 3;4945,4542,4539;, - 3;4542,4945,4577;, - 3;4577,4945,4580;, - 3;4580,4945,4533;, - 3;3906,3910,3907;, - 3;3906,3907,3913;, - 3;3906,3913,3916;, - 3;3916,3919,3906;, - 3;3919,3922,3906;, - 3;3922,3910,3906;, - 3;3908,4540,3914;, - 3;3915,4543,3917;, - 3;3918,4578,3920;, - 3;3921,4581,3923;, - 3;3924,4534,3911;, - 3;3912,4537,3909;, - 3;4479,4902,4482;, - 3;4480,3858,3855;, - 3;4483,3805,3859;, - 3;4905,3806,4903;, - 3;4481,3808,4906;, - 3;3856,3807,3809;, - 3;4033,4039,4036;, - 3;4043,5056,4046;, - 3;3679,4813,4811;, - 3;5062,5066,5064;, - 3;4811,4818,4815;, - 3;4049,3811,4051;, - 3;3815,3813,3817;, - 3;4044,3812,3819;, - 3;3819,3812,3816;, - 3;4047,3814,4050;, - 3;3814,3820,3818;, - 3;5059,3819,4908;, - 3;4909,3819,3816;, - 3;5057,3820,4047;, - 3;3818,4910,4911;, - 3;5072,4908,4912;, - 3;4914,4908,4909;, - 3;5074,4910,5057;, - 3;4911,4916,4918;, - 3;5075,4913,4917;, - 3;4919,4913,4915;, - 3;3680,3817,3682;, - 3;3683,4911,4814;, - 3;3681,4909,3816;, - 3;4814,4918,4819;, - 3;4816,4919,4915;, - 3;4812,4914,4909;, - 3;4052,4055,4053;, - 3;4045,4058,4056;, - 3;4050,4059,4047;, - 3;4051,4061,4049;, - 3;5059,5079,5076;, - 3;5073,5081,5080;, - 3;5057,5082,5074;, - 3;5060,5083,5058;, - 3;4053,4041,4034;, - 3;4062,4040,4059;, - 3;4054,4037,4061;, - 3;5076,5069,5063;, - 3;5080,5067,5070;, - 3;5084,5068,5082;, - 3;4057,5085,5077;, - 3;4059,5065,5084;, - 3;4042,5064,4039;, - 3;4055,5063,4041;, - 3;4302,3752,4304;, - 3;4307,4311,4309;, - 3;4314,4319,4317;, - 3;4305,4319,4303;, - 3;4312,4318,3757;, - 3;3753,4318,4306;, - 3;4320,4326,4323;, - 3;4328,3759,3761;, - 3;4313,3764,4310;, - 3;3755,3758,3754;, - 3;3760,4310,3764;, - 3;4327,4308,4324;, - 3;4321,4307,4309;, - 3;4329,4319,4327;, - 3;3762,3764,3755;, - 3;4330,3756,4302;, - 3;4331,3768,3765;, - 3;4332,4337,4334;, - 3;4335,3771,3769;, - 3;3766,3772,4343;, - 3;4333,4344,4340;, - 3;4341,3773,4338;, - 3;4346,3777,3774;, - 3;4347,4352,4349;, - 3;4350,3780,3778;, - 3;3775,3781,3783;, - 3;4348,3784,4355;, - 3;4356,3782,4353;, - 3;4358,3789,3786;, - 3;4359,4363,4361;, - 3;4362,3791,3789;, - 3;3787,3792,3794;, - 3;4360,3795,4366;, - 3;4367,3793,4364;, - 3;3871,4518,4520;, - 3;4509,4511,4520;, - 3;4518,4509,4520;, - 3;3870,4522,4515;, - 3;4515,4522,4507;, - 3;4507,4522,4504;, - 3;3874,4526,4384;, - 3;3874,4386,4393;, - 3;3874,4384,4386;, - 3;3876,4390,4524;, - 3;4388,4381,4524;, - 3;4390,4388,4524;, - 3;4603,4607,4605;, - 3;4583,4609,4603;, - 3;4589,4586,4584;, - 3;4611,4592,4590;, - 3;4611,4615,4613;, - 3;4640,4646,4643;, - 3;4649,4619,4647;, - 3;4623,4604,4606;, - 3;4623,4585,4604;, - 3;4623,4591,4585;, - 3;4623,4612,4591;, - 3;4612,4623,4617;, - 3;4617,4623,4652;, - 3;4652,4623,4656;, - 3;4656,4623,4606;, - 3;4624,4657,4608;, - 3;4624,4658,4657;, - 3;4624,4616,4658;, - 3;4624,4614,4616;, - 3;4614,4624,4593;, - 3;4593,4624,4587;, - 3;4587,4624,4610;, - 3;4610,4624,4608;, - 3;4641,4659,4653;, - 3;4644,4657,4658;, - 3;4642,4656,4650;, - 3;4648,4608,4657;, - 3;4621,4607,4619;, - 3;4650,4606,4622;, - 3;5160,5176,5162;, - 3;5162,5181,5179;, - 3;5160,5183,5177;, - 3;5167,5170,5169;, - 3;5172,5185,5171;, - 3;5186,5188,5185;, - 3;5190,5194,5189;, - 3;5195,5197,5194;, - 3;4991,4851,4995;, - 3;5169,4853,5167;, - 3;5198,4996,5197;, - 3;5161,5173,5167;, - 3;5178,5196,5176;, - 3;5163,5187,5174;, - 3;5180,5191,5187;, - 3;5181,5196,5192;, - 3;5183,5199,5177;, - 3;5165,4992,5184;, - 3;5160,4854,5166;, - 3;3521,4211,4199;, - 3;3246,4199,4178;, - 3;4199,4770,4753;, - 3;4178,4753,4729;, - 3;3559,3525,3602;, - 3;4212,3603,4229;, - 3;4771,4229,4773;, - 3;4754,4774,4755;, - 3;4730,4755,4736;, - 3;4179,4737,4185;, - 3;4185,3247,4179;, - 3;3254,3522,3248;, - 3;3562,3665,3663;, - 3;3562,4255,4213;, - 3;3568,4215,3571;, - 3;3568,3576,3573;, - 3;4218,3562,4213;, - 3;3579,3585,3582;, - 3;3308,3588,3580;, - 3;3574,3583,3569;, - 3;3570,3586,3563;, - 3;3565,3587,3589;, - 3;3565,3589,3310;, - 3;3574,3309,3581;, - 3;3664,3670,3669;, - 3;4214,4259,4230;, - 3;3666,3604,3671;, - 3;3572,3606,3577;, - 3;4216,4233,4231;, - 3;3575,3607,3609;, - 3;3311,3318,3316;, - 3;4219,4230,4234;, - 3;4256,3669,4260;, - 3;3572,4232,3608;, - 3;3309,3610,3319;, - 3;3565,3317,3605;, - 3;4643,4654,4660;, - 3;4661,4618,4655;, - 3;5019,5024,5022;, - 3;5026,5232,5024;, - 3;5239,5278,5241;, - 3;5028,5229,5227;, - 3;5227,5286,5284;, - 3;5279,5284,5286;, - 3;5200,5235,5027;, - 3;5230,5285,5287;, - 3;5031,5027,5020;, - 3;5032,5228,5230;, - 3;5248,5280,5240;, - 3;5287,5281,5289;, - 3;5202,5023,5025;, - 3;5025,5249,5202;, - 3;5204,5288,5251;, - 3;5201,5251,5245;, - 3;5231,5035,5032;, - 3;5204,5031,5035;, - 3;5236,5242,5233;, - 3;5234,5243,5249;, - 3;5288,5248,5251;, - 3;5245,5251,5248;, - 3;5029,5036,5037;, - 3;5031,5037,5036;, - 3;5237,5248,5240;, - 3;6189,5203,6194;, - 3;6190,5229,5030;, - 3;6198,5286,5229;, - 3;6194,5250,6195;, - 3;6199,5279,5286;, - 3;6196,5278,6201;, - 3;6195,5244,6197;, - 3;5252,5257,5254;, - 3;5253,2371,31;, - 3;5255,2373,2372;, - 3;5260,2374,5258;, - 3;5262,2378,5263;, - 3;5263,5265,5262;, - 3;5205,2380,5262;, - 3;5206,5262,5265;, - 3;5270,5267,5272;, - 3;5275,2393,2392;, - 3;5275,5273,5276;, - 3;5208,5266,5270;, - 3;5210,2392,34;, - 3;5210,5271,5275;, - 3;5268,2379,2397;, - 3;2398,5277,5274;, - 3;2398,5268,2397;, - 3;3879,4664,4545;, - 3;4064,4666,4665;, - 3;4069,4670,4666;, - 3;4077,4672,4670;, - 3;4086,4674,4673;, - 3;4088,4625,4674;, - 3;4627,3970,3979;, - 3;3948,4627,3979;, - 3;3899,4595,3948;, - 3;3880,4547,3899;, - 3;5101,4671,4675;, - 3;4972,4596,4958;, - 3;4972,4630,4628;, - 3;5102,4677,5105;, - 3;4961,4596,4598;, - 3;4964,5108,4979;, - 3;4980,4964,4979;, - 3;4677,4982,5105;, - 3;4631,4982,4633;, - 3;4667,4946,4548;, - 3;4948,4548,4946;, - 3;5108,4984,4979;, - 3;4979,4986,4980;, - 3;4636,4597,4629;, - 3;4636,4632,4634;, - 3;4668,5090,5086;, - 3;4671,5090,4669;, - 3;4551,4950,4553;, - 3;4962,4554,4951;, - 3;4954,4969,4967;, - 3;4965,4967,4969;, - 3;4556,4552,4555;, - 3;4599,4556,4555;, - 3;4964,5099,5097;, - 3;4956,5099,4971;, - 3;4956,4969,4954;, - 3;4964,4969,4971;, - 3;4552,4557,4549;, - 3;4597,4557,4556;, - 3;5109,5095,5103;, - 3;4981,4959,4966;, - 3;4985,5106,4983;, - 3;5110,5104,5107;, - 3;4980,4975,4973;, - 3;4987,4983,4976;, - 3;4968,4949,4955;, - 3;4970,4952,4967;, - 3;4970,4960,4963;, - 3;5098,5091,5095;, - 3;5093,5092,5099;, - 3;4957,5087,5094;, - 3;4955,4947,4957;, - 3;4548,4664,4667;, - 3;4668,4666,4669;, - 3;4669,4670,4671;, - 3;4671,4672,4675;, - 3;4676,4674,4677;, - 3;4677,4625,4633;, - 3;4627,4635,4626;, - 3;4601,4627,4595;, - 3;4558,4595,4547;, - 3;4550,4547,4546;, - 3;5038,5041,5148;, - 3;5038,4680,4663;, - 3;5043,5000,4997;, - 3;5039,4638,5003;, - 3;5049,5112,5152;, - 3;5007,5004,5114;, - 3;5004,4678,5114;, - 3;5044,5008,5042;, - 3;4998,5004,5007;, - 3;5046,5005,5001;, - 3;5045,5038,5047;, - 3;5042,5006,5049;, - 3;5042,5152,5149;, - 3;5153,5115,5150;, - 3;5008,5112,5006;, - 3;4679,5151,5116;, - 3;3726,3733,3729;, - 3;3726,4272,4270;, - 3;4027,4005,4002;, - 3;3727,4266,3699;, - 3;3735,3702,3736;, - 3;3705,3700,3707;, - 3;3700,4268,3707;, - 3;4028,3706,3734;, - 3;4003,3700,3705;, - 3;4030,3701,4006;, - 3;4029,3726,4031;, - 3;3734,3704,3735;, - 3;3734,3736,3730;, - 3;3737,3708,3731;, - 3;3706,3702,3704;, - 3;4269,3732,3709;, - 3;4876,4881,4879;, - 3;4876,4272,4881;, - 3;5050,5009,5053;, - 3;4877,4266,4271;, - 3;4885,4861,4860;, - 3;4863,4865,4857;, - 3;4857,4268,4267;, - 3;5051,4864,5012;, - 3;5013,4857,5010;, - 3;5054,4858,4878;, - 3;5052,4876,4879;, - 3;4880,4860,4864;, - 3;4880,4886,4885;, - 3;4887,4866,4862;, - 3;4864,4861,4867;, - 3;4269,4882,4273;, - 3;4235,4221,4223;, - 3;3672,4222,3668;, - 3;3611,3668,3592;, - 3;3614,3591,3593;, - 3;3616,3593,3595;, - 3;3619,3594,3596;, - 3;4240,3596,4225;, - 3;4238,4224,4221;, - 3;4241,4239,3041;, - 3;3620,4241,3041;, - 3;3620,3041,3617;, - 3;3617,3041,3615;, - 3;3615,3041,3612;, - 3;3612,3041,3673;, - 3;4236,3673,3041;, - 3;4239,4236,3041;, - 3;4261,3042,3388;, - 3;3042,3390,3388;, - 3;4261,4829,3042;, - 3;4261,4793,4829;, - 3;3042,4831,3390;, - 3;3042,4829,4831;, - 3;3354,3388,3126;, - 3;3354,4261,3388;, - 3;3126,3388,3393;, - 3;3347,3355,3127;, - 3;3347,3127,3124;, - 3;4262,4789,4794;, - 3;4258,4789,4262;, - 3;4795,4826,4830;, - 3;4790,4826,4795;, - 3;4830,4827,4832;, - 3;4826,4827,4830;, - 3;3391,4833,4828;, - 3;3384,3391,4828;, - 3;3389,3392,3385;, - 3;3386,3389,3385;, - 3;3128,3394,3387;, - 3;3125,3128,3387;, - 3;3356,4258,4262;, - 3;3348,4258,3356;, - 3;3387,3394,3389;, - 3;3387,3389,3386;, - 3;3282,3320,3313;, - 3;3043,3359,3044;, - 3;3285,3324,3321;, - 3;3282,3287,3286;, - 3;3044,3361,3045;, - 3;3288,3621,3324;, - 3;3284,3526,3289;, - 3;3524,3622,3527;, - 3;3312,3044,3315;, - 3;3322,3360,3357;, - 3;3312,3358,3043;, - 3;3315,3045,3601;, - 3;3601,3361,3623;, - 3;3325,3362,3360;, - 3;3529,3293,3290;, - 3;3291,3333,3326;, - 3;3530,3292,3046;, - 3;3292,3625,3046;, - 3;3327,3659,3626;, - 3;3294,3660,3334;, - 3;3294,3534,3047;, - 3;3530,3046,4756;, - 3;3046,4775,4756;, - 3;3626,4781,4776;, - 3;3047,4782,3660;, - 3;3047,3534,4761;, - 3;3531,4762,3535;, - 3;4757,4783,4763;, - 3;4186,4180,4182;, - 3;4191,4182,4183;, - 3;4191,4732,4738;, - 3;4193,4734,4184;, - 3;3048,4187,4192;, - 3;4194,4188,3048;, - 3;3048,4739,4741;, - 3;4195,3048,4741;, - 3;4189,4184,4181;, - 3;4740,4735,4742;, - 3;3112,3256,3258;, - 3;3256,3500,3258;, - 3;3257,3115,3049;, - 3;3108,3049,3115;, - 3;3503,3050,3506;, - 3;3040,3506,3050;, - 3;3501,3051,3508;, - 3;3495,3508,3051;, - 3;3502,3052,3259;, - 3;3497,3052,3509;, - 3;3259,3116,3113;, - 3;3249,3116,3052;, - 3;3507,3498,3504;, - 3;3260,3499,3256;, - 3;3494,3051,3507;, - 3;3059,3117,3062;, - 3;3059,3064,3061;, - 3;3060,3119,3111;, - 3;3110,3262,3117;, - 3;3111,3265,3253;, - 3;3251,3266,3263;, - 3;3063,3120,3065;, - 3;3118,3267,3120;, - 3;3532,4243,3627;, - 3;3268,3053,3532;, - 3;3053,4778,4243;, - 3;4197,4759,3053;, - 3;3628,3525,3533;, - 3;4244,3603,3629;, - 3;4779,4229,4244;, - 3;4760,4774,4780;, - 3;4744,4755,4760;, - 3;4198,4737,4745;, - 3;4185,3269,3255;, - 3;3254,3533,3525;, - 3;3630,3676,3633;, - 3;3630,4263,3674;, - 3;3636,4247,4250;, - 3;3636,3644,3639;, - 3;4250,3630,3636;, - 3;3647,3653,3656;, - 3;3329,3657,3331;, - 3;3641,3650,3648;, - 3;3637,3654,3651;, - 3;3634,3655,3631;, - 3;3634,3332,3658;, - 3;3641,3648,3330;, - 3;3675,3670,3677;, - 3;4245,4259,4264;, - 3;3678,3604,3635;, - 3;3640,3606,3608;, - 3;4248,4233,4251;, - 3;3642,3607,3645;, - 3;3331,3318,3329;, - 3;4252,4230,4245;, - 3;4265,3669,3675;, - 3;3640,4232,4249;, - 3;3330,3610,3641;, - 3;3634,3317,3332;, - 3;5323,5331,5326;, - 3;5318,5332,5324;, - 3;5291,5320,5318;, - 3;5294,5302,5292;, - 3;5296,5304,5294;, - 3;5299,5305,5297;, - 3;5328,5307,5299;, - 3;5326,5334,5329;, - 3;5330,5301,5327;, - 3;5300,5301,5330;, - 3;5300,5298,5301;, - 3;5298,5295,5301;, - 3;5295,5293,5301;, - 3;5293,5319,5301;, - 3;5325,5301,5319;, - 3;5327,5301,5325;, - 3;5336,5331,5333;, - 3;5321,5332,5320;, - 3;5308,5320,5303;, - 3;5311,5302,5304;, - 3;5313,5304,5306;, - 3;5316,5305,5307;, - 3;5341,5307,5335;, - 3;5339,5334,5331;, - 3;5342,5340,5290;, - 3;5317,5342,5290;, - 3;5317,5290,5314;, - 3;5314,5290,5312;, - 3;5312,5290,5309;, - 3;5309,5290,5322;, - 3;5337,5322,5290;, - 3;5340,5337,5290;, - 3;5350,5355,5352;, - 3;5351,2485,2465;, - 3;5353,2487,2486;, - 3;5358,2488,5356;, - 3;5360,2492,5361;, - 3;5361,5363,5360;, - 3;5344,2494,5360;, - 3;5345,5360,5363;, - 3;5368,5365,5370;, - 3;5373,2507,2506;, - 3;5373,5371,5374;, - 3;5347,5364,5368;, - 3;5349,2506,2468;, - 3;5349,5369,5373;, - 3;5366,2493,2511;, - 3;2512,5375,5372;, - 3;2512,5366,2511;, - 3;5384,5396,5397;, - 3;5386,5401,5396;, - 3;5384,5403,5389;, - 3;5391,5170,5393;, - 3;5394,5185,5405;, - 3;5405,5188,5407;, - 3;5408,5194,5411;, - 3;5411,5197,5413;, - 3;5380,4851,5376;, - 3;5169,5377,4852;, - 3;5413,4996,5381;, - 3;5385,5393,5387;, - 3;5398,5412,5414;, - 3;5388,5406,5399;, - 3;5399,5409,5402;, - 3;5401,5412,5396;, - 3;5403,5414,5382;, - 3;5390,5383,5378;, - 3;5384,5379,5392;, - 3;5447,5418,5415;, - 3;5448,5453,5450;, - 3;5451,5421,5419;, - 3;5416,5422,5459;, - 3;5449,5460,5456;, - 3;5457,5423,5454;, - 3;5462,5427,5424;, - 3;5463,5468,5465;, - 3;5466,5430,5428;, - 3;5425,5431,5433;, - 3;5464,5434,5471;, - 3;5472,5432,5469;, - 3;5474,5439,5436;, - 3;5475,5479,5477;, - 3;5478,5441,5439;, - 3;5437,5442,5444;, - 3;5476,5445,5482;, - 3;5483,5443,5480;, - 3;5517,5488,5485;, - 3;5518,5523,5520;, - 3;5521,5491,5489;, - 3;5486,5492,5529;, - 3;5519,5530,5526;, - 3;5527,5493,5524;, - 3;5532,5497,5494;, - 3;5533,5538,5535;, - 3;5536,5500,5498;, - 3;5495,5501,5503;, - 3;5534,5504,5541;, - 3;5542,5502,5539;, - 3;5544,5509,5506;, - 3;5545,5549,5547;, - 3;5548,5511,5509;, - 3;5507,5512,5514;, - 3;5546,5515,5552;, - 3;5553,5513,5550;, - 3;5587,5558,5555;, - 3;5588,5593,5590;, - 3;5591,5561,5559;, - 3;5556,5562,5599;, - 3;5589,5600,5596;, - 3;5597,5563,5594;, - 3;5602,5567,5564;, - 3;5603,5608,5605;, - 3;5606,5570,5568;, - 3;5565,5571,5573;, - 3;5604,5574,5611;, - 3;5612,5572,5609;, - 3;1063,1067,1161;, - 3;5615,5619,5617;, - 3;5618,5581,5579;, - 3;5577,5582,5584;, - 3;5616,5585,5622;, - 3;5623,5583,5620;, - 3;5657,5628,5625;, - 3;5658,5663,5660;, - 3;5661,5631,5629;, - 3;5626,5632,5669;, - 3;5659,5670,5666;, - 3;5667,5633,5664;, - 3;5672,5637,5634;, - 3;5673,5678,5675;, - 3;5676,5640,5638;, - 3;5635,5641,5643;, - 3;5674,5644,5681;, - 3;5682,5642,5679;, - 3;5684,5649,5646;, - 3;5685,5689,5687;, - 3;5688,5651,5649;, - 3;5647,5652,5654;, - 3;5686,5655,5692;, - 3;5693,5653,5690;, - 3;5716,5721,5718;, - 3;5713,5722,5717;, - 3;5695,5714,5713;, - 3;5697,5701,5696;, - 3;5698,5703,5697;, - 3;5700,5704,5699;, - 3;5719,5706,5700;, - 3;5718,5724,5720;, - 3;5726,5721,5723;, - 3;5715,5722,5714;, - 3;5707,5714,5702;, - 3;5709,5701,5703;, - 3;5710,5703,5705;, - 3;5712,5704,5706;, - 3;5729,5706,5725;, - 3;5728,5724,5721;, - 3;5752,5757,5754;, - 3;5749,5758,5753;, - 3;5731,5750,5749;, - 3;5733,5737,5732;, - 3;5734,5739,5733;, - 3;5736,5740,5735;, - 3;5755,5742,5736;, - 3;5754,5760,5756;, - 3;5762,5757,5759;, - 3;5751,5758,5750;, - 3;5743,5750,5738;, - 3;5745,5737,5739;, - 3;5746,5739,5741;, - 3;5748,5740,5742;, - 3;5765,5742,5761;, - 3;5764,5760,5757;, - 3;5791,5796,5794;, - 3;5801,5796,5804;, - 3;5798,5809,5807;, - 3;5805,5767,5802;, - 3;5775,5781,5778;, - 3;5785,5781,5783;, - 3;5779,5811,5776;, - 3;5788,5773,5771;, - 3;5768,5812,5810;, - 3;5809,5813,5807;, - 3;5808,5772,5769;, - 3;5770,5773,5767;, - 3;5769,5806,5808;, - 3;5797,5799,5808;, - 3;5806,5797,5808;, - 3;5768,5810,5803;, - 3;5803,5810,5795;, - 3;5795,5810,5792;, - 3;5772,5814,5780;, - 3;5772,5782,5789;, - 3;5772,5780,5782;, - 3;5774,5786,5812;, - 3;5784,5777,5812;, - 3;5786,5784,5812;, - 3;5852,5837,5834;, - 3;5852,5840,5837;, - 3;5852,5843,5840;, - 3;5843,5852,5846;, - 3;5846,5852,5849;, - 3;5849,5852,5834;, - 3;5815,5819,5816;, - 3;5815,5816,5822;, - 3;5815,5822,5825;, - 3;5825,5828,5815;, - 3;5828,5831,5815;, - 3;5831,5819,5815;, - 3;5817,5841,5823;, - 3;5824,5844,5826;, - 3;5827,5847,5829;, - 3;5830,5850,5832;, - 3;5833,5835,5820;, - 3;5821,5838,5818;, - 3;5890,5875,5872;, - 3;5890,5878,5875;, - 3;5890,5881,5878;, - 3;5881,5890,5884;, - 3;5884,5890,5887;, - 3;5887,5890,5872;, - 3;5853,5857,5854;, - 3;5853,5854,5860;, - 3;5853,5860,5863;, - 3;5863,5866,5853;, - 3;5866,5869,5853;, - 3;5869,5857,5853;, - 3;5855,5879,5861;, - 3;5862,5882,5864;, - 3;5865,5885,5867;, - 3;5868,5888,5870;, - 3;5871,5873,5858;, - 3;5859,5876,5856;, - 3;5941,5946,5948;, - 3;5931,5943,5942;, - 3;5949,5932,5931;, - 3;5954,5951,5950;, - 3;5954,5959,5955;, - 3;5957,5963,5960;, - 3;5962,5967,5963;, - 3;5965,5946,5968;, - 3;5969,5947,5970;, - 3;5964,5969,5970;, - 3;5961,5964,5970;, - 3;5956,5961,5970;, - 3;5956,5970,5952;, - 3;5952,5970,5933;, - 3;5933,5970,5944;, - 3;5944,5970,5947;, - 3;5901,5925,5928;, - 3;5901,5904,5925;, - 3;5925,5912,5971;, - 3;5925,5904,5912;, - 3;5902,5929,5891;, - 3;5891,5929,5915;, - 3;5930,5926,5916;, - 3;5916,5926,5917;, - 3;5927,5972,5918;, - 3;5918,5972,5934;, - 3;5913,5907,5973;, - 3;5907,5935,5973;, - 3;5905,5893,5914;, - 3;5893,5908,5914;, - 3;5903,5892,5906;, - 3;5892,5894,5906;, - 3;5895,5919,5898;, - 3;5895,5921,5919;, - 3;5919,5909,5898;, - 3;5919,5938,5909;, - 3;5892,5899,5894;, - 3;5892,5896,5899;, - 3;5916,5917,5922;, - 3;5923,5918,5920;, - 3;5891,5915,5897;, - 3;5915,5924,5897;, - 3;5893,5910,5908;, - 3;5893,5900,5910;, - 3;5939,5936,5907;, - 3;5911,5939,5907;, - 3;5920,5918,5940;, - 3;5918,5937,5940;, - 3;5977,5982,5984;, - 3;5974,5979,5978;, - 3;5985,5975,5974;, - 3;5990,5987,5986;, - 3;5990,5995,5991;, - 3;5993,5999,5996;, - 3;5998,6003,5999;, - 3;6001,5982,6004;, - 3;6005,5983,6006;, - 3;6000,6005,6006;, - 3;5997,6000,6006;, - 3;5992,5997,6006;, - 3;5992,6006,5988;, - 3;5988,6006,5976;, - 3;5976,6006,5980;, - 3;5980,6006,5983;, - 3;6010,6015,6017;, - 3;6007,6012,6011;, - 3;6018,6008,6007;, - 3;6023,6020,6019;, - 3;6023,6028,6024;, - 3;6026,6032,6029;, - 3;6031,6036,6032;, - 3;6034,6015,6037;, - 3;6038,6016,6039;, - 3;6033,6038,6039;, - 3;6030,6033,6039;, - 3;6025,6030,6039;, - 3;6025,6039,6021;, - 3;6021,6039,6009;, - 3;6009,6039,6013;, - 3;6013,6039,6016;, - 3;6090,6095,6092;, - 3;6080,6093,6081;, - 3;6098,6081,6100;, - 3;6103,6101,6104;, - 3;6103,6108,6106;, - 3;6107,6112,6111;, - 3;6111,6116,6114;, - 3;6115,6095,6097;, - 3;6117,6119,6096;, - 3;6113,6119,6117;, - 3;6109,6119,6113;, - 3;6105,6119,6109;, - 3;6105,6102,6119;, - 3;6102,6082,6119;, - 3;6082,6094,6119;, - 3;6094,6096,6119;, - 3;6050,6077,6074;, - 3;6050,6074,6053;, - 3;6074,6120,6061;, - 3;6074,6061,6053;, - 3;6051,6040,6078;, - 3;6040,6064,6078;, - 3;6079,6065,6075;, - 3;6065,6066,6075;, - 3;6076,6067,6121;, - 3;6067,6083,6121;, - 3;6062,6122,6056;, - 3;6056,6122,6084;, - 3;6054,6063,6042;, - 3;6042,6063,6057;, - 3;6052,6055,6041;, - 3;6041,6055,6043;, - 3;6044,6047,6068;, - 3;6044,6068,6070;, - 3;6068,6047,6058;, - 3;6068,6058,6087;, - 3;6041,6043,6048;, - 3;6041,6048,6045;, - 3;6065,6071,6066;, - 3;6072,6069,6067;, - 3;6040,6046,6064;, - 3;6064,6046,6073;, - 3;6042,6057,6059;, - 3;6042,6059,6049;, - 3;6088,6056,6085;, - 3;6060,6056,6088;, - 3;6069,6089,6067;, - 3;6067,6089,6086;, - 3;6126,6131,6128;, - 3;6123,6129,6124;, - 3;6134,6124,6136;, - 3;6139,6137,6140;, - 3;6139,6144,6142;, - 3;6143,6148,6147;, - 3;6147,6152,6150;, - 3;6151,6131,6133;, - 3;6153,6155,6132;, - 3;6149,6155,6153;, - 3;6145,6155,6149;, - 3;6141,6155,6145;, - 3;6141,6138,6155;, - 3;6138,6125,6155;, - 3;6125,6130,6155;, - 3;6130,6132,6155;, - 3;6159,6164,6161;, - 3;6156,6162,6157;, - 3;6167,6157,6169;, - 3;6172,6170,6173;, - 3;6172,6177,6175;, - 3;6176,6181,6180;, - 3;6180,6185,6183;, - 3;6184,6164,6166;, - 3;6186,6188,6165;, - 3;6182,6188,6186;, - 3;6178,6188,6182;, - 3;6174,6188,6178;, - 3;6174,6171,6188;, - 3;6171,6158,6188;, - 3;6158,6163,6188;, - 3;6163,6165,6188;, - 3;1063,1161,1747;, - 3;1068,1073,1035;, - 3;1064,1730,1705;, - 3;1074,1044,1152;, - 3;1042,1706,1745;, - 3;1069,1040,1046;, - 3;1039,1037,1042;, - 3;1071,1065,1043;, - 3;1070,1067,1063;, - 3;1066,1046,1044;, - 3;1066,1074,1162;, - 3;1163,1153,1155;, - 3;1046,1157,1152;, - 3;1746,1748,1160;, - 3;1047,2279,0;, - 3;740,1936,2279;, - 3;2,3,1936;, - 3;446,763,764;, - 3;762,4,5;, - 3;446,447,6;, - 3;420,736,737;, - 3;1958,8,1959;, - 3;425,427,193;, - 3;426,739,766;, - 3;1917,1920,737;, - 3;1962,1960,766;, - 3;421,424,427;, - 3;738,739,426;, - 3;738,1921,1962;, - 3;1918,1958,1961;, - 3;1075,2108,1749;, - 3;196,91,94;, - 3;91,93,96;, - 3;767,773,463;, - 3;466,464,468;, - 3;93,236,97;, - 3;470,469,478;, - 3;467,237,448;, - 3;237,234,195;, - 3;471,238,237;, - 3;238,92,234;, - 3;471,473,239;, - 3;238,239,235;, - 3;770,769,449;, - 3;199,450,449;, - 3;478,241,240;, - 3;241,98,236;, - 3;242,204,201;, - 3;84,202,201;, - 3;455,458,459;, - 3;456,203,205;, - 3;452,460,243;, - 3;202,85,86;, - 3;99,242,243;, - 3;84,99,100;, - 3;178,222,244;, - 3;180,225,227;, - 3;229,247,248;, - 3;245,212,214;, - 3;211,187,189;, - 3;185,189,187;, - 3;192,233,222;, - 3;228,226,229;, - 3;210,217,190;, - 3;209,244,250;, - 3;244,222,232;, - 3;178,191,186;, - 3;233,227,232;, - 3;192,186,227;, - 3;774,1078,1048;, - 3;743,1052,223;, - 3;1053,1080,246;, - 3;1079,778,212;, - 3;777,746,188;, - 3;744,183,188;, - 3;224,1051,1053;, - 3;747,741,1048;, - 3;775,742,746;, - 3;1076,1080,1053;, - 3;776,778,1079;, - 3;748,1056,1050;, - 3;1055,1049,1053;, - 3;742,749,744;, - 3;72,429,163;, - 3;61,139,385;, - 3;65,142,137;, - 3;386,433,76;, - 3;431,430,73;, - 3;144,148,169;, - 3;173,171,434;, - 3;146,390,435;, - 3;145,11,389;, - 3;391,1875,1922;, - 3;1874,393,394;, - 3;1923,1876,1878;, - 3;1881,1930,1926;, - 3;1924,1928,439;, - 3;1929,443,440;, - 3;438,441,395;, - 3;442,399,395;, - 3;12,150,151;, - 3;400,1883,1880;, - 3;13,1881,1879;, - 3;155,153,397;, - 3;149,400,396;, - 3;2214,2215,2315;, - 3;2214,1753,1755;, - 3;1758,2221,2215;, - 3;2218,1762,1753;, - 3;1164,1758,1755;, - 3;1760,1763,6191;, - 3;1765,6192,6191;, - 3;2219,2222,1764;, - 3;2223,1766,1764;, - 3;2319,2317,2321;, - 3;2327,2330,2324;, - 3;2224,2328,2322;, - 3;2316,2217,2226;, - 3;1754,6191,1767;, - 3;6192,1769,1767;, - 3;2329,2223,2222;, - 3;2219,2320,2326;, - 3;1770,2229,2230;, - 3;2220,1759,1773;, - 3;2216,2220,2231;, - 3;2229,2225,2228;, - 3;1168,1171,1172;, - 3;1757,1768,1170;, - 3;1759,1166,1173;, - 3;1767,1769,1771;, - 3;479,483,485;, - 3;1775,1175,1176;, - 3;2232,1775,1777;, - 3;1176,1175,1178;, - 3;479,489,1180;, - 3;1182,1183,1779;, - 3;1184,1781,1779;, - 3;1780,1779,2236;, - 3;1781,2237,2236;, - 3;15,2239,1783;, - 3;2240,1785,1783;, - 3;491,494,495;, - 3;495,494,497;, - 3;502,504,505;, - 3;508,511,506;, - 3;513,514,515;, - 3;514,518,519;, - 3;486,484,521;, - 3;527,528,519;, - 3;1186,1188,495;, - 3;1189,496,495;, - 3;1189,1188,1183;, - 3;1186,1184,1183;, - 3;1190,1192,1193;, - 3;1196,1197,1193;, - 3;1196,1192,505;, - 3;1190,508,505;, - 3;1197,1784,1783;, - 3;1785,1194,1193;, - 3;513,517,493;, - 3;520,526,522;, - 3;503,507,528;, - 3;1179,1187,501;, - 3;480,501,498;, - 3;482,499,493;, - 3;523,493,517;, - 3;1174,1185,1187;, - 3;1776,1782,1185;, - 3;2233,2238,1782;, - 3;1181,1191,1195;, - 3;1177,1195,1786;, - 3;1778,1786,2241;, - 3;490,509,1191;, - 3;487,512,509;, - 3;525,507,510;, - 3;519,528,507;, - 3;1198,1788,1789;, - 3;1787,1793,1794;, - 3;1204,1208,1795;, - 3;1210,1211,1212;, - 3;1201,1791,1796;, - 3;1199,1203,1211;, - 3;1199,1210,1213;, - 3;1213,1212,1207;, - 3;1202,1209,1212;, - 3;1214,2243,2244;, - 3;1214,1219,1220;, - 3;1221,1226,1228;, - 3;2245,2246,1230;, - 3;2242,1215,1232;, - 3;1217,2245,2246;, - 3;2242,1215,1232;, - 3;1215,1225,1229;, - 3;1231,1227,1222;, - 3;2248,2332,2333;, - 3;2331,2335,17;, - 3;2249,18,2335;, - 3;78,81,68;, - 3;82,75,167;, - 3;164,177,175;, - 3;428,444,176;, - 3;387,401,445;, - 3;401,388,138;, - 3;156,140,141;, - 3;158,143,66;, - 3;62,71,70;, - 3;64,68,71;, - 3;74,83,80;, - 3;432,445,444;, - 3;1081,1082,19;, - 3;21,22,1082;, - 3;2108,23,1797;, - 3;24,1075,1751;, - 3;469,475,529;, - 3;771,780,476;, - 3;94,103,218;, - 3;96,104,102;, - 3;241,478,529;, - 3;458,461,25;, - 3;207,221,461;, - 3;88,89,220;, - 3;101,26,89;, - 3;464,477,474;, - 3;97,106,104;, - 3;241,252,105;, - 3;1750,1798,1800;, - 3;451,200,219;, - 3;451,462,779;, - 3;1963,1966,1967;, - 3;1968,1967,2109;, - 3;2111,2110,2109;, - 3;1964,2112,2114;, - 3;1937,1963,1968;, - 3;1939,1968,2110;, - 3;2081,2110,2111;, - 3;1938,2083,2112;, - 3;1884,1887,2256;, - 3;1931,2262,2263;, - 3;1932,1889,2258;, - 3;2263,2262,2260;, - 3;1935,1893,1890;, - 3;159,1885,1889;, - 3;27,162,1891;, - 3;28,1888,1886;, - 3;1552,916,1554;, - 3;916,980,1626;, - 3;980,1630,1631;, - 3;1558,1559,1560;, - 3;1555,1562,1559;, - 3;1627,1634,1561;, - 3;1632,1635,1633;, - 3;1632,1629,1636;, - 3;1629,982,983;, - 3;981,918,919;, - 3;917,1553,1560;, - 3;1563,1566,1567;, - 3;921,1567,1637;, - 3;985,1637,1640;, - 3;1565,1564,1560;, - 3;1568,1565,1559;, - 3;1638,1569,1561;, - 3;1641,1639,1633;, - 3;1641,1635,1636;, - 3;1643,1636,983;, - 3;987,984,919;, - 3;923,920,1560;, - 3;1570,1573,1575;, - 3;1580,1585,1575;, - 3;1578,1587,1588;, - 3;1583,1582,924;, - 3;1446,1451,1452;, - 3;1456,1454,1452;, - 3;1449,1448,1590;, - 3;1460,929,930;, - 3;925,1589,1591;, - 3;1588,1587,1592;, - 3;1586,927,928;, - 3;926,924,930;, - 3;852,854,793;, - 3;1341,1347,1981;, - 3;2013,2017,1462;, - 3;876,1468,880;, - 3;880,1468,1469;, - 3;794,855,1436;, - 3;1351,799,795;, - 3;877,1477,1470;, - 3;1471,1480,1481;, - 3;2017,1482,1478;, - 3;1437,1441,1346;, - 3;1350,1346,1342;, - 3;1483,1466,1463;, - 3;1474,1486,1480;, - 3;884,886,887;, - 3;2018,2020,2022;, - 3;1487,1490,886;, - 3;1488,1493,1494;, - 3;2025,2023,1495;, - 3;852,887,886;, - 3;2020,1987,1983;, - 3;855,886,1497;, - 3;1496,1499,1498;, - 3;1438,1498,1499;, - 3;1439,1500,2023;, - 3;882,881,884;, - 3;880,1472,1487;, - 3;1473,1481,1493;, - 3;1482,2017,2025;, - 3;2017,2016,2018;, - 3;856,802,804;, - 3;1355,1990,1992;, - 3;2026,1503,1504;, - 3;891,895,897;, - 3;897,1508,1510;, - 3;805,1363,1442;, - 3;1365,1364,806;, - 3;892,1507,1511;, - 3;1512,1509,1517;, - 3;2029,1504,1520;, - 3;1443,1362,1361;, - 3;1362,1367,1356;, - 3;1522,1521,1505;, - 3;1514,1512,1519;, - 3;899,902,903;, - 3;2030,2033,2034;, - 3;1526,900,905;, - 3;1527,1529,1531;, - 3;2032,1535,1532;, - 3;856,858,905;, - 3;2036,2034,1994;, - 3;859,1442,1536;, - 3;1533,1530,1537;, - 3;1443,1445,1540;, - 3;1444,1993,2035;, - 3;895,902,899;, - 3;897,900,1526;, - 3;1509,1527,1534;, - 3;1518,1535,2032;, - 3;2029,2033,2030;, - 3;904,901,890;, - 3;901,896,883;, - 3;896,894,878;, - 3;893,1516,1475;, - 3;1515,1525,1484;, - 3;1524,1502,1465;, - 3;1502,2028,2014;, - 3;2027,2031,2019;, - 3;2031,2037,2021;, - 3;2037,1991,1985;, - 3;1989,1358,1343;, - 3;1357,1368,1353;, - 3;1366,803,797;, - 3;801,857,853;, - 3;857,904,888;, - 3;1138,1132,1133;, - 3;1009,1012,988;, - 3;1009,1016,1018;, - 3;1139,1143,1144;, - 3;993,990,988;, - 3;999,1134,1148;, - 3;1022,1000,999;, - 3;1144,1024,1027;, - 3;1019,1017,1027;, - 3;1119,1123,932;, - 3;937,939,934;, - 3;1148,1150,1029;, - 3;1021,1029,1031;, - 3;1033,1003,989;, - 3;1033,1013,1020;, - 3;1120,1125,1126;, - 3;1133,1132,1126;, - 3;939,937,941;, - 3;994,998,946;, - 3;1000,1007,1005;, - 3;997,989,950;, - 3;999,1008,1136;, - 3;951,1129,1136;, - 3;951,1008,1004;, - 3;999,1000,1004;, - 3;940,950,953;, - 3;989,1003,953;, - 3;1149,1135,1131;, - 3;1023,1011,991;, - 3;1030,1151,1146;, - 3;1150,1148,1141;, - 3;1022,1031,1014;, - 3;1032,1030,1028;, - 3;1006,944,938;, - 3;1007,995,943;, - 3;1007,1000,992;, - 3;1135,1137,1127;, - 3;1129,1124,1128;, - 3;952,933,1122;, - 3;949,938,933;, - 3;1267,1270,1288;, - 3;711,1269,1290;, - 3;589,711,718;, - 3;592,591,642;, - 3;594,592,643;, - 3;597,596,645;, - 3;1272,597,646;, - 3;1270,1274,1292;, - 3;304,294,318;, - 3;373,364,365;, - 3;293,296,322;, - 3;304,306,295;, - 3;374,365,367;, - 3;296,563,603;, - 3;305,574,561;, - 3;573,651,604;, - 3;335,373,374;, - 3;320,323,366;, - 3;335,321,364;, - 3;336,374,375;, - 3;650,375,367;, - 3;323,606,368;, - 3;564,569,298;, - 3;302,300,324;, - 3;303,329,607;, - 3;328,326,587;, - 3;299,560,588;, - 3;570,607,1842;, - 3;608,587,1845;, - 3;560,1828,1846;, - 3;566,1827,1829;, - 3;1826,1844,1847;, - 3;1233,1237,1247;, - 3;1238,1233,1249;, - 3;1238,1250,1810;, - 3;1240,1806,1812;, - 3;1244,1235,1234;, - 3;1244,1239,1802;, - 3;1236,1243,1251;, - 3;1803,1811,1813;, - 3;253,531,532;, - 3;254,109,110;, - 3;116,29,257;, - 3;535,259,260;, - 3;30,544,538;, - 3;533,530,540;, - 3;545,547,541;, - 3;534,542,261;, - 3;546,271,261;, - 3;256,261,111;, - 3;271,117,111;, - 3;539,540,530;, - 3;258,537,531;, - 3;543,545,540;, - 3;53,118,112;, - 3;53,48,50;, - 3;55,52,114;, - 3;118,273,262;, - 3;119,114,265;, - 3;272,275,266;, - 3;49,113,115;, - 3;113,264,267;, - 3;1594,1599,1542;, - 3;1595,957,958;, - 3;1598,960,906;, - 3;1596,1545,908;, - 3;956,909,907;, - 3;963,970,1607;, - 3;969,973,1610;, - 3;972,976,1645;, - 3;975,979,1648;, - 3;978,967,1601;, - 3;966,964,1605;, - 3;1546,1551,1995;, - 3;1547,912,913;, - 3;1550,915,860;, - 3;1999,1997,861;, - 3;1548,2000,864;, - 3;911,865,862;, - 3;1089,1094,1095;, - 3;1099,1104,2152;, - 3;729,1894,1896;, - 3;2158,2161,2162;, - 3;1894,1900,1901;, - 3;1105,1108,866;, - 3;870,873,868;, - 3;1100,874,867;, - 3;1102,1106,869;, - 3;2156,2001,874;, - 3;2002,871,874;, - 3;2153,1102,875;, - 3;872,2004,2003;, - 3;2168,2005,2001;, - 3;2007,2002,2001;, - 3;2170,2153,2003;, - 3;2004,2012,2009;, - 3;2171,2010,2006;, - 3;2011,2008,2006;, - 3;730,734,873;, - 3;733,1897,2004;, - 3;731,871,2002;, - 3;1897,1903,2012;, - 3;1898,2008,2011;, - 3;1895,2002,2007;, - 3;1107,1110,1111;, - 3;1101,1113,1114;, - 3;1106,1102,1115;, - 3;1108,1105,1118;, - 3;2156,2173,2175;, - 3;2169,2176,2177;, - 3;2153,2170,2178;, - 3;2157,2154,2180;, - 3;1110,1091,1098;, - 3;1117,1115,1096;, - 3;1109,1118,1093;, - 3;2173,2159,2166;, - 3;2176,2167,2163;, - 3;2179,2178,2164;, - 3;1112,2174,2181;, - 3;1115,2179,2160;, - 3;1097,1095,2161;, - 3;1111,1098,2159;, - 3;1369,1372,807;, - 3;1374,1377,1378;, - 3;1382,1384,1386;, - 3;1371,1370,1386;, - 3;1379,812,1385;, - 3;808,1373,1385;, - 3;1387,1391,1393;, - 3;1395,818,814;, - 3;1380,1376,819;, - 3;811,809,813;, - 3;815,819,1376;, - 3;1394,1392,1375;, - 3;1389,1377,1374;, - 3;1396,1394,1386;, - 3;816,811,819;, - 3;1397,1369,810;, - 3;1398,822,823;, - 3;1399,1403,1404;, - 3;1402,825,826;, - 3;820,1412,827;, - 3;1400,1409,1410;, - 3;1408,1406,828;, - 3;1413,831,832;, - 3;1414,1418,1419;, - 3;1417,834,835;, - 3;829,840,836;, - 3;1415,1424,838;, - 3;1423,1421,837;, - 3;1425,843,844;, - 3;1426,1429,1430;, - 3;1428,844,846;, - 3;841,851,847;, - 3;1427,1435,849;, - 3;1434,1432,848;, - 3;1670,1673,1674;, - 3;1650,1670,1676;, - 3;1656,1652,1654;, - 3;1678,1658,1660;, - 3;1678,1680,1682;, - 3;1707,1712,1713;, - 3;1717,1715,1686;, - 3;1708,1721,1726;, - 3;1711,1725,1724;, - 3;1709,1718,1723;, - 3;1714,1724,1675;, - 3;1688,1686,1674;, - 3;1718,1689,1672;, - 3;2264,2266,2280;, - 3;2266,2284,2285;, - 3;2264,2281,2287;, - 3;2271,2273,2274;, - 3;2277,2275,2289;, - 3;2290,2289,2292;, - 3;2295,2293,2298;, - 3;2299,2298,2301;, - 3;2084,2089,1940;, - 3;2273,2271,1943;, - 3;2302,2301,2088;, - 3;2265,2271,2276;, - 3;2282,2280,2300;, - 3;2268,2278,2291;, - 3;2283,2291,2296;, - 3;2285,2297,2300;, - 3;2287,2281,2303;, - 3;2270,2288,2087;, - 3;2264,2269,1945;, - 3;571,1266,1278;, - 3;268,1245,1266;, - 3;1266,1831,1848;, - 3;1245,1809,1831;, - 3;610,653,575;, - 3;1279,1296,652;, - 3;1849,1852,1296;, - 3;1832,1833,1851;, - 3;1807,1815,1833;, - 3;1246,1252,1814;, - 3;1252,1246,269;, - 3;277,270,572;, - 3;612,713,715;, - 3;612,1281,1322;, - 3;618,621,1282;, - 3;618,625,626;, - 3;1285,1281,612;, - 3;629,634,635;, - 3;330,631,639;, - 3;623,620,632;, - 3;619,614,636;, - 3;616,640,637;, - 3;714,719,720;, - 3;1280,1297,1326;, - 3;717,721,654;, - 3;622,628,656;, - 3;1283,1299,1300;, - 3;624,660,657;, - 3;332,339,340;, - 3;1287,1301,1297;, - 3;1324,1327,719;, - 3;622,658,1298;, - 3;331,341,659;, - 3;616,655,338;, - 3;1712,1728,1720;, - 3;1727,1722,1684;, - 3;2115,2119,2120;, - 3;2122,2120,2341;, - 3;2348,2352,2399;, - 3;2124,2336,2338;, - 3;2336,2405,2407;, - 3;2400,2407,2405;, - 3;2304,2123,2345;, - 3;2339,2408,2406;, - 3;2127,2117,2123;, - 3;2128,2339,2337;, - 3;2357,2349,2403;, - 3;2408,2410,2404;, - 3;2306,2121,2118;, - 3;2121,2306,2358;, - 3;2308,2360,2409;, - 3;2305,2355,2360;, - 3;2340,2128,2131;, - 3;2308,2131,2127;, - 3;2346,2343,2350;, - 3;2409,2360,2357;, - 3;2125,2133,2132;, - 3;2127,2132,2133;, - 3;2347,2349,2357;, - 3;6189,6194,2307;, - 3;6190,2126,2338;, - 3;6198,2338,2407;, - 3;6194,6195,2359;, - 3;6199,2407,2400;, - 3;6196,6201,2399;, - 3;6195,6197,2353;, - 3;2361,2365,2366;, - 3;2362,31,2371;, - 3;2364,2372,2373;, - 3;2370,2368,2374;, - 3;2375,2376,2378;, - 3;2376,2375,2381;, - 3;2309,2375,2380;, - 3;2310,2381,2375;, - 3;2386,2390,2384;, - 3;2391,2392,2393;, - 3;2391,2395,2388;, - 3;2312,2386,2382;, - 3;2314,34,2392;, - 3;2314,2391,2387;, - 3;2385,2397,2379;, - 3;2398,2389,2396;, - 3;2398,2397,2385;, - 3;934,1613,1731;, - 3;1120,1732,1733;, - 3;1125,1733,1737;, - 3;1133,1737,1739;, - 3;1143,1740,1741;, - 3;1144,1741,1692;, - 3;1694,1034,1026;, - 3;1002,1034,1694;, - 3;954,1002,1662;, - 3;936,954,1614;, - 3;2197,1743,1738;, - 3;2065,2051,1663;, - 3;2065,1695,1697;, - 3;2198,2202,1744;, - 3;2054,1667,1663;, - 3;2057,2072,2204;, - 3;2073,2072,2057;, - 3;1744,2202,2075;, - 3;1698,1700,2075;, - 3;1734,1615,2039;, - 3;2041,2039,1615;, - 3;2204,2072,2077;, - 3;2072,2073,2079;, - 3;1703,1696,1664;, - 3;1703,1702,1699;, - 3;1735,2185,2186;, - 3;1738,1736,2186;, - 3;1618,1622,2043;, - 3;2055,2046,1620;, - 3;2058,2062,2060;, - 3;1666,1621,1623;, - 3;2057,2193,2195;, - 3;2049,2064,2195;, - 3;2049,2047,2062;, - 3;2057,2064,2062;, - 3;1619,1617,1624;, - 3;1664,1623,1624;, - 3;2205,2200,2192;, - 3;2074,2059,2052;, - 3;2078,2076,2201;, - 3;2206,2203,2199;, - 3;2073,2067,2070;, - 3;2080,2071,2076;, - 3;2061,2048,2042;, - 3;2063,2060,2045;, - 3;2063,2056,2053;, - 3;2194,2192,2187;, - 3;2189,2195,2188;, - 3;2050,2190,2184;, - 3;2048,2050,2040;, - 3;1615,1734,1731;, - 3;1735,1736,1733;, - 3;1736,1738,1737;, - 3;1738,1743,1739;, - 3;1742,1744,1741;, - 3;1744,1700,1692;, - 3;1694,1693,1701;, - 3;1669,1662,1694;, - 3;1625,1614,1662;, - 3;1616,1612,1614;, - 3;2134,1729,1747;, - 3;2139,2092,2093;, - 3;2135,2098,1705;, - 3;2145,2254,2208;, - 3;2096,2210,1745;, - 3;2140,2138,2101;, - 3;2091,2100,2096;, - 3;2143,2095,2097;, - 3;2141,2144,2134;, - 3;2138,2145,2099;, - 3;2138,2252,2254;, - 3;2255,2253,2211;, - 3;2101,2099,2208;, - 3;1746,2213,2251;, - 3;781,1338,1339;, - 3;1083,1059,1060;, - 3;782,752,1333;, - 3;790,791,753;, - 3;750,758,1335;, - 3;1084,789,757;, - 3;1058,756,750;, - 3;1087,1062,751;, - 3;1085,1088,781;, - 3;789,790,755;, - 3;789,786,791;, - 3;792,787,759;, - 3;757,755,753;, - 3;1336,761,785;, - 3;1969,1974,1339;, - 3;2146,2151,2102;, - 3;1970,1337,1333;, - 3;1978,1949,1950;, - 3;1947,1334,1335;, - 3;2147,2107,1953;, - 3;2106,2104,1947;, - 3;2149,1971,1948;, - 3;2148,1972,1969;, - 3;1973,1953,1949;, - 3;1973,1978,1979;, - 3;1980,1951,1955;, - 3;1953,1957,1950;, - 3;1336,1340,1977;, - 3;1302,1289,1288;, - 3;722,718,1290;, - 3;661,641,718;, - 3;664,643,642;, - 3;666,644,643;, - 3;669,646,645;, - 3;1307,1291,646;, - 3;1305,1288,1292;, - 3;304,334,342;, - 3;37,38,381;, - 3;308,345,346;, - 3;304,307,310;, - 3;38,39,383;, - 3;309,346,671;, - 3;305,311,577;, - 3;573,578,672;, - 3;335,337,38;, - 3;343,380,382;, - 3;335,37,379;, - 3;337,650,39;, - 3;650,674,383;, - 3;347,382,384;, - 3;579,314,315;, - 3;312,350,355;, - 3;313,40,675;, - 3;349,676,709;, - 3;317,357,710;, - 3;40,1834,1853;, - 3;676,1855,1859;, - 3;41,710,1860;, - 3;581,586,1840;, - 3;1836,1841,1861;, - 3;1253,1249,1247;, - 3;1258,1250,1249;, - 3;1258,1818,1810;, - 3;1260,1251,1812;, - 3;42,1259,1254;, - 3;42,1820,1816;, - 3;1257,1248,1251;, - 3;1817,1821,1813;, - 3;278,280,550;, - 3;279,43,123;, - 3;116,123,43;, - 3;553,556,44;, - 3;30,44,556;, - 3;551,558,45;, - 3;545,45,558;, - 3;552,281,46;, - 3;546,559,46;, - 3;281,122,124;, - 3;271,46,124;, - 3;557,555,549;, - 3;283,278,548;, - 3;543,557,45;, - 3;53,56,125;, - 3;53,54,58;, - 3;55,119,127;, - 3;118,125,284;, - 3;119,274,287;, - 3;272,286,288;, - 3;57,60,128;, - 3;126,128,289;, - 3;582,678,1310;, - 3;290,582,47;, - 3;47,1310,1856;, - 3;1264,47,1837;, - 3;677,583,575;, - 3;1311,679,652;, - 3;1857,1311,1296;, - 3;1838,1858,1851;, - 3;1823,1838,1833;, - 3;1265,1824,1814;, - 3;1252,276,291;, - 3;277,575,583;, - 3;680,684,726;, - 3;680,724,1330;, - 3;686,1317,1314;, - 3;686,689,694;, - 3;1317,686,680;, - 3;697,708,703;, - 3;351,354,706;, - 3;692,699,701;, - 3;688,702,704;, - 3;683,682,705;, - 3;725,728,720;, - 3;1313,1332,1326;, - 3;727,685,654;, - 3;690,658,656;, - 3;1315,1319,1300;, - 3;693,696,657;, - 3;354,351,340;, - 3;1318,1313,1297;, - 3;1331,725,719;, - 3;690,1316,1298;, - 3;352,692,659;, - 3;683,353,338;, - 3;2444,2447,2452;, - 3;2439,2446,2454;, - 3;2412,2439,2441;, - 3;2415,2414,2424;, - 3;2417,2415,2425;, - 3;2420,2419,2427;, - 3;2449,2420,2428;, - 3;2447,2451,2456;, - 3;2457,2453,2452;, - 3;2442,2441,2454;, - 3;2429,2423,2441;, - 3;2432,2425,2424;, - 3;2434,2426,2425;, - 3;2437,2428,2427;, - 3;2462,2455,2428;, - 3;2460,2452,2456;, - 3;2475,2479,2480;, - 3;2476,2465,2485;, - 3;2478,2486,2487;, - 3;2484,2482,2488;, - 3;2489,2490,2492;, - 3;2490,2489,2495;, - 3;2469,2489,2494;, - 3;2470,2495,2489;, - 3;2500,2504,2498;, - 3;2505,2506,2507;, - 3;2505,2509,2502;, - 3;2472,2500,2496;, - 3;2474,2468,2506;, - 3;2474,2505,2501;, - 3;2499,2511,2493;, - 3;2512,2503,2510;, - 3;2512,2511,2499;, - 3;2521,2534,2533;, - 3;2523,2533,2538;, - 3;2521,2527,2540;, - 3;2528,2531,2274;, - 3;2530,2542,2289;, - 3;2542,2547,2292;, - 3;2544,2548,2298;, - 3;2548,2550,2301;, - 3;2517,2515,1940;, - 3;2273,1941,2513;, - 3;2550,2519,2088;, - 3;2522,2525,2531;, - 3;2535,2551,2549;, - 3;2524,2537,2543;, - 3;2537,2539,2545;, - 3;2538,2533,2549;, - 3;2540,2520,2551;, - 3;2526,2516,2518;, - 3;2521,2529,2514;, - 3;2584,2554,2555;, - 3;2585,2589,2590;, - 3;2588,2557,2558;, - 3;2552,2598,2559;, - 3;2586,2595,2596;, - 3;2594,2592,2560;, - 3;2599,2563,2564;, - 3;2600,2604,2605;, - 3;2603,2566,2567;, - 3;2561,2572,2568;, - 3;2601,2610,2570;, - 3;2609,2607,2569;, - 3;2611,2575,2576;, - 3;2612,2615,2616;, - 3;2614,2576,2578;, - 3;2573,2583,2579;, - 3;2613,2621,2581;, - 3;2620,2618,2580;, - 3;2654,2624,2625;, - 3;2655,2659,2660;, - 3;2658,2627,2628;, - 3;2622,2668,2629;, - 3;2656,2665,2666;, - 3;2664,2662,2630;, - 3;2669,2633,2634;, - 3;2670,2674,2675;, - 3;2673,2636,2637;, - 3;2631,2642,2638;, - 3;2671,2680,2640;, - 3;2679,2677,2639;, - 3;2681,2645,2646;, - 3;2682,2685,2686;, - 3;2684,2646,2648;, - 3;2643,2653,2649;, - 3;2683,2691,2651;, - 3;2690,2688,2650;, - 3;2724,2694,2695;, - 3;2725,2729,2730;, - 3;2728,2697,2698;, - 3;2692,2738,2699;, - 3;2726,2735,2736;, - 3;2734,2732,2700;, - 3;2739,2703,2704;, - 3;2740,2744,2745;, - 3;2743,2706,2707;, - 3;2701,2712,2708;, - 3;2741,2750,2710;, - 3;2749,2747,2709;, - 3;2751,2715,2716;, - 3;2752,2755,2756;, - 3;2754,2716,2718;, - 3;2713,2723,2719;, - 3;2753,2761,2721;, - 3;2760,2758,2720;, - 3;2794,2764,2765;, - 3;2795,2799,2800;, - 3;2798,2767,2768;, - 3;2762,2808,2769;, - 3;2796,2805,2806;, - 3;2804,2802,2770;, - 3;2809,2773,2774;, - 3;2810,2814,2815;, - 3;2813,2776,2777;, - 3;2771,2782,2778;, - 3;2811,2820,2780;, - 3;2819,2817,2779;, - 3;2821,2785,2786;, - 3;2822,2825,2826;, - 3;2824,2786,2788;, - 3;2783,2793,2789;, - 3;2823,2831,2791;, - 3;2830,2828,2790;, - 3;2853,2855,2858;, - 3;2850,2854,2860;, - 3;2832,2850,2851;, - 3;2834,2833,2839;, - 3;2835,2834,2840;, - 3;2837,2836,2842;, - 3;2856,2837,2843;, - 3;2855,2857,2862;, - 3;2863,2859,2858;, - 3;2852,2851,2860;, - 3;2844,2838,2851;, - 3;2846,2840,2839;, - 3;2847,2841,2840;, - 3;2849,2843,2842;, - 3;2866,2861,2843;, - 3;2865,2858,2862;, - 3;2889,2891,2894;, - 3;2886,2890,2896;, - 3;2868,2886,2887;, - 3;2870,2869,2875;, - 3;2871,2870,2876;, - 3;2873,2872,2878;, - 3;2892,2873,2879;, - 3;2891,2893,2898;, - 3;2899,2895,2894;, - 3;2888,2887,2896;, - 3;2880,2874,2887;, - 3;2882,2876,2875;, - 3;2883,2877,2876;, - 3;2885,2879,2878;, - 3;2902,2897,2879;, - 3;2901,2894,2898;, - 3;2928,2931,2933;, - 3;2938,2943,2933;, - 3;2936,2945,2946;, - 3;2941,2940,2904;, - 3;2912,2917,2918;, - 3;2922,2920,2918;, - 3;2915,2914,2948;, - 3;2926,2909,2910;, - 3;2905,2947,2949;, - 3;2946,2945,2950;, - 3;2944,2907,2908;, - 3;2906,2904,2910;, - 3;2954,2961,2978;, - 3;2960,2964,2981;, - 3;2963,2967,2984;, - 3;2966,2970,2987;, - 3;2969,2958,2972;, - 3;2957,2955,2976;, - 3;2992,2999,3016;, - 3;2998,3002,3019;, - 3;3001,3005,3022;, - 3;3004,3008,3025;, - 3;3007,2996,3010;, - 3;2995,2993,3014;, - 3;4008,4663,4680;, - 3;4013,3985,3980;, - 3;4009,3988,4638;, - 3;4019,4106,4096;, - 3;3986,4098,4678;, - 3;4014,4012,3991;, - 3;3984,3990,3986;, - 3;4017,3982,3987;, - 3;4015,4018,4008;, - 3;4012,4019,3989;, - 3;4012,4104,4106;, - 3;4107,4105,4099;, - 3;3991,3989,4096;, - 3;4679,4101,4103;, - 3;3992,3029,3028;, - 3;3689,3992,5175;, - 3;3030,3689,4847;, - 3;446,3414,3711;, - 3;762,3712,3032;, - 3;446,7,3033;, - 3;420,3396,3686;, - 3;1958,4872,4869;, - 3;425,9,3176;, - 3;3399,3177,3713;, - 3;1917,736,3686;, - 3;4871,3688,3713;, - 3;421,425,3398;, - 3;3687,3397,3399;, - 3;3687,3688,4871;, - 3;1918,4836,4872;, - 3;4020,4684,4682;, - 3;3179,3183,3091;, - 3;3088,3092,3093;, - 3;3714,3432,3428;, - 3;3430,3435,3433;, - 3;3090,3093,3094;, - 3;3435,3438,3439;, - 3;3431,3716,3415;, - 3;3216,3415,3178;, - 3;3436,3431,3216;, - 3;3217,3216,3213;, - 3;3436,3217,3218;, - 3;3217,3089,3215;, - 3;3718,3417,3416;, - 3;3181,3180,3416;, - 3;3439,3438,3219;, - 3;3220,3219,3214;, - 3;3221,3419,3184;, - 3;3082,3187,3184;, - 3;3422,3420,3426;, - 3;3423,3425,3188;, - 3;3419,3221,3222;, - 3;3185,3190,3084;, - 3;3096,3097,3222;, - 3;3082,3086,3097;, - 3;3161,3193,3223;, - 3;3163,3169,3206;, - 3;3208,3211,3227;, - 3;3225,3229,3197;, - 3;3195,3199,3172;, - 3;3167,3165,3170;, - 3;3175,3161,3201;, - 3;3207,3211,3208;, - 3;3192,3162,3173;, - 3;3193,3200,3228;, - 3;3223,3230,3210;, - 3;3161,3175,3168;, - 3;3212,3201,3210;, - 3;3175,3212,3206;, - 3;3721,3690,3993;, - 3;3692,3166,3204;, - 3;3998,3209,3226;, - 3;4025,3225,3194;, - 3;3725,3196,3171;, - 3;3693,3695,3171;, - 3;3205,3209,3998;, - 3;3696,4001,3993;, - 3;3722,3725,3695;, - 3;4022,3994,3998;, - 3;3723,4023,4025;, - 3;3697,3694,3997;, - 3;4000,3996,3998;, - 3;3691,3695,3693;, - 3;3074,3154,3150;, - 3;3067,3070,3363;, - 3;3071,3067,3130;, - 3;3364,3070,3078;, - 3;3404,3080,3075;, - 3;3136,3160,3156;, - 3;3159,3034,3406;, - 3;3139,3158,3407;, - 3;3137,3140,3368;, - 3;3369,3409,4837;, - 3;4797,4802,3372;, - 3;4838,4842,4799;, - 3;1881,4801,4840;, - 3;4839,3410,3411;, - 3;1929,4843,3412;, - 3;3408,3371,3373;, - 3;442,3413,3373;, - 3;12,154,3143;, - 3;3376,3375,4800;, - 3;13,4804,4801;, - 3;155,398,3374;, - 3;3142,3145,3375;, - 3;5118,5214,5211;, - 3;5118,5119,4688;, - 3;4691,4688,5119;, - 3;5122,5118,4686;, - 3;4108,4112,4688;, - 3;4694,4687,6193;, - 3;1765,4696,6193;, - 3;5123,4695,4697;, - 3;2223,5126,4697;, - 3;5215,5221,5217;, - 3;2327,5217,5219;, - 3;2224,5127,5218;, - 3;5213,5218,5127;, - 3;4687,4690,4698;, - 3;6192,6193,4698;, - 3;2329,5222,5126;, - 3;5123,5126,5220;, - 3;1770,4701,5130;, - 3;5125,5131,4700;, - 3;5121,5129,5131;, - 3;2229,5130,5128;, - 3;4111,4110,4116;, - 3;4689,4113,4115;, - 3;4692,4700,4117;, - 3;4698,4702,1771;, - 3;3440,3450,3446;, - 3;4703,4705,4120;, - 3;5132,5134,4705;, - 3;4120,4124,4122;, - 3;3440,4122,4124;, - 3;1182,1780,4707;, - 3;4127,4126,4707;, - 3;1780,14,5136;, - 3;4708,4707,5136;, - 3;15,1784,4710;, - 3;5140,5139,4710;, - 3;491,496,3454;, - 3;3454,3459,3455;, - 3;502,3461,3460;, - 3;3463,3460,3461;, - 3;513,3470,3468;, - 3;514,3468,3471;, - 3;3447,3478,3473;, - 3;527,518,3471;, - 3;4129,3459,3454;, - 3;1189,4131,3454;, - 3;1189,1182,4126;, - 3;4129,4131,4126;, - 3;4132,4136,4135;, - 3;1196,4134,4135;, - 3;1196,504,3460;, - 3;4132,4134,3460;, - 3;1197,4135,4710;, - 3;4711,4710,4135;, - 3;513,492,3453;, - 3;3472,3469,3474;, - 3;503,527,3479;, - 3;4123,3441,3458;, - 3;3441,3445,3456;, - 3;3444,3475,3453;, - 3;3475,3468,3470;, - 3;4119,4123,4130;, - 3;4704,4119,4128;, - 3;5133,4704,4709;, - 3;4125,4121,4137;, - 3;4121,4706,4712;, - 3;4706,5135,5141;, - 3;3451,4125,4133;, - 3;3448,3451,3464;, - 3;3477,3449,3467;, - 3;3471,3477,3462;, - 3;4138,4143,4715;, - 3;4714,4717,4720;, - 3;4144,4719,4721;, - 3;4150,4153,4152;, - 3;4140,4149,4722;, - 3;4139,4150,4151;, - 3;4139,4145,4153;, - 3;4153,4145,4147;, - 3;4142,4151,4152;, - 3;4154,4158,5144;, - 3;4154,4164,4160;, - 3;4161,4165,1228;, - 3;5145,4157,1230;, - 3;5143,2247,1232;, - 3;4157,1230,2246;, - 3;5143,2247,1232;, - 3;4155,1232,1229;, - 3;1231,4159,4162;, - 3;5146,3036,5225;, - 3;5224,5226,17;, - 3;5147,5224,2335;, - 3;3079,3069,68;, - 3;82,174,3153;, - 3;3151,3155,175;, - 3;3402,3152,176;, - 3;3365,3405,445;, - 3;401,156,3131;, - 3;156,157,3134;, - 3;158,69,3072;, - 3;3068,3073,70;, - 3;3069,3068,71;, - 3;3077,3081,80;, - 3;3405,3402,444;, - 3;4026,3037,19;, - 3;3038,4026,1082;, - 3;5015,4682,1797;, - 3;24,1799,4684;, - 3;3434,3439,529;, - 3;3719,3428,476;, - 3;3091,3183,218;, - 3;3093,3092,102;, - 3;3220,252,529;, - 3;3424,3426,25;, - 3;3189,3424,461;, - 3;3085,3191,220;, - 3;3098,3085,89;, - 3;3429,3433,474;, - 3;3094,3093,104;, - 3;3220,3095,105;, - 3;4683,4685,1800;, - 3;3418,462,219;, - 3;3418,3720,779;, - 3;4873,4875,1967;, - 3;4875,5016,2109;, - 3;5017,2113,2109;, - 3;4874,1965,2114;, - 3;4848,4850,4875;, - 3;4850,4988,5016;, - 3;4988,4990,5017;, - 3;4849,4874,5018;, - 3;4805,5157,2256;, - 3;4844,1934,2263;, - 3;4845,5159,5154;, - 3;2263,2256,5156;, - 3;1935,4846,4809;, - 3;3146,3149,4808;, - 3;27,1892,4810;, - 3;28,3147,4807;, - 3;4485,4491,4487;, - 3;3861,4487,4559;, - 3;3925,4559,4564;, - 3;4490,4486,4493;, - 3;4488,4490,4492;, - 3;4560,4489,4495;, - 3;4565,4561,4567;, - 3;4565,4568,4569;, - 3;4563,4569,3928;, - 3;3927,3929,3864;, - 3;3863,3865,4493;, - 3;4496,3866,4500;, - 3;3866,3930,4570;, - 3;3930,4576,4573;, - 3;4499,4492,4493;, - 3;4501,4494,4492;, - 3;4571,4566,4495;, - 3;4574,4568,4567;, - 3;4574,4575,4569;, - 3;4575,3932,3928;, - 3;3931,3868,3864;, - 3;3867,4497,4493;, - 3;4503,4512,4508;, - 3;4513,4506,4508;, - 3;4510,4505,4521;, - 3;4517,3872,3869;, - 3;4379,4387,4385;, - 3;4389,4394,4385;, - 3;4383,4525,4523;, - 3;4392,4391,3875;, - 3;3870,3876,4524;, - 3;4521,4523,4525;, - 3;4520,4526,3874;, - 3;3872,3873,3875;, - 3;3797,3743,3738;, - 3;4274,4893,4888;, - 3;4920,4399,4395;, - 3;3821,3827,3825;, - 3;3825,4405,4402;, - 3;3739,4282,4369;, - 3;4284,4283,3740;, - 3;3822,4401,4403;, - 3;4404,4406,4414;, - 3;4924,4395,4412;, - 3;4370,4281,4280;, - 3;4281,4286,4275;, - 3;4416,4413,4396;, - 3;4408,4404,4411;, - 3;3829,3835,3832;, - 3;4925,4932,4929;, - 3;4420,3830,3831;, - 3;4421,4423,4427;, - 3;4931,4426,4428;, - 3;3797,3799,3831;, - 3;4927,4929,4890;, - 3;3800,4369,4430;, - 3;4429,4424,4431;, - 3;4371,4374,4432;, - 3;4372,4889,4930;, - 3;3827,3835,3829;, - 3;3825,3830,4420;, - 3;4406,4421,4425;, - 3;4415,4426,4931;, - 3;4924,4932,4925;, - 3;3801,3803,3749;, - 3;4288,4294,4899;, - 3;4933,4936,4437;, - 3;3836,4440,3842;, - 3;3842,4440,4443;, - 3;3750,3804,4375;, - 3;4298,3748,3751;, - 3;3837,4449,4444;, - 3;4445,4454,4450;, - 3;4936,4451,4452;, - 3;4376,4378,4293;, - 3;4297,4293,4289;, - 3;4455,4436,4438;, - 3;4446,4458,4454;, - 3;3844,3850,3848;, - 3;4937,4943,4941;, - 3;4459,4462,3850;, - 3;4460,4468,4464;, - 3;4940,4942,4465;, - 3;3801,3848,3850;, - 3;4943,4898,4901;, - 3;3804,3850,4469;, - 3;4466,4474,4470;, - 3;4376,4471,4472;, - 3;4377,4473,4942;, - 3;3840,3843,3844;, - 3;3842,4441,4459;, - 3;4442,4450,4468;, - 3;4451,4936,4940;, - 3;4936,4933,4937;, - 3;3849,3833,3834;, - 3;3847,3834,3828;, - 3;3841,3828,3823;, - 3;3839,3824,4409;, - 3;4448,4410,4418;, - 3;4457,4419,4398;, - 3;4435,4398,4922;, - 3;4935,4923,4926;, - 3;4938,4926,4928;, - 3;4944,4928,4892;, - 3;4897,4894,4276;, - 3;4291,4277,4285;, - 3;4301,4287,3742;, - 3;3747,3744,3798;, - 3;3802,3798,3833;, - 3;4082,4087,4077;, - 3;3954,3935,3933;, - 3;3954,3957,3963;, - 3;4083,4090,4088;, - 3;3938,3943,3933;, - 3;3944,3966,4092;, - 3;3967,3966,3944;, - 3;4088,4090,3972;, - 3;3964,3969,3972;, - 3;4063,3879,3877;, - 3;3882,3877,3879;, - 3;4092,3966,3974;, - 3;3966,3967,3976;, - 3;3978,3958,3934;, - 3;3978,3971,3965;, - 3;4064,4068,4070;, - 3;4077,4069,4070;, - 3;3884,3892,3886;, - 3;3939,3889,3890;, - 3;3945,3949,3950;, - 3;3942,3891,3895;, - 3;3944,4078,4080;, - 3;3896,3953,4080;, - 3;3896,3893,3949;, - 3;3944,3953,3949;, - 3;3885,3881,3898;, - 3;3934,3895,3898;, - 3;4093,4085,4076;, - 3;3968,3946,3936;, - 3;3975,3973,4089;, - 3;4094,4091,4084;, - 3;3967,3956,3961;, - 3;3977,3962,3973;, - 3;3951,3894,3883;, - 3;3952,3950,3888;, - 3;3952,3940,3937;, - 3;4079,4076,4071;, - 3;4073,4080,4072;, - 3;3897,4074,4067;, - 3;3894,3897,3878;, - 3;4200,4223,4221;, - 3;3661,3668,4222;, - 3;3539,3592,3668;, - 3;3542,3593,3591;, - 3;3544,3595,3593;, - 3;3547,3596,3594;, - 3;4205,4225,3596;, - 3;4203,4221,4224;, - 3;3282,3313,3296;, - 3;3351,3352,3343;, - 3;3272,3299,3300;, - 3;3282,3271,3274;, - 3;3352,3353,3345;, - 3;3273,3300,3553;, - 3;3284,3275,3512;, - 3;3524,3513,3554;, - 3;3312,3314,3352;, - 3;3297,3342,3344;, - 3;3312,3351,3341;, - 3;3314,3601,3353;, - 3;3601,3556,3345;, - 3;3301,3344,3346;, - 3;3514,3281,3276;, - 3;3279,3307,3302;, - 3;3280,3520,3557;, - 3;3306,3558,3537;, - 3;3278,3304,3538;, - 3;3520,4747,4764;, - 3;3558,4766,4767;, - 3;3510,3538,4768;, - 3;3516,3519,4751;, - 3;4749,4752,4769;, - 3;4166,4182,4180;, - 3;4171,4183,4182;, - 3;4171,4725,4732;, - 3;4173,4184,4734;, - 3;4177,4172,4167;, - 3;4177,4727,4723;, - 3;4170,4181,4184;, - 3;4724,4728,4735;, - 3;3231,3233,3482;, - 3;3232,3235,3102;, - 3;3108,3102,3235;, - 3;3485,3488,3238;, - 3;3040,3238,3488;, - 3;3483,3491,3490;, - 3;3495,3490,3491;, - 3;3484,3234,3239;, - 3;3497,3492,3239;, - 3;3234,3101,3103;, - 3;3249,3239,3103;, - 3;3489,3487,3481;, - 3;3237,3231,3480;, - 3;3494,3489,3490;, - 3;3059,3054,3104;, - 3;3059,3061,3056;, - 3;3060,3111,3106;, - 3;3110,3104,3240;, - 3;3111,3253,3243;, - 3;3251,3242,3244;, - 3;3055,3058,3107;, - 3;3105,3107,3245;, - 3;4527,4478,4475;, - 3;4528,4532,3903;, - 3;4531,4476,3851;, - 3;4529,3902,3853;, - 3;3901,3905,3852;, - 3;3908,4538,4540;, - 3;3915,4541,4543;, - 3;3918,4544,4578;, - 3;3921,4579,4581;, - 3;3924,4582,4534;, - 3;3912,4535,4537;, - 3;4479,4907,4902;, - 3;4480,4484,3858;, - 3;4483,4904,3805;, - 3;4905,3810,3806;, - 3;4481,3857,3808;, - 3;3856,3860,3807;, - 3;4033,4042,4039;, - 3;4043,5061,5056;, - 3;3679,3684,4813;, - 3;5062,5071,5066;, - 3;4811,4813,4818;, - 3;4049,3813,3811;, - 3;3815,3811,3813;, - 3;4044,4052,3812;, - 3;4047,3820,3814;, - 3;5059,4044,3819;, - 3;4909,4908,3819;, - 3;5057,4910,3820;, - 3;3818,3820,4910;, - 3;5072,5059,4908;, - 3;4914,4912,4908;, - 3;5074,4916,4910;, - 3;4911,4910,4916;, - 3;5075,5073,4913;, - 3;4919,4917,4913;, - 3;3680,3815,3817;, - 3;3683,3818,4911;, - 3;3681,4812,4909;, - 3;4814,4911,4918;, - 3;4816,4820,4919;, - 3;4812,4817,4914;, - 3;4052,4044,4055;, - 3;4045,4048,4058;, - 3;4050,4062,4059;, - 3;4051,4054,4061;, - 3;5059,5072,5079;, - 3;5073,5075,5081;, - 3;5057,5084,5082;, - 3;5060,5078,5083;, - 3;4053,4055,4041;, - 3;4062,4038,4040;, - 3;4054,4035,4037;, - 3;5076,5079,5069;, - 3;5080,5081,5067;, - 3;5084,5065,5068;, - 3;4057,4060,5085;, - 3;4059,4040,5065;, - 3;4042,5062,5064;, - 3;4055,5076,5063;, - 3;4302,3756,3752;, - 3;4307,4315,4311;, - 3;4314,4308,4319;, - 3;4305,4317,4319;, - 3;4312,4316,4318;, - 3;3753,3757,4318;, - 3;4320,3759,4326;, - 3;4328,4326,3759;, - 3;4313,3758,3764;, - 3;3755,3764,3758;, - 3;3760,4322,4310;, - 3;4327,4319,4308;, - 3;4321,4325,4307;, - 3;4329,4303,4319;, - 3;3762,3760,3764;, - 3;4330,3763,3756;, - 3;4331,4336,3768;, - 3;4332,4342,4337;, - 3;4335,4339,3771;, - 3;3766,3770,3772;, - 3;4333,3767,4344;, - 3;4341,4345,3773;, - 3;4346,4351,3777;, - 3;4347,4357,4352;, - 3;4350,4354,3780;, - 3;3775,3779,3781;, - 3;4348,3776,3784;, - 3;4356,3785,3782;, - 3;4358,4362,3789;, - 3;4359,4368,4363;, - 3;4362,4365,3791;, - 3;3787,3790,3792;, - 3;4360,3788,3795;, - 3;4367,3796,3793;, - 3;4603,4609,4607;, - 3;4583,4588,4609;, - 3;4589,4594,4586;, - 3;4611,4613,4592;, - 3;4611,4618,4615;, - 3;4640,4651,4646;, - 3;4649,4621,4619;, - 3;4641,4645,4659;, - 3;4644,4648,4657;, - 3;4642,4652,4656;, - 3;4648,4620,4608;, - 3;4621,4605,4607;, - 3;4650,4656,4606;, - 3;5160,5177,5176;, - 3;5162,5176,5181;, - 3;5160,5166,5183;, - 3;5167,5173,5170;, - 3;5172,5186,5185;, - 3;5186,5193,5188;, - 3;5190,5195,5194;, - 3;5195,5198,5197;, - 3;4991,4855,4851;, - 3;5169,4852,4853;, - 3;5198,4993,4996;, - 3;5161,5164,5173;, - 3;5178,5199,5196;, - 3;5163,5180,5187;, - 3;5180,5182,5191;, - 3;5181,5176,5196;, - 3;5183,4994,5199;, - 3;5165,4856,4992;, - 3;5160,5168,4854;, - 3;3521,3560,4211;, - 3;3246,3521,4199;, - 3;4199,4211,4770;, - 3;4178,4199,4753;, - 3;3559,3522,3525;, - 3;4212,3561,3603;, - 3;4771,4212,4229;, - 3;4754,4772,4774;, - 3;4730,4754,4755;, - 3;4179,4731,4737;, - 3;4185,3255,3247;, - 3;3254,3525,3522;, - 3;3562,3566,3665;, - 3;3562,3663,4255;, - 3;3568,4218,4215;, - 3;3568,3571,3576;, - 3;4218,3568,3562;, - 3;3579,3590,3585;, - 3;3308,3311,3588;, - 3;3574,3581,3583;, - 3;3570,3584,3586;, - 3;3565,3564,3587;, - 3;3664,3667,3670;, - 3;4214,4257,4259;, - 3;3666,3567,3604;, - 3;3572,3608,3606;, - 3;4216,4220,4233;, - 3;3575,3578,3607;, - 3;3311,3308,3318;, - 3;4219,4214,4230;, - 3;4256,3664,3669;, - 3;3572,4217,4232;, - 3;3309,3574,3610;, - 3;3565,3310,3317;, - 3;4643,4640,4654;, - 3;4661,4615,4618;, - 3;5019,5026,5024;, - 3;5026,5238,5232;, - 3;5239,5282,5278;, - 3;5028,5030,5229;, - 3;5227,5229,5286;, - 3;5279,5283,5284;, - 3;5200,5246,5235;, - 3;5230,5228,5285;, - 3;5031,5200,5027;, - 3;5032,5029,5228;, - 3;5248,5289,5280;, - 3;5287,5285,5281;, - 3;5202,5033,5023;, - 3;5025,5234,5249;, - 3;5204,5231,5288;, - 3;5201,5204,5251;, - 3;5231,5204,5035;, - 3;5204,5201,5031;, - 3;5236,5239,5242;, - 3;5288,5289,5248;, - 3;5029,5032,5036;, - 3;5031,5021,5037;, - 3;5237,5247,5248;, - 3;6189,5034,5203;, - 3;6190,6198,5229;, - 3;6198,6199,5286;, - 3;6194,5203,5250;, - 3;6199,6200,5279;, - 3;6196,5241,5278;, - 3;6195,5250,5244;, - 3;5252,5261,5257;, - 3;5253,5256,2371;, - 3;5255,5259,2373;, - 3;5260,32,2374;, - 3;5262,2380,2378;, - 3;5263,5269,5265;, - 3;5205,33,2380;, - 3;5206,5205,5262;, - 3;5270,5266,5267;, - 3;5275,5276,2393;, - 3;5275,5271,5273;, - 3;5208,5207,5266;, - 3;5210,5275,2392;, - 3;5210,5209,5271;, - 3;5268,5264,2379;, - 3;2398,2394,5277;, - 3;2398,5274,5268;, - 3;3879,4063,4664;, - 3;4064,4069,4666;, - 3;4069,4077,4670;, - 3;4077,4087,4672;, - 3;4086,4088,4674;, - 3;4088,3969,4625;, - 3;4627,4626,3970;, - 3;3948,4595,4627;, - 3;3899,4547,4595;, - 3;3880,4546,4547;, - 3;5101,5096,4671;, - 3;4972,4628,4596;, - 3;4972,4977,4630;, - 3;5102,4676,4677;, - 3;4961,4958,4596;, - 3;4964,5097,5108;, - 3;4980,4965,4964;, - 3;4677,4633,4982;, - 3;4631,4978,4982;, - 3;4667,5088,4946;, - 3;4948,4551,4548;, - 3;5108,5110,4984;, - 3;4979,4984,4986;, - 3;4636,4602,4597;, - 3;4636,4629,4632;, - 3;4668,4669,5090;, - 3;4671,5096,5090;, - 3;4551,4948,4950;, - 3;4962,4600,4554;, - 3;4965,4970,4967;, - 3;4599,4597,4556;, - 3;4964,4971,5099;, - 3;4956,5093,5099;, - 3;4956,4971,4969;, - 3;4964,4965,4969;, - 3;4552,4556,4557;, - 3;4597,4602,4557;, - 3;5109,5098,5095;, - 3;4981,4974,4959;, - 3;4985,5111,5106;, - 3;5110,5108,5104;, - 3;4980,4986,4975;, - 3;4987,4985,4983;, - 3;4968,4953,4949;, - 3;4970,4963,4952;, - 3;4970,4965,4960;, - 3;5098,5100,5091;, - 3;5093,5089,5092;, - 3;4957,4947,5087;, - 3;4955,4949,4947;, - 3;4548,4545,4664;, - 3;4668,4665,4666;, - 3;4669,4666,4670;, - 3;4671,4670,4672;, - 3;4676,4673,4674;, - 3;4677,4674,4625;, - 3;4627,4637,4635;, - 3;4601,4637,4627;, - 3;4558,4601,4595;, - 3;4550,4558,4547;, - 3;5038,5148,4680;, - 3;5043,5048,5000;, - 3;5039,4662,4638;, - 3;5049,5006,5112;, - 3;5004,4639,4678;, - 3;5044,4999,5008;, - 3;4998,5002,5004;, - 3;5046,5040,5005;, - 3;5045,5041,5038;, - 3;5042,5008,5006;, - 3;5042,5049,5152;, - 3;5153,5113,5115;, - 3;5008,5117,5112;, - 3;4679,4681,5151;, - 3;3726,3729,4272;, - 3;4027,4032,4005;, - 3;3727,4271,4266;, - 3;3735,3704,3702;, - 3;3700,4267,4268;, - 3;4028,4004,3706;, - 3;4003,4007,3700;, - 3;4030,3728,3701;, - 3;4029,3733,3726;, - 3;3734,3706,3704;, - 3;3734,3735,3736;, - 3;3737,3703,3708;, - 3;3706,3710,3702;, - 3;4269,4273,3732;, - 3;4876,4270,4272;, - 3;5050,5014,5009;, - 3;4877,4859,4266;, - 3;4885,4886,4861;, - 3;4857,4865,4268;, - 3;5051,4880,4864;, - 3;5013,4863,4857;, - 3;5054,5011,4858;, - 3;5052,5055,4876;, - 3;4880,4885,4860;, - 3;4880,4883,4886;, - 3;4887,4884,4866;, - 3;4864,4860,4861;, - 3;4269,4868,4882;, - 3;4235,4238,4221;, - 3;3672,4237,4222;, - 3;3611,3672,3668;, - 3;3614,3613,3591;, - 3;3616,3614,3593;, - 3;3619,3618,3594;, - 3;4240,3619,3596;, - 3;4238,4242,4224;, - 3;3282,3286,3320;, - 3;3043,3358,3359;, - 3;3285,3288,3324;, - 3;3282,3283,3287;, - 3;3044,3359,3361;, - 3;3288,3528,3621;, - 3;3284,3523,3526;, - 3;3524,3600,3622;, - 3;3312,3043,3044;, - 3;3322,3325,3360;, - 3;3312,3323,3358;, - 3;3315,3044,3045;, - 3;3601,3045,3361;, - 3;3325,3624,3362;, - 3;3529,3536,3293;, - 3;3291,3295,3333;, - 3;3292,3328,3625;, - 3;3327,3335,3659;, - 3;3294,3047,3660;, - 3;3046,3625,4775;, - 3;3626,3659,4781;, - 3;3047,4761,4782;, - 3;3531,4758,4762;, - 3;4757,4777,4783;, - 3;4186,4190,4180;, - 3;4191,4186,4182;, - 3;4191,4183,4732;, - 3;4193,4743,4734;, - 3;3048,4188,4187;, - 3;3048,4192,4739;, - 3;4189,4196,4184;, - 3;4740,4733,4735;, - 3;3256,3499,3500;, - 3;3257,3114,3115;, - 3;3108,3039,3049;, - 3;3503,3261,3050;, - 3;3040,3493,3506;, - 3;3501,3498,3051;, - 3;3495,3496,3508;, - 3;3502,3509,3052;, - 3;3497,3249,3052;, - 3;3259,3052,3116;, - 3;3249,3109,3116;, - 3;3507,3051,3498;, - 3;3260,3505,3499;, - 3;3494,3495,3051;, - 3;3059,3110,3117;, - 3;3059,3062,3064;, - 3;3060,3066,3119;, - 3;3110,3250,3262;, - 3;3111,3119,3265;, - 3;3251,3252,3266;, - 3;3063,3118,3120;, - 3;3118,3264,3267;, - 3;3532,3053,4243;, - 3;3268,4197,3053;, - 3;3053,4759,4778;, - 3;4197,4746,4759;, - 3;3628,3602,3525;, - 3;4244,4229,3603;, - 3;4779,4773,4229;, - 3;4760,4755,4774;, - 3;4744,4736,4755;, - 3;4198,4185,4737;, - 3;4185,4198,3269;, - 3;3254,3270,3533;, - 3;3630,3674,3676;, - 3;3630,4246,4263;, - 3;3636,3639,4247;, - 3;3636,3643,3644;, - 3;4250,4246,3630;, - 3;3647,3652,3653;, - 3;3329,3649,3657;, - 3;3641,3638,3650;, - 3;3637,3632,3654;, - 3;3634,3658,3655;, - 3;3675,3669,3670;, - 3;4245,4230,4259;, - 3;3678,3671,3604;, - 3;3640,3646,3606;, - 3;4248,4231,4233;, - 3;3642,3609,3607;, - 3;3331,3316,3318;, - 3;4252,4234,4230;, - 3;4265,4260,3669;, - 3;3640,3608,4232;, - 3;3330,3319,3610;, - 3;3634,3605,3317;, - 3;5323,5333,5331;, - 3;5318,5320,5332;, - 3;5291,5303,5320;, - 3;5294,5304,5302;, - 3;5296,5306,5304;, - 3;5299,5307,5305;, - 3;5328,5335,5307;, - 3;5326,5331,5334;, - 3;5336,5339,5331;, - 3;5321,5338,5332;, - 3;5308,5321,5320;, - 3;5311,5310,5302;, - 3;5313,5311,5304;, - 3;5316,5315,5305;, - 3;5341,5316,5307;, - 3;5339,5343,5334;, - 3;5350,5359,5355;, - 3;5351,5354,2485;, - 3;5353,5357,2487;, - 3;5358,2466,2488;, - 3;5360,2494,2492;, - 3;5361,5367,5363;, - 3;5344,2467,2494;, - 3;5345,5344,5360;, - 3;5368,5364,5365;, - 3;5373,5374,2507;, - 3;5373,5369,5371;, - 3;5347,5346,5364;, - 3;5349,5373,2506;, - 3;5349,5348,5369;, - 3;5366,5362,2493;, - 3;2512,2508,5375;, - 3;2512,5372,5366;, - 3;5384,5386,5396;, - 3;5386,5400,5401;, - 3;5384,5397,5403;, - 3;5391,5169,5170;, - 3;5394,5171,5185;, - 3;5405,5185,5188;, - 3;5408,5189,5194;, - 3;5411,5194,5197;, - 3;5380,4995,4851;, - 3;5169,5391,5377;, - 3;5413,5197,4996;, - 3;5385,5391,5393;, - 3;5398,5396,5412;, - 3;5388,5395,5406;, - 3;5399,5406,5409;, - 3;5401,5410,5412;, - 3;5403,5397,5414;, - 3;5390,5404,5383;, - 3;5384,5389,5379;, - 3;5447,5452,5418;, - 3;5448,5458,5453;, - 3;5451,5455,5421;, - 3;5416,5420,5422;, - 3;5449,5417,5460;, - 3;5457,5461,5423;, - 3;5462,5467,5427;, - 3;5463,5473,5468;, - 3;5466,5470,5430;, - 3;5425,5429,5431;, - 3;5464,5426,5434;, - 3;5472,5435,5432;, - 3;5474,5478,5439;, - 3;5475,5484,5479;, - 3;5478,5481,5441;, - 3;5437,5440,5442;, - 3;5476,5438,5445;, - 3;5483,5446,5443;, - 3;5517,5522,5488;, - 3;5518,5528,5523;, - 3;5521,5525,5491;, - 3;5486,5490,5492;, - 3;5519,5487,5530;, - 3;5527,5531,5493;, - 3;5532,5537,5497;, - 3;5533,5543,5538;, - 3;5536,5540,5500;, - 3;5495,5499,5501;, - 3;5534,5496,5504;, - 3;5542,5505,5502;, - 3;5544,5548,5509;, - 3;5545,5554,5549;, - 3;5548,5551,5511;, - 3;5507,5510,5512;, - 3;5546,5508,5515;, - 3;5553,5516,5513;, - 3;5587,5592,5558;, - 3;5588,5598,5593;, - 3;5591,5595,5561;, - 3;5556,5560,5562;, - 3;5589,5557,5600;, - 3;5597,5601,5563;, - 3;5602,5607,5567;, - 3;5603,5613,5608;, - 3;5606,5610,5570;, - 3;5565,5569,5571;, - 3;5604,5566,5574;, - 3;5612,5575,5572;, - 3;5614,5618,5579;, - 3;5615,5624,5619;, - 3;5618,5621,5581;, - 3;5577,5580,5582;, - 3;5616,5578,5585;, - 3;5623,5586,5583;, - 3;5657,5662,5628;, - 3;5658,5668,5663;, - 3;5661,5665,5631;, - 3;5626,5630,5632;, - 3;5659,5627,5670;, - 3;5667,5671,5633;, - 3;5672,5677,5637;, - 3;5673,5683,5678;, - 3;5676,5680,5640;, - 3;5635,5639,5641;, - 3;5674,5636,5644;, - 3;5682,5645,5642;, - 3;5684,5688,5649;, - 3;5685,5694,5689;, - 3;5688,5691,5651;, - 3;5647,5650,5652;, - 3;5686,5648,5655;, - 3;5693,5656,5653;, - 3;5716,5723,5721;, - 3;5713,5714,5722;, - 3;5695,5702,5714;, - 3;5697,5703,5701;, - 3;5698,5705,5703;, - 3;5700,5706,5704;, - 3;5719,5725,5706;, - 3;5718,5721,5724;, - 3;5726,5728,5721;, - 3;5715,5727,5722;, - 3;5707,5715,5714;, - 3;5709,5708,5701;, - 3;5710,5709,5703;, - 3;5712,5711,5704;, - 3;5729,5712,5706;, - 3;5728,5730,5724;, - 3;5752,5759,5757;, - 3;5749,5750,5758;, - 3;5731,5738,5750;, - 3;5733,5739,5737;, - 3;5734,5741,5739;, - 3;5736,5742,5740;, - 3;5755,5761,5742;, - 3;5754,5757,5760;, - 3;5762,5764,5757;, - 3;5751,5763,5758;, - 3;5743,5751,5750;, - 3;5745,5744,5737;, - 3;5746,5745,5739;, - 3;5748,5747,5740;, - 3;5765,5748,5742;, - 3;5764,5766,5760;, - 3;5791,5800,5796;, - 3;5801,5794,5796;, - 3;5798,5793,5809;, - 3;5805,5770,5767;, - 3;5775,5783,5781;, - 3;5785,5790,5781;, - 3;5779,5813,5811;, - 3;5788,5787,5773;, - 3;5768,5774,5812;, - 3;5809,5811,5813;, - 3;5808,5814,5772;, - 3;5770,5771,5773;, - 3;5817,5839,5841;, - 3;5824,5842,5844;, - 3;5827,5845,5847;, - 3;5830,5848,5850;, - 3;5833,5851,5835;, - 3;5821,5836,5838;, - 3;5855,5877,5879;, - 3;5862,5880,5882;, - 3;5865,5883,5885;, - 3;5868,5886,5888;, - 3;5871,5889,5873;, - 3;5859,5874,5876;, - 3;5941,5945,5946;, - 3;5931,5932,5943;, - 3;5949,5953,5932;, - 3;5954,5955,5951;, - 3;5954,5958,5959;, - 3;5957,5962,5963;, - 3;5962,5966,5967;, - 3;5965,5948,5946;, - 3;5977,5981,5982;, - 3;5974,5975,5979;, - 3;5985,5989,5975;, - 3;5990,5991,5987;, - 3;5990,5994,5995;, - 3;5993,5998,5999;, - 3;5998,6002,6003;, - 3;6001,5984,5982;, - 3;6010,6014,6015;, - 3;6007,6008,6012;, - 3;6018,6022,6008;, - 3;6023,6024,6020;, - 3;6023,6027,6028;, - 3;6026,6031,6032;, - 3;6031,6035,6036;, - 3;6034,6017,6015;, - 3;6090,6097,6095;, - 3;6080,6091,6093;, - 3;6098,6080,6081;, - 3;6103,6099,6101;, - 3;6103,6104,6108;, - 3;6107,6110,6112;, - 3;6111,6112,6116;, - 3;6115,6118,6095;, - 3;6126,6133,6131;, - 3;6123,6127,6129;, - 3;6134,6123,6124;, - 3;6139,6135,6137;, - 3;6139,6140,6144;, - 3;6143,6146,6148;, - 3;6147,6148,6152;, - 3;6151,6154,6131;, - 3;6159,6166,6164;, - 3;6156,6160,6162;, - 3;6167,6156,6157;, - 3;6172,6168,6170;, - 3;6172,6173,6177;, - 3;6176,6179,6181;, - 3;6180,6181,6185;, - 3;6184,6187,6164;; - } - - MeshTextureCoords { - 6202; - 0.472531;0.024249;, - 0.403337;0.024249;, - 0.398724;0.111289;, - 0.472531;0.111289;, - 0.978985;0.021333;, - 0.976615;0.021333;, - 0.977548;0.022780;, - 0.979919;0.022780;, - 0.705752;0.382443;, - 0.481538;0.382443;, - 0.389242;0.879776;, - 0.401882;0.879805;, - 0.981133;0.022644;, - 0.978483;0.021604;, - 0.232804;0.860443;, - 0.232804;0.860121;, - 0.166456;0.778736;, - 0.237407;0.781483;, - 0.237407;0.814796;, - 0.994840;0.512451;, - 0.959048;0.512451;, - 0.959048;0.396487;, - 0.994840;0.396487;, - 0.538022;0.044407;, - 0.538022;0.107538;, - 0.518180;0.650506;, - 0.414883;0.531321;, - 0.979394;0.021284;, - 0.383669;0.995439;, - 0.977044;0.021392;, - 0.759894;0.521686;, - 0.686540;0.017110;, - 0.686477;0.042153;, - 0.918247;0.185722;, - 0.918247;0.185778;, - 0.713500;0.089000;, - 0.641115;0.577911;, - 0.569468;0.863191;, - 0.579224;0.863191;, - 0.593834;0.863191;, - 0.977010;0.021888;, - 0.933173;0.928821;, - 0.713399;0.743062;, - 0.976753;0.021392;, - 0.759894;0.504977;, - 0.835111;0.458703;, - 0.761022;0.407988;, - 0.730511;0.909761;, - 0.555516;0.785034;, - 0.556456;0.768150;, - 0.546440;0.785034;, - 0.547380;0.762180;, - 0.546440;0.678549;, - 0.555516;0.815257;, - 0.546440;0.815257;, - 0.546440;0.708772;, - 0.555516;0.785034;, - 0.556456;0.768150;, - 0.546440;0.785034;, - 0.546440;0.678549;, - 0.547380;0.762180;, - 0.302199;0.946783;, - 0.263560;0.948159;, - 0.295370;0.940241;, - 0.260667;0.941319;, - 0.315857;0.987318;, - 0.315702;0.988050;, - 0.266264;0.990540;, - 0.278444;0.941319;, - 0.315702;0.989442;, - 0.278444;0.990540;, - 0.278444;0.948159;, - 0.313333;0.864576;, - 0.977897;0.020979;, - 0.976665;0.020882;, - 0.260667;0.862208;, - 0.313481;0.868559;, - 0.977900;0.021141;, - 0.260667;0.866372;, - 0.976665;0.021052;, - 0.977081;0.021052;, - 0.278444;0.866372;, - 0.278444;0.862208;, - 0.977081;0.020882;, - 0.435701;0.551310;, - 0.435652;0.551397;, - 0.429940;0.549638;, - 0.429993;0.549678;, - 0.387183;0.549880;, - 0.414883;0.549880;, - 0.321629;0.721642;, - 0.252376;0.725528;, - 0.327268;0.686475;, - 0.252469;0.686829;, - 0.268395;0.726256;, - 0.268350;0.726269;, - 0.268350;0.681512;, - 0.268350;0.673331;, - 0.268320;0.673278;, - 0.441209;0.535723;, - 0.436927;0.532459;, - 0.387183;0.531321;, - 0.305407;0.726269;, - 0.305452;0.726256;, - 0.305407;0.681512;, - 0.305377;0.673278;, - 0.305407;0.673331;, - 0.734663;0.454345;, - 0.734663;0.417325;, - 0.976616;0.021821;, - 0.976753;0.021821;, - 0.734663;0.407988;, - 0.602106;0.785034;, - 0.603046;0.768150;, - 0.602106;0.678549;, - 0.603046;0.726360;, - 0.977044;0.021821;, - 0.734663;0.390297;, - 0.602106;0.815257;, - 0.602106;0.708772;, - 0.734663;0.454345;, - 0.976616;0.021821;, - 0.734663;0.417325;, - 0.976753;0.021821;, - 0.734663;0.407988;, - 0.602106;0.785034;, - 0.603046;0.768150;, - 0.602106;0.678549;, - 0.603046;0.726360;, - 0.595595;0.625155;, - 0.554509;0.627484;, - 0.554529;0.626267;, - 0.580962;0.627484;, - 0.580991;0.626267;, - 0.595595;0.625155;, - 0.554509;0.627484;, - 0.554529;0.626267;, - 0.361134;0.946783;, - 0.977996;0.020954;, - 0.361134;0.946783;, - 0.977996;0.020954;, - 0.978082;0.021635;, - 0.361134;0.987318;, - 0.361000;0.987971;, - 0.422412;0.920730;, - 0.401882;0.891889;, - 0.401821;0.920276;, - 0.389242;0.891889;, - 0.410299;0.920730;, - 0.389864;0.107756;, - 0.980067;0.022644;, - 0.980067;0.018289;, - 0.389864;0.033711;, - 0.978467;0.022124;, - 0.981133;0.018289;, - 0.979533;0.022124;, - 0.978725;0.020954;, - 0.978725;0.021635;, - 0.361000;0.989442;, - 0.384220;0.964429;, - 0.383669;0.971190;, - 0.384220;0.932359;, - 0.978043;0.021284;, - 0.354305;0.837126;, - 0.353952;0.830714;, - 0.978015;0.019112;, - 0.319271;0.843669;, - 0.266102;0.840349;, - 0.319381;0.826383;, - 0.410299;0.893814;, - 0.401821;0.893360;, - 0.401968;0.891888;, - 0.422412;0.893814;, - 0.401968;0.879776;, - 0.278444;0.840349;, - 0.319381;0.812286;, - 0.978725;0.019112;, - 0.353952;0.812286;, - 0.160200;0.104403;, - 0.160200;0.104406;, - 0.137212;0.105146;, - 0.138000;0.057480;, - 0.681176;0.318447;, - 0.536902;0.329036;, - 0.144314;0.104446;, - 0.144300;0.064700;, - 0.144303;0.104439;, - 0.145500;0.051987;, - 0.556327;0.331772;, - 0.155000;0.058484;, - 0.155100;0.109098;, - 0.155100;0.109097;, - 0.149353;0.099465;, - 0.501218;0.382443;, - 0.520189;0.382686;, - 0.364053;0.752399;, - 0.252379;0.754120;, - 0.364806;0.755188;, - 0.268261;0.758812;, - 0.364364;0.757451;, - 0.976859;0.021175;, - 0.479354;0.575723;, - 0.458510;0.596617;, - 0.503402;0.596615;, - 0.447728;0.542094;, - 0.506719;0.603402;, - 0.455833;0.603363;, - 0.457069;0.622806;, - 0.387183;0.605783;, - 0.189000;0.104494;, - 0.189000;0.104498;, - 0.194809;0.051841;, - 0.979923;0.019534;, - 0.627550;0.331772;, - 0.979756;0.019534;, - 0.194809;0.058456;, - 0.194800;0.109004;, - 0.194800;0.109009;, - 0.305318;0.758812;, - 0.978519;0.021175;, - 0.414883;0.605783;, - 0.457069;0.650506;, - 0.160176;0.064647;, - 0.664930;0.253753;, - 0.536902;0.329201;, - 0.138000;0.057500;, - 0.138000;0.057489;, - 0.144300;0.064700;, - 0.144300;0.064686;, - 0.145500;0.051947;, - 0.556327;0.331158;, - 0.155000;0.058496;, - 0.155000;0.058509;, - 0.149353;0.070769;, - 0.339140;0.710426;, - 0.330887;0.678159;, - 0.252510;0.673670;, - 0.371135;0.691565;, - 0.360897;0.667221;, - 0.359134;0.662039;, - 0.252439;0.639745;, - 0.268320;0.641782;, - 0.463365;0.527209;, - 0.464792;0.522314;, - 0.189036;0.064647;, - 0.979714;0.018363;, - 0.627550;0.331158;, - 0.194809;0.051342;, - 0.194809;0.058489;, - 0.979567;0.018437;, - 0.194808;0.058525;, - 0.194808;0.058525;, - 0.305377;0.641782;, - 0.761022;0.467576;, - 0.976616;0.021392;, - 0.761022;0.432294;, - 0.761022;0.417325;, - 0.976753;0.021392;, - 0.761022;0.485217;, - 0.759894;0.497114;, - 0.759894;0.504977;, - 0.761022;0.407988;, - 0.658376;0.785034;, - 0.976682;0.021253;, - 0.659317;0.768150;, - 0.658376;0.678549;, - 0.976682;0.020660;, - 0.659317;0.726360;, - 0.663523;0.967885;, - 0.977029;0.021804;, - 0.626448;0.967188;, - 0.761022;0.390297;, - 0.977111;0.021253;, - 0.658376;0.815257;, - 0.658376;0.708772;, - 0.977111;0.020660;, - 0.977169;0.021804;, - 0.651019;0.967188;, - 0.761022;0.467576;, - 0.976616;0.021392;, - 0.761022;0.432294;, - 0.761022;0.417325;, - 0.759894;0.497114;, - 0.761022;0.485217;, - 0.658376;0.785034;, - 0.659317;0.768150;, - 0.976682;0.021253;, - 0.658376;0.678549;, - 0.976682;0.020660;, - 0.659317;0.726360;, - 0.663523;0.967885;, - 0.977029;0.021804;, - 0.626448;0.967188;, - 0.565046;0.950613;, - 0.527416;0.950131;, - 0.527416;0.965961;, - 0.579606;0.965780;, - 0.580043;0.994122;, - 0.850936;0.929242;, - 0.887671;0.928821;, - 0.850845;0.929228;, - 0.875384;0.929242;, - 0.875417;0.929228;, - 0.976841;0.021888;, - 0.551988;0.950131;, - 0.598963;0.994122;, - 0.551988;0.965961;, - 0.527416;0.950131;, - 0.565046;0.950613;, - 0.579606;0.965780;, - 0.527416;0.965961;, - 0.580043;0.994122;, - 0.875417;0.929228;, - 0.976841;0.021888;, - 0.875384;0.929242;, - 0.850936;0.929242;, - 0.850845;0.929228;, - 0.887671;0.928821;, - 0.527416;0.879556;, - 0.565046;0.879109;, - 0.564616;0.842129;, - 0.564663;0.842250;, - 0.579606;0.879109;, - 0.579176;0.842129;, - 0.850845;0.866799;, - 0.887671;0.865984;, - 0.979058;0.849635;, - 0.875417;0.866799;, - 0.979058;0.829159;, - 0.976841;0.021556;, - 0.224270;0.065100;, - 0.224919;0.084722;, - 0.224270;0.048234;, - 0.225106;0.084722;, - 0.551988;0.879556;, - 0.564663;0.866821;, - 0.579224;0.866821;, - 0.579224;0.866821;, - 0.236397;0.084722;, - 0.244397;0.048234;, - 0.244397;0.065100;, - 0.236210;0.084722;, - 0.527416;0.879556;, - 0.564616;0.842129;, - 0.564663;0.842250;, - 0.565046;0.879109;, - 0.579606;0.879109;, - 0.579176;0.842129;, - 0.976841;0.021556;, - 0.979058;0.829159;, - 0.875417;0.866799;, - 0.224270;0.065100;, - 0.224919;0.084722;, - 0.225106;0.084722;, - 0.224270;0.048234;, - 0.850845;0.866799;, - 0.979058;0.849635;, - 0.887671;0.865984;, - 0.611242;0.631618;, - 0.554509;0.635865;, - 0.976859;0.021772;, - 0.785203;0.704550;, - 0.863801;0.704061;, - 0.569464;0.845664;, - 0.569468;0.845659;, - 0.579224;0.845659;, - 0.579219;0.845664;, - 0.593834;0.845659;, - 0.593829;0.845664;, - 0.580962;0.635834;, - 0.976865;0.021772;, - 0.852944;0.704550;, - 0.863556;0.704183;, - 0.569468;0.863191;, - 0.579224;0.863191;, - 0.593834;0.863191;, - 0.611242;0.631618;, - 0.554509;0.635865;, - 0.976859;0.021772;, - 0.569468;0.845659;, - 0.569464;0.845664;, - 0.579224;0.845659;, - 0.579219;0.845664;, - 0.593834;0.845659;, - 0.593829;0.845664;, - 0.367963;0.940241;, - 0.367963;0.940241;, - 0.977816;0.020844;, - 0.977816;0.020844;, - 0.389242;0.879805;, - 0.389406;0.920276;, - 0.384207;0.857811;, - 0.977818;0.021385;, - 0.977922;0.022045;, - 0.979961;0.022045;, - 0.979901;0.021385;, - 0.402736;0.033711;, - 0.978467;0.020410;, - 0.979533;0.020410;, - 0.980848;0.021385;, - 0.402736;0.107756;, - 0.978725;0.020844;, - 0.622594;0.573857;, - 0.554529;0.569907;, - 0.633946;0.559671;, - 0.633105;0.526087;, - 0.554529;0.554319;, - 0.603619;0.582256;, - 0.554529;0.579134;, - 0.633105;0.552549;, - 0.580991;0.554319;, - 0.580991;0.569907;, - 0.580991;0.579134;, - 0.622594;0.573857;, - 0.554529;0.569907;, - 0.633946;0.559671;, - 0.633105;0.526087;, - 0.554529;0.554319;, - 0.603619;0.582256;, - 0.554529;0.579134;, - 0.979079;0.021500;, - 0.481538;0.498336;, - 0.977973;0.021500;, - 0.528692;0.498579;, - 0.507479;0.498336;, - 0.481538;0.454556;, - 0.543302;0.454800;, - 0.507479;0.454556;, - 0.977816;0.019573;, - 0.367963;0.864576;, - 0.979175;0.020979;, - 0.979175;0.021141;, - 0.977816;0.019640;, - 0.367963;0.868559;, - 0.389242;0.891888;, - 0.389406;0.893360;, - 0.384207;0.833563;, - 0.385571;0.825413;, - 0.977818;0.019015;, - 0.385571;0.806829;, - 0.977759;0.021792;, - 0.979901;0.019015;, - 0.980848;0.019015;, - 0.978498;0.021792;, - 0.978725;0.019573;, - 0.978725;0.019640;, - 0.979919;0.021572;, - 0.977888;0.021572;, - 0.397884;0.752564;, - 0.398545;0.755188;, - 0.398862;0.757451;, - 0.976859;0.019546;, - 0.512121;0.568048;, - 0.517276;0.615934;, - 0.503402;0.596604;, - 0.508481;0.615934;, - 0.458510;0.596617;, - 0.455839;0.603402;, - 0.507949;0.622806;, - 0.518180;0.622806;, - 0.517830;0.566416;, - 0.507949;0.650506;, - 0.978519;0.019546;, - 0.977028;0.021470;, - 0.268321;0.563588;, - 0.976971;0.021482;, - 0.252469;0.564262;, - 0.421693;0.663596;, - 0.268321;0.575890;, - 0.268320;0.576004;, - 0.252500;0.576100;, - 0.412754;0.639577;, - 0.252439;0.590600;, - 0.405137;0.636980;, - 0.305375;0.575890;, - 0.305377;0.576004;, - 0.977161;0.021470;, - 0.305475;0.563588;, - 0.268320;0.591865;, - 0.977757;0.021000;, - 0.074864;0.903802;, - 0.062496;0.903802;, - 0.012834;0.883347;, - 0.977689;0.021000;, - 0.977438;0.021042;, - 0.977689;0.021042;, - 0.977438;0.021090;, - 0.062496;0.906459;, - 0.012834;0.887585;, - 0.977757;0.021042;, - 0.074864;0.906459;, - 0.063781;0.860443;, - 0.048303;0.853180;, - 0.029400;0.853180;, - 0.063781;0.849133;, - 0.075645;0.841937;, - 0.075645;0.860443;, - 0.063781;0.839881;, - 0.062673;0.886662;, - 0.013934;0.856006;, - 0.075645;0.834740;, - 0.074525;0.881221;, - 0.063781;0.860121;, - 0.048303;0.910185;, - 0.075645;0.860121;, - 0.075645;0.842644;, - 0.063781;0.848812;, - 0.029400;0.910185;, - 0.075645;0.834419;, - 0.074525;0.927712;, - 0.013934;0.907360;, - 0.063781;0.839559;, - 0.062673;0.918856;, - 0.048303;0.859947;, - 0.048303;0.880683;, - 0.031044;0.883568;, - 0.977666;0.021127;, - 0.036394;0.859947;, - 0.048303;0.890149;, - 0.031032;0.887264;, - 0.977666;0.021199;, - 0.977484;0.021042;, - 0.977566;0.021123;, - 0.024245;0.883347;, - 0.977484;0.021090;, - 0.024245;0.887585;, - 0.977566;0.021206;, - 0.048303;0.903469;, - 0.036394;0.903469;, - 0.305377;0.591865;, - 0.826304;0.458703;, - 0.816137;0.458755;, - 0.816137;0.447730;, - 0.826304;0.447511;, - 0.816137;0.417325;, - 0.803328;0.497114;, - 0.826304;0.485564;, - 0.801759;0.485217;, - 0.803328;0.504977;, - 0.835111;0.485564;, - 0.835111;0.458703;, - 0.835111;0.447511;, - 0.816137;0.407988;, - 0.853824;0.485564;, - 0.803328;0.521686;, - 0.853824;0.458703;, - 0.816137;0.390297;, - 0.853824;0.447511;, - 0.816137;0.458755;, - 0.826304;0.458703;, - 0.816137;0.447730;, - 0.826304;0.447511;, - 0.816137;0.417325;, - 0.803328;0.497114;, - 0.801759;0.485217;, - 0.826304;0.485564;, - 0.803328;0.504977;, - 0.835111;0.485564;, - 0.835111;0.447511;, - 0.816137;0.407988;, - 0.933173;0.928821;, - 0.580043;0.972991;, - 0.976926;0.021640;, - 0.599021;0.965780;, - 0.875384;0.961844;, - 0.977010;0.022036;, - 0.875221;0.961950;, - 0.933173;0.956989;, - 0.850649;0.961950;, - 0.850936;0.961844;, - 0.977010;0.021888;, - 0.692232;0.901150;, - 0.628371;0.899765;, - 0.977145;0.021640;, - 0.598963;0.972991;, - 0.651019;0.899765;, - 0.599021;0.965780;, - 0.580043;0.972991;, - 0.976926;0.021640;, - 0.875384;0.961844;, - 0.977010;0.022036;, - 0.875221;0.961950;, - 0.692232;0.901150;, - 0.628371;0.899765;, - 0.850936;0.961844;, - 0.933173;0.956989;, - 0.850649;0.961950;, - 0.933556;0.853730;, - 0.933173;0.865984;, - 0.690009;0.103508;, - 0.699532;0.075033;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.699532;0.102968;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.713500;0.089000;, - 0.794167;0.784460;, - 0.976861;0.021786;, - 0.879137;0.783971;, - 0.599021;0.879109;, - 0.976926;0.021228;, - 0.598639;0.842250;, - 0.598591;0.842129;, - 0.977010;0.021556;, - 0.933556;0.829159;, - 0.692232;0.849484;, - 0.628371;0.847567;, - 0.977001;0.021658;, - 0.304000;0.057351;, - 0.225106;0.071820;, - 0.977489;0.019676;, - 0.267704;0.057351;, - 0.225106;0.082977;, - 0.355783;0.108129;, - 0.304000;0.084427;, - 0.977489;0.021390;, - 0.224919;0.071820;, - 0.304000;0.118257;, - 0.355667;0.082000;, - 0.224919;0.082977;, - 0.355487;0.108129;, - 0.267704;0.084427;, - 0.278335;0.108348;, - 0.355487;0.081986;, - 0.355667;0.107253;, - 0.216469;0.110778;, - 0.220182;0.082977;, - 0.215825;0.065556;, - 0.220182;0.071820;, - 0.977045;0.021219;, - 0.255975;0.110778;, - 0.255975;0.093000;, - 0.977045;0.019848;, - 0.220369;0.071820;, - 0.216469;0.093000;, - 0.215825;0.047778;, - 0.220369;0.082977;, - 0.673214;0.103508;, - 0.672880;0.074825;, - 0.672880;0.089111;, - 0.672880;0.103397;, - 0.672880;0.104508;, - 0.672880;0.090222;, - 0.846680;0.784460;, - 0.878892;0.784093;, - 0.976880;0.021786;, - 0.598639;0.866821;, - 0.977145;0.021228;, - 0.977194;0.021658;, - 0.651019;0.847567;, - 0.373696;0.108129;, - 0.236397;0.082977;, - 0.373444;0.107253;, - 0.373399;0.081986;, - 0.373444;0.082000;, - 0.236210;0.082977;, - 0.373399;0.108129;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.699532;0.075033;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.699532;0.102968;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.599021;0.879109;, - 0.976926;0.021228;, - 0.598591;0.842129;, - 0.598639;0.842250;, - 0.977010;0.021556;, - 0.933556;0.829159;, - 0.628371;0.847567;, - 0.692232;0.849484;, - 0.977001;0.021658;, - 0.304000;0.057351;, - 0.977489;0.019676;, - 0.225106;0.071820;, - 0.225106;0.082977;, - 0.267704;0.057351;, - 0.355783;0.108129;, - 0.304000;0.084427;, - 0.224919;0.071820;, - 0.977489;0.021390;, - 0.304000;0.118257;, - 0.355667;0.082000;, - 0.267704;0.084427;, - 0.224919;0.082977;, - 0.355487;0.108129;, - 0.278335;0.108348;, - 0.355667;0.107253;, - 0.355487;0.081986;, - 0.216469;0.110778;, - 0.215825;0.065556;, - 0.220182;0.082977;, - 0.255975;0.110778;, - 0.220182;0.071820;, - 0.977045;0.021219;, - 0.255975;0.093000;, - 0.977045;0.019848;, - 0.220369;0.071820;, - 0.215825;0.047778;, - 0.220369;0.082977;, - 0.216469;0.093000;, - 0.933556;0.853730;, - 0.933173;0.865984;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.304000;0.023520;, - 0.355889;0.082000;, - 0.278335;0.033429;, - 0.355889;0.107253;, - 0.355783;0.081986;, - 0.673214;0.089222;, - 0.373667;0.082000;, - 0.373667;0.107253;, - 0.373696;0.081986;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.304000;0.023520;, - 0.355889;0.082000;, - 0.278335;0.033429;, - 0.355783;0.081986;, - 0.355889;0.107253;, - 0.034693;0.444254;, - 0.150000;0.418061;, - 0.944172;0.112669;, - 0.034750;0.430285;, - 0.036224;0.418061;, - 0.134655;0.418061;, - 0.641115;0.577911;, - 0.979079;0.020671;, - 0.976867;0.020671;, - 0.582179;0.498579;, - 0.579256;0.454800;, - 0.391459;0.096439;, - 0.556537;0.174932;, - 0.556327;0.186090;, - 0.802622;0.317627;, - 0.523953;0.193454;, - 0.802641;0.317638;, - 0.556327;0.193454;, - 0.525422;0.173285;, - 0.808426;0.313459;, - 0.523953;0.186090;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.977141;0.022000;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.016518;0.087040;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012437;0.059286;, - 0.012381;0.052598;, - 0.978985;0.022400;, - 0.979919;0.019087;, - 0.977888;0.019087;, - 0.976954;0.022400;, - 0.579256;0.382686;, - 0.976971;0.021659;, - 0.437405;0.752756;, - 0.437958;0.755188;, - 0.437345;0.757451;, - 0.977028;0.021682;, - 0.976859;0.017325;, - 0.977028;0.021682;, - 0.624989;0.174932;, - 0.627550;0.186090;, - 0.981273;0.019472;, - 0.627550;0.193454;, - 0.981189;0.019555;, - 0.978519;0.017325;, - 0.977161;0.021682;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.064652;0.058120;, - 0.040952;0.052598;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.036926;0.087040;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.061440;0.582196;, - 0.061440;0.582191;, - 0.061440;0.582194;, - 0.056848;0.586661;, - 0.048289;0.586332;, - 0.057496;0.640360;, - 0.056848;0.586710;, - 0.056848;0.586707;, - 0.057496;0.595107;, - 0.056848;0.586684;, - 0.007516;0.586332;, - 0.061440;0.582197;, - 0.061440;0.582191;, - 0.061440;0.582193;, - 0.976930;0.021836;, - 0.198440;0.419736;, - 0.190825;0.353778;, - 0.976915;0.021836;, - 0.194000;0.361263;, - 0.214525;0.419736;, - 0.206698;0.353778;, - 0.214741;0.467736;, - 0.206698;0.371556;, - 0.199079;0.371556;, - 0.976930;0.021836;, - 0.198337;0.467736;, - 0.206698;0.361263;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.977022;0.021746;, - 0.976941;0.021762;, - 0.186550;0.382365;, - 0.976866;0.021710;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021757;, - 0.976874;0.021718;, - 0.186550;0.382338;, - 0.976831;0.021731;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.178570;0.404936;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021859;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.178570;0.404949;, - 0.081705;0.586605;, - 0.082024;0.640360;, - 0.083616;0.582528;, - 0.083616;0.582524;, - 0.081669;0.586745;, - 0.082024;0.595107;, - 0.083616;0.582530;, - 0.083616;0.582524;, - 0.187500;0.223505;, - 0.267815;0.177636;, - 0.187000;0.166775;, - 0.260407;0.177636;, - 0.187500;0.223505;, - 0.187000;0.173798;, - 0.149345;0.309203;, - 0.932877;0.072573;, - 0.134000;0.309203;, - 0.012391;0.309203;, - 0.150000;0.333850;, - 0.944172;0.081652;, - 0.036224;0.333850;, - 0.134655;0.333850;, - 0.944104;0.072573;, - 0.036080;0.309203;, - 0.179997;0.572433;, - 0.180010;0.572431;, - 0.178385;0.640360;, - 0.223123;0.571935;, - 0.163192;0.582575;, - 0.163192;0.582584;, - 0.166048;0.586672;, - 0.164847;0.640360;, - 0.157032;0.582529;, - 0.157032;0.582520;, - 0.126288;0.582528;, - 0.126343;0.586605;, - 0.125824;0.640360;, - 0.157021;0.586605;, - 0.155927;0.640360;, - 0.179972;0.572433;, - 0.180012;0.572439;, - 0.189418;0.571935;, - 0.178385;0.595107;, - 0.166048;0.586672;, - 0.164846;0.595107;, - 0.163192;0.582575;, - 0.163192;0.582587;, - 0.157032;0.582532;, - 0.157032;0.582520;, - 0.155927;0.595107;, - 0.157014;0.586745;, - 0.126324;0.586745;, - 0.125824;0.595107;, - 0.126288;0.582528;, - 0.187500;0.223504;, - 0.187000;0.166799;, - 0.187500;0.223497;, - 0.187000;0.173799;, - 0.254500;0.223545;, - 0.255000;0.173794;, - 0.260518;0.177636;, - 0.267926;0.177636;, - 0.255000;0.166775;, - 0.254500;0.223545;, - 0.256975;0.526919;, - 0.354975;0.527475;, - 0.257000;0.466000;, - 0.257000;0.446000;, - 0.335222;0.527475;, - 0.257198;0.526919;, - 0.257000;0.466000;, - 0.354969;0.527475;, - 0.062673;0.171389;, - 0.123628;0.174197;, - 0.062673;0.153611;, - 0.123573;0.174197;, - 0.099649;0.174197;, - 0.040549;0.153611;, - 0.040549;0.171389;, - 0.099705;0.174197;, - 0.270545;0.320182;, - 0.280385;0.318542;, - 0.241037;0.320182;, - 0.976858;0.021754;, - 0.976858;0.021774;, - 0.270545;0.362200;, - 0.280385;0.360561;, - 0.241037;0.362200;, - 0.976858;0.021761;, - 0.270545;0.379708;, - 0.298860;0.427511;, - 0.297409;0.384957;, - 0.296785;0.384628;, - 0.241037;0.379708;, - 0.298860;0.398356;, - 0.976859;0.021765;, - 0.291704;0.354200;, - 0.291626;0.353945;, - 0.976859;0.021761;, - 0.291704;0.318563;, - 0.291626;0.318654;, - 0.976859;0.021754;, - 0.976859;0.021774;, - 0.254500;0.223468;, - 0.255000;0.173798;, - 0.768148;0.107475;, - 0.759941;0.107475;, - 0.255000;0.166799;, - 0.254500;0.223496;, - 0.745439;0.090556;, - 0.736667;0.086111;, - 0.760385;0.107030;, - 0.760111;0.107155;, - 0.745556;0.081667;, - 0.768028;0.107043;, - 0.760428;0.107343;, - 0.736667;0.095000;, - 0.759889;0.107155;, - 0.768593;0.107030;, - 0.745556;0.099444;, - 0.760206;0.107343;, - 0.767806;0.107043;, - 0.754444;0.095000;, - 0.768292;0.107041;, - 0.768123;0.107230;, - 0.754444;0.086111;, - 0.768345;0.107230;, - 0.759885;0.107141;, - 0.317469;0.526919;, - 0.317000;0.465985;, - 0.354975;0.527364;, - 0.335222;0.527364;, - 0.317000;0.446000;, - 0.317691;0.526919;, - 0.354969;0.527364;, - 0.317000;0.465955;, - 0.356910;0.398384;, - 0.976862;0.021761;, - 0.356911;0.427576;, - 0.361011;0.366363;, - 0.361042;0.366416;, - 0.345901;0.427576;, - 0.345718;0.427511;, - 0.349473;0.384957;, - 0.345901;0.398384;, - 0.976861;0.021765;, - 0.345718;0.398356;, - 0.361490;0.318563;, - 0.355319;0.354200;, - 0.355564;0.354180;, - 0.976862;0.021774;, - 0.976862;0.021754;, - 0.305321;0.355683;, - 0.301464;0.369666;, - 0.301466;0.370190;, - 0.342793;0.369666;, - 0.305321;0.318563;, - 0.428474;0.427576;, - 0.436245;0.366416;, - 0.435854;0.366363;, - 0.428474;0.398384;, - 0.976865;0.021761;, - 0.455528;0.351583;, - 0.455865;0.350599;, - 0.446824;0.427576;, - 0.470350;0.348420;, - 0.446824;0.398384;, - 0.487806;0.348420;, - 0.976866;0.021759;, - 0.421864;0.306189;, - 0.427871;0.354200;, - 0.427885;0.354180;, - 0.487806;0.305599;, - 0.976866;0.021751;, - 0.976866;0.021774;, - 0.470350;0.305599;, - 0.455865;0.307346;, - 0.444892;0.306189;, - 0.444966;0.306476;, - 0.444892;0.341826;, - 0.444966;0.341115;, - 0.976865;0.021751;, - 0.976865;0.021774;, - 0.977044;0.020660;, - 0.977118;0.021875;, - 0.069496;0.120769;, - 0.977044;0.022066;, - 0.047090;0.120769;, - 0.012437;0.120825;, - 0.977141;0.022000;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.016518;0.087040;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.391459;0.048318;, - 0.556537;0.147086;, - 0.556327;0.185371;, - 0.802641;0.177464;, - 0.523953;0.193199;, - 0.802622;0.177608;, - 0.556327;0.193199;, - 0.525422;0.149144;, - 0.523953;0.185371;, - 0.808426;0.177464;, - 0.012437;0.120825;, - 0.047090;0.120769;, - 0.977044;0.022066;, - 0.977044;0.020660;, - 0.069496;0.120769;, - 0.977118;0.021875;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.041008;0.093561;, - 0.047645;0.092394;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.978312;0.020660;, - 0.036926;0.087040;, - 0.513845;0.107538;, - 0.627550;0.185371;, - 0.981273;0.017225;, - 0.624989;0.147086;, - 0.981189;0.017225;, - 0.627550;0.193199;, - 0.959048;0.472795;, - 0.994840;0.472795;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978312;0.020660;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.012320;0.208577;, - 0.149345;0.222939;, - 0.932877;0.040799;, - 0.012391;0.222939;, - 0.134000;0.222939;, - 0.012372;0.195110;, - 0.036002;0.195269;, - 0.036080;0.222939;, - 0.035950;0.208736;, - 0.944104;0.040799;, - 0.976860;0.021777;, - 0.944104;0.046851;, - 0.976876;0.021732;, - 0.036080;0.239370;, - 0.976869;0.021732;, - 0.976860;0.021758;, - 0.134000;0.239370;, - 0.012391;0.239370;, - 0.932877;0.046851;, - 0.149345;0.239370;, - 0.149345;0.231155;, - 0.932877;0.043825;, - 0.944104;0.043825;, - 0.976861;0.021745;, - 0.976876;0.021723;, - 0.976869;0.021723;, - 0.036080;0.231155;, - 0.976861;0.021725;, - 0.012391;0.231155;, - 0.134000;0.231155;, - 0.241037;0.260656;, - 0.283754;0.199532;, - 0.283754;0.230704;, - 0.282025;0.259016;, - 0.270545;0.260656;, - 0.281983;0.258879;, - 0.298999;0.199532;, - 0.298999;0.230704;, - 0.298179;0.247924;, - 0.297409;0.247754;, - 0.291704;0.268942;, - 0.291626;0.270159;, - 0.361064;0.246283;, - 0.361884;0.230704;, - 0.361884;0.199532;, - 0.361490;0.259662;, - 0.361506;0.259643;, - 0.305321;0.259662;, - 0.305997;0.259643;, - 0.420957;0.230704;, - 0.470350;0.248506;, - 0.420137;0.246283;, - 0.420819;0.247754;, - 0.420957;0.199532;, - 0.487806;0.248506;, - 0.487806;0.280621;, - 0.470350;0.280621;, - 0.455865;0.282116;, - 0.455528;0.281128;, - 0.414254;0.259662;, - 0.413650;0.259643;, - 0.444892;0.287502;, - 0.444966;0.288312;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012381;0.052598;, - 0.012437;0.059286;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.040952;0.052598;, - 0.064652;0.058120;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.055508;0.799522;, - 0.041032;0.799147;, - 0.055172;0.801413;, - 0.061024;0.774863;, - 0.041032;0.774293;, - 0.046266;0.754438;, - 0.046266;0.763075;, - 0.049668;0.774293;, - 0.049668;0.799147;, - 0.055172;0.805506;, - 0.143339;0.893176;, - 0.978132;0.020834;, - 0.978132;0.020876;, - 0.143339;0.895832;, - 0.978023;0.021000;, - 0.123466;0.903802;, - 0.978023;0.021042;, - 0.123466;0.906459;, - 0.144531;0.860443;, - 0.144531;0.841937;, - 0.144531;0.834740;, - 0.143339;0.872366;, - 0.120558;0.834740;, - 0.119390;0.874137;, - 0.120558;0.841937;, - 0.120558;0.860443;, - 0.120558;0.834419;, - 0.119390;0.929483;, - 0.120558;0.842644;, - 0.144531;0.842644;, - 0.144531;0.834419;, - 0.143339;0.929483;, - 0.120558;0.860121;, - 0.144531;0.860121;, - 0.094847;0.733336;, - 0.095624;0.727406;, - 0.061534;0.733336;, - 0.052957;0.727665;, - 0.062312;0.727406;, - 0.062312;0.727406;, - 0.053159;0.667221;, - 0.095624;0.706678;, - 0.052957;0.706937;, - 0.062312;0.706678;, - 0.053159;0.700534;, - 0.062312;0.706678;, - 0.094103;0.723951;, - 0.066877;0.723951;, - 0.066877;0.710133;, - 0.094103;0.710133;, - 0.097992;0.977510;, - 0.098017;0.986461;, - 0.091536;0.944197;, - 0.978578;0.023576;, - 0.979911;0.020133;, - 0.091536;0.944197;, - 0.086421;0.951453;, - 0.079639;0.951881;, - 0.980081;0.020395;, - 0.090749;0.973784;, - 0.079639;0.974521;, - 0.090437;0.989766;, - 0.068064;0.951881;, - 0.980356;0.020395;, - 0.068064;0.974521;, - 0.090437;0.995098;, - 0.979022;0.023576;, - 0.980356;0.020133;, - 0.098017;0.995098;, - 0.694760;0.788548;, - 0.694760;0.771873;, - 0.683241;0.739164;, - 0.682954;0.683341;, - 0.683241;0.789919;, - 0.713399;0.788548;, - 0.713399;0.771873;, - 0.713112;0.684300;, - 0.713399;0.718950;, - 0.713399;0.718950;, - 0.713112;0.684300;, - 0.713399;0.743062;, - 0.730511;0.978649;, - 0.976985;0.021629;, - 0.683241;0.813119;, - 0.682954;0.707912;, - 0.694760;0.813119;, - 0.713399;0.813119;, - 0.713112;0.707912;, - 0.977169;0.021629;, - 0.694760;0.788548;, - 0.694760;0.771873;, - 0.683241;0.789919;, - 0.683241;0.739164;, - 0.682954;0.683341;, - 0.713399;0.788548;, - 0.713399;0.771873;, - 0.713112;0.684300;, - 0.713399;0.718950;, - 0.713399;0.718950;, - 0.713112;0.684300;, - 0.730511;0.978649;, - 0.976985;0.021629;, - 0.730511;0.909761;, - 0.689675;0.074825;, - 0.727468;0.075033;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.727468;0.102968;, - 0.689675;0.103397;, - 0.794045;0.784020;, - 0.976861;0.021721;, - 0.943549;0.783971;, - 0.730511;0.849484;, - 0.977001;0.021494;, - 0.355333;0.081438;, - 0.340296;0.057351;, - 0.329665;0.108348;, - 0.355333;0.105852;, - 0.355667;0.056747;, - 0.340296;0.084427;, - 0.355333;0.082673;, - 0.355333;0.107673;, - 0.672880;0.089111;, - 0.672880;0.074825;, - 0.673214;0.074937;, - 0.672880;0.075937;, - 0.672880;0.103397;, - 0.846557;0.784020;, - 0.943305;0.784093;, - 0.976880;0.021721;, - 0.977194;0.021494;, - 0.373111;0.081438;, - 0.373444;0.056747;, - 0.373111;0.105852;, - 0.373111;0.082673;, - 0.373111;0.107673;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.727468;0.075033;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.727468;0.102968;, - 0.730511;0.849484;, - 0.977001;0.021494;, - 0.340296;0.057351;, - 0.355333;0.081438;, - 0.329665;0.108348;, - 0.355333;0.105852;, - 0.355667;0.056747;, - 0.340296;0.084427;, - 0.355333;0.107673;, - 0.355333;0.082673;, - 0.690705;0.630605;, - 0.976859;0.021750;, - 0.329665;0.033429;, - 0.355333;0.058259;, - 0.355889;0.056747;, - 0.976865;0.021750;, - 0.373111;0.058259;, - 0.373667;0.056747;, - 0.690705;0.630605;, - 0.976859;0.021750;, - 0.329665;0.033429;, - 0.355889;0.056747;, - 0.355333;0.058259;, - 0.977141;0.020800;, - 0.100000;0.093505;, - 0.100000;0.059231;, - 0.012381;0.015444;, - 0.977981;0.020800;, - 0.100556;0.092394;, - 0.100556;0.058120;, - 0.040952;0.015444;, - 0.056960;0.536178;, - 0.976864;0.021741;, - 0.048288;0.536195;, - 0.976877;0.021741;, - 0.061440;0.536148;, - 0.976866;0.021741;, - 0.061440;0.536165;, - 0.061440;0.539509;, - 0.061440;0.539497;, - 0.976866;0.021744;, - 0.056960;0.539482;, - 0.976864;0.021744;, - 0.976877;0.021744;, - 0.048288;0.539582;, - 0.056960;0.536187;, - 0.976864;0.021741;, - 0.976863;0.021741;, - 0.007516;0.536195;, - 0.061440;0.536175;, - 0.061440;0.536148;, - 0.976866;0.021741;, - 0.976866;0.021744;, - 0.061440;0.539509;, - 0.061440;0.539531;, - 0.056960;0.539537;, - 0.007516;0.539582;, - 0.976864;0.021744;, - 0.976863;0.021744;, - 0.976915;0.021593;, - 0.194067;0.361263;, - 0.190892;0.353778;, - 0.976930;0.021593;, - 0.198440;0.379835;, - 0.976933;0.021711;, - 0.219463;0.361263;, - 0.219397;0.361263;, - 0.976852;0.021711;, - 0.976852;0.021665;, - 0.231033;0.413585;, - 0.219397;0.353778;, - 0.976933;0.021665;, - 0.219463;0.353778;, - 0.231033;0.387217;, - 0.206765;0.353778;, - 0.214525;0.379835;, - 0.206765;0.361263;, - 0.231249;0.461585;, - 0.219397;0.371556;, - 0.976852;0.021774;, - 0.976933;0.021774;, - 0.231249;0.435217;, - 0.219463;0.371556;, - 0.214741;0.427835;, - 0.206765;0.371556;, - 0.198337;0.427835;, - 0.199146;0.371556;, - 0.976930;0.021593;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.976941;0.021651;, - 0.976887;0.021710;, - 0.186550;0.382365;, - 0.178570;0.382418;, - 0.976887;0.021756;, - 0.176404;0.382494;, - 0.178572;0.404842;, - 0.176177;0.404762;, - 0.186138;0.413602;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.178574;0.404842;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.976986;0.021718;, - 0.976853;0.021731;, - 0.186550;0.382334;, - 0.178570;0.382379;, - 0.976853;0.021747;, - 0.176404;0.382508;, - 0.178570;0.404934;, - 0.176176;0.404762;, - 0.976872;0.021776;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.976919;0.021730;, - 0.186550;0.382342;, - 0.178570;0.382383;, - 0.976919;0.021690;, - 0.176404;0.382505;, - 0.178570;0.404955;, - 0.176178;0.404770;, - 0.976887;0.021767;, - 0.083984;0.539458;, - 0.976874;0.021744;, - 0.976856;0.021700;, - 0.083984;0.536070;, - 0.976856;0.021681;, - 0.976874;0.021740;, - 0.083735;0.539458;, - 0.976874;0.021744;, - 0.083735;0.536070;, - 0.976874;0.021740;, - 0.149444;0.168841;, - 0.090307;0.140477;, - 0.032025;0.171556;, - 0.032025;0.153778;, - 0.090251;0.140477;, - 0.167222;0.168841;, - 0.167222;0.154555;, - 0.086359;0.154444;, - 0.149444;0.154555;, - 0.086414;0.154444;, - 0.149444;0.140270;, - 0.031858;0.171389;, - 0.090307;0.168412;, - 0.167222;0.140270;, - 0.031858;0.153611;, - 0.090251;0.168412;, - 0.176074;0.525865;, - 0.176073;0.525855;, - 0.179992;0.521776;, - 0.223123;0.523861;, - 0.179991;0.521785;, - 0.176089;0.568671;, - 0.176111;0.568592;, - 0.176111;0.539458;, - 0.176089;0.539508;, - 0.976907;0.021744;, - 0.163320;0.539458;, - 0.976902;0.021744;, - 0.976908;0.021744;, - 0.223123;0.540527;, - 0.976892;0.021758;, - 0.179954;0.539508;, - 0.176111;0.536070;, - 0.176089;0.536066;, - 0.976907;0.021740;, - 0.976902;0.021740;, - 0.163320;0.536070;, - 0.179954;0.536066;, - 0.976892;0.021754;, - 0.223123;0.537322;, - 0.976908;0.021740;, - 0.157168;0.546233;, - 0.976900;0.021752;, - 0.976891;0.021752;, - 0.131424;0.546233;, - 0.976977;0.021737;, - 0.157168;0.542845;, - 0.976900;0.021748;, - 0.976891;0.021748;, - 0.131424;0.542845;, - 0.976977;0.021718;, - 0.126567;0.539458;, - 0.976965;0.021700;, - 0.976965;0.021681;, - 0.126567;0.536070;, - 0.179993;0.521762;, - 0.189418;0.523861;, - 0.179985;0.521776;, - 0.176064;0.525865;, - 0.176071;0.525880;, - 0.176086;0.568648;, - 0.176097;0.568606;, - 0.163071;0.539458;, - 0.976902;0.021744;, - 0.176086;0.539458;, - 0.176041;0.539524;, - 0.976907;0.021744;, - 0.180012;0.539524;, - 0.976908;0.021744;, - 0.976876;0.021758;, - 0.189418;0.540527;, - 0.976902;0.021740;, - 0.163071;0.536070;, - 0.976907;0.021740;, - 0.176086;0.536070;, - 0.176041;0.536143;, - 0.180012;0.536143;, - 0.976908;0.021741;, - 0.189418;0.537322;, - 0.976876;0.021754;, - 0.156919;0.546233;, - 0.976900;0.021752;, - 0.131175;0.546233;, - 0.976891;0.021752;, - 0.976914;0.021737;, - 0.976891;0.021748;, - 0.131175;0.542845;, - 0.976914;0.021718;, - 0.976900;0.021748;, - 0.156919;0.542845;, - 0.126318;0.539458;, - 0.976901;0.021700;, - 0.976889;0.021744;, - 0.976901;0.021681;, - 0.976889;0.021740;, - 0.126318;0.536070;, - 0.187000;0.166801;, - 0.187400;0.177905;, - 0.187000;0.173800;, - 0.187400;0.177892;, - 0.255000;0.173817;, - 0.260518;0.224141;, - 0.254700;0.177947;, - 0.267926;0.224141;, - 0.254700;0.177947;, - 0.255000;0.166807;, - 0.250926;0.517450;, - 0.354975;0.518005;, - 0.256975;0.476414;, - 0.354975;0.476970;, - 0.257000;0.466000;, - 0.250926;0.485884;, - 0.354975;0.486439;, - 0.335222;0.486439;, - 0.335222;0.518005;, - 0.257000;0.445997;, - 0.335222;0.476970;, - 0.251148;0.517450;, - 0.354969;0.518005;, - 0.354969;0.486439;, - 0.251148;0.485884;, - 0.257198;0.476414;, - 0.354969;0.476970;, - 0.257000;0.466000;, - 0.149444;0.168619;, - 0.071531;0.171556;, - 0.133026;0.140477;, - 0.149444;0.154333;, - 0.136919;0.154444;, - 0.167222;0.154333;, - 0.136864;0.154444;, - 0.167222;0.168619;, - 0.071531;0.153778;, - 0.132971;0.140477;, - 0.149444;0.140048;, - 0.133026;0.168412;, - 0.071364;0.171389;, - 0.071364;0.153611;, - 0.132971;0.168412;, - 0.167222;0.140048;, - 0.123573;0.134691;, - 0.062840;0.153778;, - 0.062840;0.171556;, - 0.123628;0.134691;, - 0.040716;0.171556;, - 0.099705;0.134691;, - 0.040716;0.153778;, - 0.099649;0.134691;, - 0.255000;0.173799;, - 0.767548;0.056470;, - 0.254700;0.177950;, - 0.760341;0.056570;, - 0.254700;0.177957;, - 0.255000;0.166801;, - 0.745278;0.081667;, - 0.760172;0.056313;, - 0.767572;0.056213;, - 0.736389;0.086111;, - 0.760185;0.056325;, - 0.759855;0.056125;, - 0.736389;0.095000;, - 0.767593;0.056025;, - 0.760033;0.056525;, - 0.745278;0.099444;, - 0.767750;0.056213;, - 0.759950;0.056313;, - 0.976858;0.021766;, - 0.208814;0.320182;, - 0.976859;0.021766;, - 0.241037;0.320182;, - 0.976858;0.021774;, - 0.976858;0.021754;, - 0.241037;0.362200;, - 0.976858;0.021761;, - 0.298860;0.398356;, - 0.976859;0.021765;, - 0.241037;0.379708;, - 0.976859;0.021761;, - 0.976859;0.021754;, - 0.976859;0.021774;, - 0.317469;0.476414;, - 0.317000;0.465965;, - 0.354975;0.476859;, - 0.354975;0.517894;, - 0.323519;0.517449;, - 0.323519;0.485884;, - 0.354975;0.486328;, - 0.335222;0.476859;, - 0.317000;0.446000;, - 0.335222;0.486328;, - 0.335222;0.517894;, - 0.317691;0.476414;, - 0.317000;0.465935;, - 0.354969;0.476859;, - 0.323741;0.485884;, - 0.354969;0.486328;, - 0.323741;0.517449;, - 0.354969;0.517894;, - 0.754167;0.095000;, - 0.767667;0.056401;, - 0.767492;0.056136;, - 0.754167;0.086111;, - 0.759685;0.056136;, - 0.767889;0.056401;, - 0.601948;0.046861;, - 0.602138;0.072716;, - 0.976943;0.021610;, - 0.601948;0.054907;, - 0.976862;0.021610;, - 0.601995;0.072716;, - 0.976943;0.021785;, - 0.602138;0.091960;, - 0.601952;0.047634;, - 0.976862;0.021785;, - 0.601952;0.054583;, - 0.601995;0.091960;, - 0.976862;0.021766;, - 0.356910;0.398384;, - 0.976862;0.021761;, - 0.345718;0.398356;, - 0.976861;0.021765;, - 0.345901;0.398384;, - 0.976862;0.021754;, - 0.976862;0.021774;, - 0.614541;0.046861;, - 0.614364;0.059108;, - 0.631655;0.059108;, - 0.632351;0.046861;, - 0.632351;0.054907;, - 0.631513;0.059108;, - 0.614541;0.054907;, - 0.614222;0.059108;, - 0.614545;0.047634;, - 0.614364;0.105567;, - 0.614545;0.054583;, - 0.614222;0.105567;, - 0.632355;0.054583;, - 0.631513;0.105567;, - 0.632355;0.047634;, - 0.631655;0.105567;, - 0.642504;0.054907;, - 0.641371;0.059108;, - 0.642504;0.046861;, - 0.641513;0.059108;, - 0.623009;0.082338;, - 0.622867;0.082338;, - 0.509253;0.305599;, - 0.976866;0.021766;, - 0.976865;0.021766;, - 0.428474;0.398384;, - 0.976865;0.021761;, - 0.446824;0.398384;, - 0.487806;0.348420;, - 0.976866;0.021759;, - 0.487806;0.305599;, - 0.976866;0.021774;, - 0.976866;0.021751;, - 0.976865;0.021751;, - 0.976865;0.021774;, - 0.977141;0.020800;, - 0.100000;0.093505;, - 0.976866;0.021771;, - 0.664403;0.047634;, - 0.662769;0.101237;, - 0.664403;0.054583;, - 0.662627;0.101237;, - 0.976858;0.021771;, - 0.976858;0.021745;, - 0.662627;0.072716;, - 0.664398;0.054907;, - 0.976866;0.021745;, - 0.664398;0.046861;, - 0.662769;0.072716;, - 0.643881;0.091960;, - 0.976866;0.021763;, - 0.644948;0.047634;, - 0.644948;0.047634;, - 0.643881;0.072716;, - 0.643739;0.072716;, - 0.643739;0.091960;, - 0.644948;0.054583;, - 0.644948;0.054583;, - 0.976858;0.021763;, - 0.100556;0.092394;, - 0.977981;0.020800;, - 0.208814;0.260656;, - 0.283754;0.161235;, - 0.298999;0.161235;, - 0.241037;0.260656;, - 0.283754;0.199532;, - 0.298999;0.199532;, - 0.361884;0.161235;, - 0.361884;0.199532;, - 0.420957;0.161235;, - 0.509253;0.248506;, - 0.509253;0.280621;, - 0.487806;0.248506;, - 0.420957;0.199532;, - 0.487806;0.280621;, - 0.100000;0.059231;, - 0.012381;0.015444;, - 0.100556;0.058120;, - 0.040952;0.015444;, - 0.525933;0.055547;, - 0.977200;0.020086;, - 0.525933;0.088970;, - 0.977200;0.021691;, - 0.112049;0.739555;, - 0.977650;0.021116;, - 0.107912;0.774863;, - 0.977650;0.021611;, - 0.098954;0.754438;, - 0.107912;0.799522;, - 0.108081;0.801413;, - 0.977650;0.020891;, - 0.113989;0.678436;, - 0.114706;0.723546;, - 0.977710;0.020825;, - 0.113989;0.682655;, - 0.977948;0.020825;, - 0.113989;0.699164;, - 0.977710;0.021611;, - 0.098954;0.763075;, - 0.977948;0.021611;, - 0.977408;0.021428;, - 0.977948;0.021957;, - 0.977408;0.020876;, - 0.108081;0.805506;, - 0.977710;0.021957;, - 0.978355;0.020834;, - 0.183867;0.893176;, - 0.978355;0.020876;, - 0.183867;0.895832;, - 0.185102;0.841937;, - 0.185102;0.860443;, - 0.185102;0.834740;, - 0.183867;0.872366;, - 0.185102;0.842644;, - 0.185102;0.860121;, - 0.185102;0.834419;, - 0.183867;0.929483;, - 0.095236;0.694759;, - 0.094847;0.743240;, - 0.061534;0.743240;, - 0.061923;0.694759;, - 0.011573;0.727665;, - 0.010595;0.667221;, - 0.095236;0.674031;, - 0.061923;0.674031;, - 0.010595;0.700534;, - 0.011573;0.706937;, - 0.538022;0.055547;, - 0.977733;0.020086;, - 0.538022;0.088970;, - 0.977733;0.021691;, - 0.732037;0.792106;, - 0.732037;0.771873;, - 0.752646;0.815263;, - 0.745670;0.746966;, - 0.756254;0.782280;, - 0.745384;0.689022;, - 0.796474;0.958596;, - 0.977029;0.021491;, - 0.783144;0.959274;, - 0.732037;0.813119;, - 0.773659;0.815263;, - 0.745384;0.707912;, - 0.774089;0.782280;, - 0.977169;0.021491;, - 0.821046;0.958596;, - 0.732037;0.771873;, - 0.752646;0.815263;, - 0.732037;0.792106;, - 0.745384;0.689022;, - 0.745670;0.746966;, - 0.756254;0.782280;, - 0.783144;0.959274;, - 0.796474;0.958596;, - 0.977029;0.021491;, - 0.977179;0.021888;, - 0.875226;0.929324;, - 0.875221;0.929347;, - 0.978676;0.928821;, - 0.850649;0.929347;, - 0.850654;0.929324;, - 0.768789;0.901150;, - 0.798397;0.900318;, - 0.821046;0.900318;, - 0.977179;0.021888;, - 0.875221;0.929347;, - 0.875226;0.929324;, - 0.768789;0.901150;, - 0.798397;0.900318;, - 0.978676;0.928821;, - 0.850649;0.929347;, - 0.850654;0.929324;, - 0.977179;0.021556;, - 0.888053;0.829159;, - 0.875226;0.866894;, - 0.888053;0.849635;, - 0.978676;0.865984;, - 0.850654;0.866894;, - 0.768789;0.849484;, - 0.977001;0.021331;, - 0.798397;0.848516;, - 0.821046;0.848516;, - 0.977194;0.021331;, - 0.977179;0.021556;, - 0.875226;0.866894;, - 0.888053;0.829159;, - 0.768789;0.849484;, - 0.977001;0.021331;, - 0.798397;0.848516;, - 0.888053;0.849635;, - 0.978676;0.865984;, - 0.850654;0.866894;, - 0.711138;0.630605;, - 0.976859;0.021745;, - 0.731947;0.631618;, - 0.785081;0.704734;, - 0.968087;0.704061;, - 0.976865;0.021745;, - 0.758409;0.631618;, - 0.852822;0.704734;, - 0.967843;0.704183;, - 0.711138;0.630605;, - 0.976859;0.021745;, - 0.731947;0.631618;, - 0.977922;0.019611;, - 0.464119;0.857811;, - 0.481521;0.845698;, - 0.979961;0.019611;, - 0.510688;0.845698;, - 0.977782;0.020245;, - 0.486403;0.033711;, - 0.978483;0.020245;, - 0.977782;0.021604;, - 0.486403;0.107756;, - 0.479421;0.992755;, - 0.447425;0.964429;, - 0.447130;0.971190;, - 0.512606;0.992755;, - 0.447130;0.995439;, - 0.447425;0.932359;, - 0.978215;0.022379;, - 0.978043;0.019009;, - 0.979394;0.019009;, - 0.980585;0.022379;, - 0.097140;0.444659;, - 0.972515;0.112669;, - 0.097196;0.430691;, - 0.096024;0.418061;, - 0.151500;0.418061;, - 0.982745;0.112669;, - 0.119679;0.444805;, - 0.119735;0.430837;, - 0.135500;0.418061;, - 0.117609;0.418061;, - 0.724760;0.577911;, - 0.731947;0.578171;, - 0.715679;0.559671;, - 0.731947;0.559671;, - 0.714579;0.526087;, - 0.758409;0.578171;, - 0.758409;0.559671;, - 0.714579;0.552549;, - 0.724760;0.577911;, - 0.731947;0.578171;, - 0.715679;0.559671;, - 0.731947;0.559671;, - 0.714579;0.526087;, - 0.979079;0.019428;, - 0.705752;0.498336;, - 0.676086;0.498336;, - 0.977499;0.019428;, - 0.662365;0.498579;, - 0.464119;0.833563;, - 0.481521;0.808872;, - 0.465483;0.825413;, - 0.510688;0.808872;, - 0.977782;0.019429;, - 0.977759;0.019088;, - 0.465483;0.806829;, - 0.978498;0.019088;, - 0.978483;0.019429;, - 0.479421;0.872712;, - 0.447425;0.883464;, - 0.978215;0.018687;, - 0.512606;0.872712;, - 0.980585;0.018687;, - 0.480373;0.096439;, - 0.835909;0.220903;, - 0.978103;0.021676;, - 0.835909;0.217521;, - 0.793123;0.111296;, - 0.818815;0.126731;, - 0.806177;0.111554;, - 0.818815;0.114854;, - 0.818477;0.111554;, - 0.818506;0.111551;, - 0.977141;0.022000;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.016518;0.087040;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012381;0.052598;, - 0.012437;0.059286;, - 0.705752;0.437973;, - 0.670927;0.382443;, - 0.658868;0.382686;, - 0.676086;0.437973;, - 0.651163;0.438217;, - 0.856740;0.220903;, - 0.978563;0.021676;, - 0.979321;0.021676;, - 0.891110;0.220903;, - 0.891110;0.217521;, - 0.856740;0.217521;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.064652;0.058120;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.040952;0.052598;, - 0.036926;0.087040;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.083840;0.509236;, - 0.083840;0.509233;, - 0.083855;0.509239;, - 0.080480;0.504795;, - 0.082948;0.497871;, - 0.048288;0.505028;, - 0.080510;0.504641;, - 0.080480;0.504793;, - 0.007516;0.505028;, - 0.080480;0.504795;, - 0.082948;0.464938;, - 0.083840;0.509232;, - 0.083840;0.509222;, - 0.083840;0.509230;, - 0.187000;0.166807;, - 0.187400;0.177905;, - 0.267815;0.224141;, - 0.187000;0.173806;, - 0.260407;0.224141;, - 0.187400;0.177905;, - 0.972515;0.072573;, - 0.972515;0.081652;, - 0.096024;0.309203;, - 0.096024;0.333850;, - 0.982745;0.072573;, - 0.151500;0.309203;, - 0.982745;0.081652;, - 0.151500;0.333850;, - 0.117609;0.309203;, - 0.135500;0.309203;, - 0.135500;0.333850;, - 0.117609;0.333850;, - 0.166720;0.505346;, - 0.223123;0.507837;, - 0.164252;0.497871;, - 0.166720;0.505303;, - 0.163360;0.509056;, - 0.156752;0.504651;, - 0.155496;0.497871;, - 0.126960;0.504654;, - 0.125945;0.497871;, - 0.126505;0.509127;, - 0.126400;0.509152;, - 0.156976;0.509006;, - 0.156976;0.508959;, - 0.166720;0.505346;, - 0.164252;0.464938;, - 0.189418;0.507837;, - 0.163360;0.509056;, - 0.156752;0.504688;, - 0.155496;0.464938;, - 0.156976;0.508959;, - 0.156976;0.508964;, - 0.126400;0.509215;, - 0.126400;0.509152;, - 0.126960;0.504789;, - 0.125945;0.464938;, - 0.745394;0.090556;, - 0.270545;0.320182;, - 0.280385;0.318542;, - 0.270545;0.362200;, - 0.280385;0.360561;, - 0.270545;0.379708;, - 0.296785;0.384628;, - 0.297409;0.384957;, - 0.298860;0.427511;, - 0.291704;0.354200;, - 0.291626;0.353945;, - 0.291704;0.318563;, - 0.291626;0.318654;, - 0.356911;0.427576;, - 0.361011;0.366363;, - 0.361042;0.366416;, - 0.345901;0.427576;, - 0.345718;0.427511;, - 0.349473;0.384957;, - 0.361490;0.318563;, - 0.355319;0.354200;, - 0.355564;0.354180;, - 0.301464;0.369666;, - 0.301466;0.370190;, - 0.305321;0.355683;, - 0.342793;0.369666;, - 0.305321;0.318563;, - 0.428474;0.427576;, - 0.435854;0.366363;, - 0.436245;0.366416;, - 0.446824;0.427576;, - 0.470350;0.348420;, - 0.455528;0.351583;, - 0.455865;0.350599;, - 0.421864;0.306189;, - 0.427871;0.354200;, - 0.427885;0.354180;, - 0.470350;0.305599;, - 0.455865;0.307346;, - 0.444892;0.306189;, - 0.444966;0.306476;, - 0.444892;0.341826;, - 0.444966;0.341115;, - 0.835909;0.151790;, - 0.835909;0.147563;, - 0.978103;0.020028;, - 0.806054;0.037284;, - 0.816593;0.026083;, - 0.818506;0.037251;, - 0.818354;0.037284;, - 0.816593;0.013880;, - 0.793123;0.037628;, - 0.012437;0.120825;, - 0.047090;0.120769;, - 0.977044;0.022066;, - 0.977044;0.020660;, - 0.069496;0.120769;, - 0.977118;0.021875;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.977141;0.022000;, - 0.016518;0.087040;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.977044;0.020660;, - 0.977118;0.021875;, - 0.069496;0.120769;, - 0.977044;0.022066;, - 0.047090;0.120769;, - 0.012437;0.120825;, - 0.513845;0.044407;, - 0.891110;0.151790;, - 0.856740;0.151790;, - 0.856740;0.147563;, - 0.978563;0.020028;, - 0.891110;0.147563;, - 0.979321;0.020028;, - 0.859301;0.400070;, - 0.859000;0.396008;, - 0.859000;0.396004;, - 0.975690;0.024113;, - 0.859301;0.410331;, - 0.873399;0.410331;, - 0.976407;0.024113;, - 0.873399;0.400070;, - 0.873466;0.396199;, - 0.863305;0.291435;, - 0.859200;0.327200;, - 0.863305;0.280722;, - 0.863800;0.390604;, - 0.863600;0.330400;, - 0.975690;0.020550;, - 0.978600;0.022376;, - 0.863800;0.334800;, - 0.863800;0.334805;, - 0.858768;0.334964;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978312;0.020660;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.036926;0.087040;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.978312;0.020660;, - 0.976888;0.021758;, - 0.096024;0.239370;, - 0.976871;0.021721;, - 0.976888;0.021778;, - 0.972515;0.046851;, - 0.976878;0.021721;, - 0.095747;0.209137;, - 0.972515;0.040799;, - 0.096024;0.222939;, - 0.095799;0.195670;, - 0.117331;0.195815;, - 0.135500;0.222939;, - 0.117609;0.222939;, - 0.117279;0.209282;, - 0.982745;0.040799;, - 0.151500;0.222939;, - 0.982745;0.046851;, - 0.151500;0.239370;, - 0.117609;0.239370;, - 0.135500;0.239370;, - 0.976878;0.021710;, - 0.972515;0.043825;, - 0.976889;0.021745;, - 0.982745;0.043825;, - 0.151500;0.231155;, - 0.135500;0.231155;, - 0.117609;0.231155;, - 0.096024;0.231155;, - 0.976871;0.021710;, - 0.976889;0.021726;, - 0.270545;0.260656;, - 0.281983;0.258879;, - 0.282025;0.259016;, - 0.283754;0.230704;, - 0.298999;0.230704;, - 0.298179;0.247924;, - 0.297409;0.247754;, - 0.291704;0.268942;, - 0.291626;0.270159;, - 0.361884;0.230704;, - 0.361064;0.246283;, - 0.361490;0.259662;, - 0.361506;0.259643;, - 0.305321;0.259662;, - 0.305997;0.259643;, - 0.420957;0.230704;, - 0.470350;0.248506;, - 0.420819;0.247754;, - 0.420137;0.246283;, - 0.455865;0.282116;, - 0.470350;0.280621;, - 0.455528;0.281128;, - 0.414254;0.259662;, - 0.413650;0.259643;, - 0.444892;0.287502;, - 0.444966;0.288312;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012437;0.059286;, - 0.012381;0.052598;, - 0.146322;0.732423;, - 0.146322;0.766866;, - 0.146863;0.801413;, - 0.146016;0.768382;, - 0.146322;0.714883;, - 0.146626;0.678436;, - 0.132939;0.801413;, - 0.132532;0.799522;, - 0.146626;0.682655;, - 0.146626;0.699164;, - 0.146016;0.772113;, - 0.978448;0.021428;, - 0.146016;0.769142;, - 0.146863;0.805506;, - 0.978448;0.020876;, - 0.978075;0.021428;, - 0.978075;0.020876;, - 0.132939;0.805506;, - 0.978617;0.020834;, - 0.231518;0.893176;, - 0.978617;0.020876;, - 0.231518;0.895832;, - 0.232804;0.841937;, - 0.232804;0.834740;, - 0.231518;0.872366;, - 0.232804;0.842644;, - 0.232804;0.834419;, - 0.231518;0.929483;, - 0.184482;0.986461;, - 0.183964;0.977510;, - 0.183964;0.944197;, - 0.978578;0.018557;, - 0.979022;0.018557;, - 0.184482;0.995098;, - 0.147982;0.824798;, - 0.216679;0.814796;, - 0.064652;0.058120;, - 0.040952;0.052598;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.512606;0.947429;, - 0.479421;0.947429;, - 0.463765;0.932537;, - 0.463765;0.932537;, - 0.479421;0.947429;, - 0.463765;0.887007;, - 0.479421;0.885961;, - 0.512606;0.885961;, - 0.830295;0.111366;, - 0.830238;0.111442;, - 0.841218;0.111366;, - 0.841314;0.111442;, - 0.841241;0.111373;, - 0.824065;0.108391;, - 0.824024;0.108408;, - 0.826483;0.114661;, - 0.826420;0.114626;, - 0.826483;0.126731;, - 0.843742;0.126731;, - 0.914073;0.111583;, - 0.843742;0.114661;, - 0.896810;0.111583;, - 0.843674;0.114607;, - 0.484986;0.048318;, - 0.860172;0.035810;, - 0.830283;0.035767;, - 0.830283;0.035763;, - 0.874513;0.073311;, - 0.874515;0.073245;, - 0.874515;0.043185;, - 0.874513;0.043157;, - 0.824065;0.039785;, - 0.824024;0.039738;, - 0.914073;0.072339;, - 0.896810;0.072339;, - 0.880635;0.073336;, - 0.914073;0.039635;, - 0.878714;0.013880;, - 0.896810;0.039635;, - 0.878714;0.025890;, - 0.880635;0.041337;, - 0.880627;0.041351;, - 0.862452;0.013880;, - 0.862452;0.025890;, - 0.864354;0.033144;, - 0.824507;0.013880;, - 0.824507;0.025890;, - 0.826409;0.033187;, - 0.874000;0.390598;, - 0.874000;0.390602;, - 0.977189;0.020514;, - 0.978600;0.020878;, - 0.885381;0.334233;, - 0.918247;0.169976;, - 0.918247;0.167944;, - 0.918025;0.131270;, - 0.918025;0.159841;, - 0.918247;0.168000;, - 0.918247;0.170032;, - 0.182508;0.766866;, - 0.178079;0.768382;, - 0.208776;0.768315;, - 0.191817;0.726879;, - 0.208776;0.727114;, - 0.193589;0.678436;, - 0.212995;0.768315;, - 0.182405;0.769142;, - 0.212995;0.722253;, - 0.212995;0.722253;, - 0.198628;0.682655;, - 0.198628;0.682655;, - 0.229504;0.768315;, - 0.182405;0.772113;, - 0.198628;0.699164;, - 0.229504;0.722253;, - 0.217974;0.804906;, - 0.201590;0.811736;, - 0.206868;0.780799;, - 0.217974;0.781483;, - 0.237407;0.804906;, - 0.892228;0.291435;, - 0.891228;0.302435;, - 0.892228;0.280722;, - 0.892253;0.306969;, - 0.892222;0.307059;, - 0.936839;0.410331;, - 0.979634;0.022435;, - 0.966333;0.367325;, - 0.936839;0.400070;, - 0.924808;0.367270;, - 0.955046;0.367325;, - 0.924796;0.367275;, - 0.955046;0.332160;, - 0.942046;0.332160;, - 0.966333;0.332160;, - 0.980710;0.020420;, - 0.966333;0.332160;, - 0.978600;0.017357;, - 0.920766;0.363703;, - 0.920741;0.363700;, - 0.920780;0.363679;, - 0.936500;0.332500;, - 0.979993;0.020455;, - 0.978600;0.018074;, - 0.925926;0.333333;, - 0.686697;0.042090;, - 0.686383;0.041777;, - 0.711212;0.041930;, - 0.722178;0.040237;, - 0.711221;0.041841;, - 0.711058;0.017096;, - 0.722178;0.019530;, - 0.710839;0.016926;, - 0.686540;0.017166;, - 0.686540;0.017172;, - 0.710745;0.016972;, - 0.742470;0.040237;, - 0.742470;0.019530;, - 0.711218;0.041900;, - 0.943531;0.170051;, - 0.957753;0.175131;, - 0.968940;0.133152;, - 0.957753;0.185722;, - 0.983323;0.133152;, - 0.943531;0.185722;, - 0.943531;0.167944;, - 0.943309;0.131325;, - 0.957753;0.173024;, - 0.957531;0.135035;, - 0.966079;0.134702;, - 0.943309;0.159786;, - 0.943531;0.168000;, - 0.957753;0.173079;, - 0.966079;0.155887;, - 0.957531;0.156076;, - 0.943531;0.170107;, - 0.943531;0.185778;, - 0.957753;0.185778;, - 0.983323;0.157437;, - 0.957753;0.175186;, - 0.968940;0.157437;, - 0.983323;0.134646;, - 0.983323;0.155943;, - 0.966333;0.305786;, - 0.942926;0.280722;, - 0.955046;0.305786;, - 0.942926;0.291435;, - 0.942300;0.306196;, - 0.942300;0.306200;, - 0.937193;0.291435;, - 0.937193;0.302435;, - 0.937193;0.280722;, - 0.931623;0.307069;, - 0.931630;0.307059;, - 0.936303;0.309600;, - 0.713500;0.089000;, - 0.690009;0.103508;, - 0.699532;0.075033;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.699532;0.102968;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.713500;0.089000;, - 0.673214;0.103508;, - 0.672880;0.074825;, - 0.672880;0.089111;, - 0.672880;0.103397;, - 0.672880;0.104508;, - 0.672880;0.090222;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.699532;0.075033;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.699532;0.102968;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.673214;0.089222;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.689675;0.074825;, - 0.727468;0.075033;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.727468;0.102968;, - 0.689675;0.103397;, - 0.672880;0.089111;, - 0.672880;0.074825;, - 0.673214;0.074937;, - 0.672880;0.075937;, - 0.672880;0.103397;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.727468;0.075033;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.727468;0.102968;, - 0.686540;0.017110;, - 0.686477;0.042153;, - 0.918247;0.185722;, - 0.918247;0.185778;, - 0.918247;0.169976;, - 0.918247;0.167944;, - 0.918025;0.131270;, - 0.918025;0.159841;, - 0.918247;0.168000;, - 0.918247;0.170032;, - 0.686697;0.042090;, - 0.686383;0.041777;, - 0.711212;0.041930;, - 0.722178;0.040237;, - 0.711221;0.041841;, - 0.711058;0.017096;, - 0.722178;0.019530;, - 0.710839;0.016926;, - 0.686540;0.017166;, - 0.686540;0.017172;, - 0.710745;0.016972;, - 0.742470;0.040237;, - 0.742470;0.019530;, - 0.711218;0.041900;, - 0.943531;0.170051;, - 0.957753;0.175131;, - 0.968940;0.133152;, - 0.957753;0.185722;, - 0.983323;0.133152;, - 0.943531;0.185722;, - 0.943531;0.167944;, - 0.943309;0.131325;, - 0.957753;0.173024;, - 0.957531;0.135035;, - 0.966079;0.134702;, - 0.943309;0.159786;, - 0.943531;0.168000;, - 0.957753;0.173079;, - 0.966079;0.155887;, - 0.957531;0.156076;, - 0.943531;0.170107;, - 0.943531;0.185778;, - 0.957753;0.185778;, - 0.983323;0.157437;, - 0.957753;0.175186;, - 0.968940;0.157437;, - 0.983323;0.134646;, - 0.983323;0.155943;, - 0.818815;0.114854;, - 0.818506;0.111551;, - 0.806177;0.111554;, - 0.818477;0.111554;, - 0.806054;0.037284;, - 0.818354;0.037284;, - 0.816593;0.026083;, - 0.818506;0.037251;, - 0.830295;0.111366;, - 0.830238;0.111442;, - 0.841218;0.111366;, - 0.841241;0.111373;, - 0.841314;0.111442;, - 0.824024;0.108408;, - 0.824065;0.108391;, - 0.826483;0.114661;, - 0.826420;0.114626;, - 0.896810;0.111583;, - 0.843742;0.114661;, - 0.843674;0.114607;, - 0.860172;0.035810;, - 0.830283;0.035767;, - 0.830283;0.035763;, - 0.874515;0.073245;, - 0.874513;0.073311;, - 0.874515;0.043185;, - 0.874513;0.043157;, - 0.824065;0.039785;, - 0.824024;0.039738;, - 0.896810;0.072339;, - 0.880635;0.073336;, - 0.878714;0.025890;, - 0.880635;0.041337;, - 0.880627;0.041351;, - 0.896810;0.039635;, - 0.862452;0.025890;, - 0.864354;0.033144;, - 0.824507;0.025890;, - 0.826409;0.033187;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.977022;0.021746;, - 0.976941;0.021762;, - 0.186550;0.382365;, - 0.976866;0.021710;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021757;, - 0.976874;0.021718;, - 0.186550;0.382338;, - 0.976831;0.021731;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.178570;0.404936;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021859;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.178570;0.404949;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.976941;0.021651;, - 0.976887;0.021710;, - 0.186550;0.382365;, - 0.178570;0.382418;, - 0.976887;0.021756;, - 0.176404;0.382494;, - 0.178572;0.404842;, - 0.176177;0.404762;, - 0.186138;0.413602;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.178574;0.404842;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.976986;0.021718;, - 0.976853;0.021731;, - 0.186550;0.382334;, - 0.178570;0.382379;, - 0.976853;0.021747;, - 0.176404;0.382508;, - 0.178570;0.404934;, - 0.176176;0.404762;, - 0.976872;0.021776;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.976919;0.021730;, - 0.186550;0.382342;, - 0.178570;0.382383;, - 0.976919;0.021690;, - 0.176404;0.382505;, - 0.178570;0.404955;, - 0.176178;0.404770;, - 0.976887;0.021767;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.977022;0.021746;, - 0.976941;0.021762;, - 0.186550;0.382365;, - 0.976866;0.021710;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021757;, - 0.976874;0.021718;, - 0.186550;0.382338;, - 0.976831;0.021731;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.178570;0.404936;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021859;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.178570;0.404949;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.976941;0.021651;, - 0.976887;0.021710;, - 0.186550;0.382365;, - 0.178570;0.382418;, - 0.976887;0.021756;, - 0.176404;0.382494;, - 0.178572;0.404842;, - 0.176177;0.404762;, - 0.186138;0.413602;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.178574;0.404842;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.976986;0.021718;, - 0.976853;0.021731;, - 0.186550;0.382334;, - 0.178570;0.382379;, - 0.976853;0.021747;, - 0.176404;0.382508;, - 0.178570;0.404934;, - 0.176176;0.404762;, - 0.976872;0.021776;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.976919;0.021730;, - 0.186550;0.382342;, - 0.178570;0.382383;, - 0.976919;0.021690;, - 0.176404;0.382505;, - 0.178570;0.404955;, - 0.176178;0.404770;, - 0.976887;0.021767;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.977022;0.021746;, - 0.976941;0.021762;, - 0.186550;0.382365;, - 0.976866;0.021710;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021757;, - 0.976874;0.021718;, - 0.186550;0.382338;, - 0.976831;0.021731;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.178570;0.404936;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021859;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.178570;0.404949;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.976941;0.021651;, - 0.976887;0.021710;, - 0.186550;0.382365;, - 0.178570;0.382418;, - 0.976887;0.021756;, - 0.176404;0.382494;, - 0.178572;0.404842;, - 0.176177;0.404762;, - 0.186138;0.413602;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.178574;0.404842;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.976986;0.021718;, - 0.976853;0.021731;, - 0.186550;0.382334;, - 0.178570;0.382379;, - 0.976853;0.021747;, - 0.176404;0.382508;, - 0.178570;0.404934;, - 0.176176;0.404762;, - 0.976872;0.021776;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.976919;0.021730;, - 0.186550;0.382342;, - 0.178570;0.382383;, - 0.976919;0.021690;, - 0.176404;0.382505;, - 0.178570;0.404955;, - 0.176178;0.404770;, - 0.976887;0.021767;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.977022;0.021746;, - 0.976941;0.021762;, - 0.186550;0.382365;, - 0.976866;0.021710;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021757;, - 0.976874;0.021718;, - 0.186550;0.382338;, - 0.976831;0.021731;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.178570;0.404936;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021859;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.178570;0.404949;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.976941;0.021651;, - 0.976887;0.021710;, - 0.186550;0.382365;, - 0.178570;0.382418;, - 0.976887;0.021756;, - 0.176404;0.382494;, - 0.178572;0.404842;, - 0.176177;0.404762;, - 0.186138;0.413602;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.178574;0.404842;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.976986;0.021718;, - 0.976853;0.021731;, - 0.186550;0.382334;, - 0.178570;0.382379;, - 0.976853;0.021747;, - 0.176404;0.382508;, - 0.178570;0.404934;, - 0.176176;0.404762;, - 0.976872;0.021776;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.976919;0.021730;, - 0.186550;0.382342;, - 0.178570;0.382383;, - 0.976919;0.021690;, - 0.176404;0.382505;, - 0.178570;0.404955;, - 0.176178;0.404770;, - 0.976887;0.021767;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.673214;0.103508;, - 0.672880;0.074825;, - 0.672880;0.089111;, - 0.672880;0.103397;, - 0.672880;0.104508;, - 0.672880;0.090222;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.690009;0.089222;, - 0.673214;0.089222;, - 0.690009;0.089222;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.672880;0.089111;, - 0.672880;0.074825;, - 0.673214;0.074937;, - 0.672880;0.075937;, - 0.672880;0.103397;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.673214;0.103508;, - 0.672880;0.074825;, - 0.672880;0.089111;, - 0.672880;0.103397;, - 0.672880;0.104508;, - 0.672880;0.090222;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.690009;0.089222;, - 0.673214;0.089222;, - 0.690009;0.089222;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.672880;0.089111;, - 0.672880;0.074825;, - 0.673214;0.074937;, - 0.672880;0.075937;, - 0.672880;0.103397;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.062673;0.171389;, - 0.123628;0.174197;, - 0.062673;0.153611;, - 0.123573;0.174197;, - 0.099649;0.174197;, - 0.040549;0.153611;, - 0.040549;0.171389;, - 0.099705;0.174197;, - 0.149444;0.168841;, - 0.090307;0.140477;, - 0.032025;0.171556;, - 0.032025;0.153778;, - 0.090251;0.140477;, - 0.167222;0.168841;, - 0.167222;0.154555;, - 0.086359;0.154444;, - 0.149444;0.154555;, - 0.086414;0.154444;, - 0.149444;0.140270;, - 0.031858;0.171389;, - 0.090307;0.168412;, - 0.167222;0.140270;, - 0.031858;0.153611;, - 0.090251;0.168412;, - 0.149444;0.168619;, - 0.071531;0.171556;, - 0.133026;0.140477;, - 0.149444;0.154333;, - 0.136919;0.154444;, - 0.167222;0.154333;, - 0.136864;0.154444;, - 0.167222;0.168619;, - 0.071531;0.153778;, - 0.132971;0.140477;, - 0.149444;0.140048;, - 0.133026;0.168412;, - 0.071364;0.171389;, - 0.071364;0.153611;, - 0.132971;0.168412;, - 0.167222;0.140048;, - 0.123573;0.134691;, - 0.062840;0.153778;, - 0.062840;0.171556;, - 0.123628;0.134691;, - 0.040716;0.171556;, - 0.099705;0.134691;, - 0.040716;0.153778;, - 0.099649;0.134691;, - 0.745439;0.090556;, - 0.736667;0.086111;, - 0.760385;0.107030;, - 0.760111;0.107155;, - 0.745556;0.081667;, - 0.768028;0.107043;, - 0.760428;0.107343;, - 0.736667;0.095000;, - 0.759889;0.107155;, - 0.768593;0.107030;, - 0.745556;0.099444;, - 0.760206;0.107343;, - 0.767806;0.107043;, - 0.754444;0.095000;, - 0.768292;0.107041;, - 0.768123;0.107230;, - 0.754444;0.086111;, - 0.768345;0.107230;, - 0.759885;0.107141;, - 0.745278;0.081667;, - 0.760172;0.056313;, - 0.767572;0.056213;, - 0.736389;0.086111;, - 0.760185;0.056325;, - 0.759855;0.056125;, - 0.736389;0.095000;, - 0.767593;0.056025;, - 0.760033;0.056525;, - 0.745278;0.099444;, - 0.767750;0.056213;, - 0.759950;0.056313;, - 0.754167;0.095000;, - 0.767667;0.056401;, - 0.767492;0.056136;, - 0.754167;0.086111;, - 0.759685;0.056136;, - 0.767889;0.056401;, - 0.745394;0.090556;, - 0.745439;0.090556;, - 0.736667;0.086111;, - 0.760385;0.107030;, - 0.760111;0.107155;, - 0.745556;0.081667;, - 0.768028;0.107043;, - 0.760428;0.107343;, - 0.736667;0.095000;, - 0.759889;0.107155;, - 0.768593;0.107030;, - 0.745556;0.099444;, - 0.760206;0.107343;, - 0.767806;0.107043;, - 0.754444;0.095000;, - 0.768292;0.107041;, - 0.768123;0.107230;, - 0.754444;0.086111;, - 0.768345;0.107230;, - 0.759885;0.107141;, - 0.745278;0.081667;, - 0.760172;0.056313;, - 0.767572;0.056213;, - 0.736389;0.086111;, - 0.760185;0.056325;, - 0.759855;0.056125;, - 0.736389;0.095000;, - 0.767593;0.056025;, - 0.760033;0.056525;, - 0.745278;0.099444;, - 0.767750;0.056213;, - 0.759950;0.056313;, - 0.754167;0.095000;, - 0.767667;0.056401;, - 0.767492;0.056136;, - 0.754167;0.086111;, - 0.759685;0.056136;, - 0.767889;0.056401;, - 0.745394;0.090556;, - 0.472531;0.024249;, - 0.403337;0.024249;, - 0.398724;0.111289;, - 0.472531;0.111289;, - 0.976615;0.021333;, - 0.977548;0.022780;, - 0.389242;0.879776;, - 0.401882;0.879805;, - 0.166456;0.778736;, - 0.959048;0.512451;, - 0.959048;0.396487;, - 0.977044;0.021392;, - 0.759894;0.521686;, - 0.713500;0.089000;, - 0.641115;0.577911;, - 0.569468;0.863191;, - 0.579224;0.863191;, - 0.593834;0.863191;, - 0.977010;0.021888;, - 0.933173;0.928821;, - 0.713399;0.743062;, - 0.976753;0.021392;, - 0.759894;0.504977;, - 0.835111;0.458703;, - 0.761022;0.407988;, - 0.730511;0.909761;, - 0.555516;0.785034;, - 0.556456;0.768150;, - 0.546440;0.785034;, - 0.546440;0.678549;, - 0.547380;0.762180;, - 0.555516;0.815257;, - 0.546440;0.708772;, - 0.546440;0.815257;, - 0.555516;0.785034;, - 0.556456;0.768150;, - 0.546440;0.785034;, - 0.547380;0.762180;, - 0.546440;0.678549;, - 0.302199;0.946783;, - 0.263560;0.948159;, - 0.260667;0.941319;, - 0.295370;0.940241;, - 0.315857;0.987318;, - 0.315702;0.988050;, - 0.266264;0.990540;, - 0.313333;0.864576;, - 0.977897;0.020979;, - 0.260667;0.862208;, - 0.976665;0.020882;, - 0.313481;0.868559;, - 0.260667;0.866372;, - 0.977900;0.021141;, - 0.976665;0.021052;, - 0.435701;0.551310;, - 0.435652;0.551397;, - 0.429940;0.549638;, - 0.387183;0.549880;, - 0.429993;0.549678;, - 0.321629;0.721642;, - 0.252376;0.725528;, - 0.327268;0.686475;, - 0.252469;0.686829;, - 0.268395;0.726256;, - 0.268350;0.726269;, - 0.268350;0.681512;, - 0.268350;0.673331;, - 0.268320;0.673278;, - 0.441209;0.535723;, - 0.436927;0.532459;, - 0.387183;0.531321;, - 0.734663;0.454345;, - 0.976616;0.021821;, - 0.734663;0.417325;, - 0.976753;0.021821;, - 0.734663;0.407988;, - 0.602106;0.785034;, - 0.603046;0.768150;, - 0.602106;0.678549;, - 0.603046;0.726360;, - 0.977044;0.021821;, - 0.734663;0.390297;, - 0.602106;0.815257;, - 0.602106;0.708772;, - 0.734663;0.454345;, - 0.734663;0.417325;, - 0.976616;0.021821;, - 0.976753;0.021821;, - 0.734663;0.407988;, - 0.602106;0.785034;, - 0.603046;0.768150;, - 0.602106;0.678549;, - 0.603046;0.726360;, - 0.595595;0.625155;, - 0.554509;0.627484;, - 0.554529;0.626267;, - 0.580962;0.627484;, - 0.580991;0.626267;, - 0.595595;0.625155;, - 0.554509;0.627484;, - 0.554529;0.626267;, - 0.361134;0.946783;, - 0.361134;0.946783;, - 0.977996;0.020954;, - 0.977996;0.020954;, - 0.361134;0.987318;, - 0.978082;0.021635;, - 0.361000;0.987971;, - 0.422412;0.920730;, - 0.401882;0.891889;, - 0.410299;0.920730;, - 0.401821;0.920276;, - 0.389242;0.891889;, - 0.980067;0.022644;, - 0.389864;0.107756;, - 0.980067;0.018289;, - 0.978467;0.022124;, - 0.389864;0.033711;, - 0.384220;0.964429;, - 0.383669;0.971190;, - 0.978043;0.021284;, - 0.384220;0.932359;, - 0.354305;0.837126;, - 0.353952;0.830714;, - 0.978015;0.019112;, - 0.266102;0.840349;, - 0.319271;0.843669;, - 0.319381;0.826383;, - 0.410299;0.893814;, - 0.401968;0.891888;, - 0.401821;0.893360;, - 0.401968;0.879776;, - 0.422412;0.893814;, - 0.160200;0.104403;, - 0.160200;0.104406;, - 0.137212;0.105146;, - 0.536902;0.329036;, - 0.138000;0.057480;, - 0.681176;0.318447;, - 0.144300;0.064700;, - 0.144303;0.104439;, - 0.144314;0.104446;, - 0.145500;0.051987;, - 0.556327;0.331772;, - 0.155000;0.058484;, - 0.155100;0.109098;, - 0.155100;0.109097;, - 0.149353;0.099465;, - 0.501218;0.382443;, - 0.520189;0.382686;, - 0.364053;0.752399;, - 0.252379;0.754120;, - 0.364806;0.755188;, - 0.364364;0.757451;, - 0.976859;0.021175;, - 0.268261;0.758812;, - 0.479354;0.575723;, - 0.458510;0.596617;, - 0.503402;0.596615;, - 0.447728;0.542094;, - 0.506719;0.603402;, - 0.457069;0.622806;, - 0.455833;0.603363;, - 0.387183;0.605783;, - 0.189000;0.104498;, - 0.189000;0.104494;, - 0.979923;0.019534;, - 0.194809;0.051841;, - 0.627550;0.331772;, - 0.979756;0.019534;, - 0.194800;0.109009;, - 0.194809;0.058456;, - 0.194800;0.109004;, - 0.160176;0.064647;, - 0.138000;0.057500;, - 0.138000;0.057489;, - 0.664930;0.253753;, - 0.536902;0.329201;, - 0.144300;0.064700;, - 0.144300;0.064686;, - 0.145500;0.051947;, - 0.556327;0.331158;, - 0.155000;0.058509;, - 0.155000;0.058496;, - 0.149353;0.070769;, - 0.339140;0.710426;, - 0.252510;0.673670;, - 0.330887;0.678159;, - 0.371135;0.691565;, - 0.360897;0.667221;, - 0.359134;0.662039;, - 0.252439;0.639745;, - 0.268320;0.641782;, - 0.463365;0.527209;, - 0.464792;0.522314;, - 0.189036;0.064647;, - 0.194809;0.051342;, - 0.979714;0.018363;, - 0.627550;0.331158;, - 0.194809;0.058489;, - 0.194808;0.058525;, - 0.979567;0.018437;, - 0.194808;0.058525;, - 0.761022;0.467576;, - 0.976616;0.021392;, - 0.761022;0.432294;, - 0.761022;0.417325;, - 0.976753;0.021392;, - 0.759894;0.497114;, - 0.761022;0.485217;, - 0.759894;0.504977;, - 0.761022;0.407988;, - 0.658376;0.785034;, - 0.659317;0.768150;, - 0.976682;0.021253;, - 0.658376;0.678549;, - 0.976682;0.020660;, - 0.659317;0.726360;, - 0.663523;0.967885;, - 0.977029;0.021804;, - 0.626448;0.967188;, - 0.761022;0.390297;, - 0.658376;0.815257;, - 0.977111;0.021253;, - 0.977111;0.020660;, - 0.658376;0.708772;, - 0.651019;0.967188;, - 0.977169;0.021804;, - 0.761022;0.467576;, - 0.976616;0.021392;, - 0.761022;0.432294;, - 0.761022;0.417325;, - 0.761022;0.485217;, - 0.759894;0.497114;, - 0.658376;0.785034;, - 0.976682;0.021253;, - 0.659317;0.768150;, - 0.658376;0.678549;, - 0.976682;0.020660;, - 0.659317;0.726360;, - 0.663523;0.967885;, - 0.977029;0.021804;, - 0.626448;0.967188;, - 0.527416;0.950131;, - 0.565046;0.950613;, - 0.579606;0.965780;, - 0.527416;0.965961;, - 0.580043;0.994122;, - 0.850936;0.929242;, - 0.850845;0.929228;, - 0.887671;0.928821;, - 0.875417;0.929228;, - 0.976841;0.021888;, - 0.875384;0.929242;, - 0.551988;0.950131;, - 0.551988;0.965961;, - 0.598963;0.994122;, - 0.565046;0.950613;, - 0.527416;0.950131;, - 0.527416;0.965961;, - 0.579606;0.965780;, - 0.580043;0.994122;, - 0.875384;0.929242;, - 0.875417;0.929228;, - 0.976841;0.021888;, - 0.850936;0.929242;, - 0.887671;0.928821;, - 0.850845;0.929228;, - 0.527416;0.879556;, - 0.564616;0.842129;, - 0.564663;0.842250;, - 0.565046;0.879109;, - 0.579606;0.879109;, - 0.579176;0.842129;, - 0.850845;0.866799;, - 0.979058;0.849635;, - 0.887671;0.865984;, - 0.976841;0.021556;, - 0.979058;0.829159;, - 0.875417;0.866799;, - 0.224270;0.065100;, - 0.224919;0.084722;, - 0.225106;0.084722;, - 0.224270;0.048234;, - 0.564663;0.866821;, - 0.551988;0.879556;, - 0.579224;0.866821;, - 0.579224;0.866821;, - 0.244397;0.048234;, - 0.236397;0.084722;, - 0.244397;0.065100;, - 0.236210;0.084722;, - 0.527416;0.879556;, - 0.565046;0.879109;, - 0.564616;0.842129;, - 0.564663;0.842250;, - 0.579606;0.879109;, - 0.579176;0.842129;, - 0.875417;0.866799;, - 0.979058;0.829159;, - 0.976841;0.021556;, - 0.224270;0.065100;, - 0.224919;0.084722;, - 0.224270;0.048234;, - 0.225106;0.084722;, - 0.850845;0.866799;, - 0.887671;0.865984;, - 0.979058;0.849635;, - 0.611242;0.631618;, - 0.554509;0.635865;, - 0.976859;0.021772;, - 0.785203;0.704550;, - 0.863801;0.704061;, - 0.569468;0.845659;, - 0.569464;0.845664;, - 0.579224;0.845659;, - 0.579219;0.845664;, - 0.593834;0.845659;, - 0.593829;0.845664;, - 0.580962;0.635834;, - 0.976865;0.021772;, - 0.852944;0.704550;, - 0.863556;0.704183;, - 0.569468;0.863191;, - 0.579224;0.863191;, - 0.593834;0.863191;, - 0.611242;0.631618;, - 0.554509;0.635865;, - 0.976859;0.021772;, - 0.569464;0.845664;, - 0.569468;0.845659;, - 0.579224;0.845659;, - 0.579219;0.845664;, - 0.593834;0.845659;, - 0.593829;0.845664;, - 0.367963;0.940241;, - 0.367963;0.940241;, - 0.977816;0.020844;, - 0.977816;0.020844;, - 0.389406;0.920276;, - 0.389242;0.879805;, - 0.384207;0.857811;, - 0.977922;0.022045;, - 0.977818;0.021385;, - 0.979961;0.022045;, - 0.979901;0.021385;, - 0.978467;0.020410;, - 0.402736;0.033711;, - 0.402736;0.107756;, - 0.622594;0.573857;, - 0.554529;0.569907;, - 0.633946;0.559671;, - 0.633105;0.526087;, - 0.554529;0.554319;, - 0.603619;0.582256;, - 0.554529;0.579134;, - 0.633105;0.552549;, - 0.580991;0.554319;, - 0.580991;0.569907;, - 0.580991;0.579134;, - 0.622594;0.573857;, - 0.554529;0.569907;, - 0.633946;0.559671;, - 0.633105;0.526087;, - 0.554529;0.554319;, - 0.603619;0.582256;, - 0.554529;0.579134;, - 0.507479;0.498336;, - 0.977973;0.021500;, - 0.528692;0.498579;, - 0.507479;0.454556;, - 0.543302;0.454800;, - 0.367963;0.864576;, - 0.979175;0.020979;, - 0.977816;0.019573;, - 0.367963;0.868559;, - 0.979175;0.021141;, - 0.977816;0.019640;, - 0.389242;0.891888;, - 0.389406;0.893360;, - 0.977818;0.019015;, - 0.384207;0.833563;, - 0.385571;0.825413;, - 0.385571;0.806829;, - 0.977759;0.021792;, - 0.979901;0.019015;, - 0.977888;0.021572;, - 0.397884;0.752564;, - 0.398545;0.755188;, - 0.398862;0.757451;, - 0.976859;0.019546;, - 0.512121;0.568048;, - 0.517276;0.615934;, - 0.503402;0.596604;, - 0.508481;0.615934;, - 0.458510;0.596617;, - 0.507949;0.622806;, - 0.455839;0.603402;, - 0.518180;0.622806;, - 0.517830;0.566416;, - 0.977028;0.021470;, - 0.268321;0.563588;, - 0.252469;0.564262;, - 0.421693;0.663596;, - 0.976971;0.021482;, - 0.268321;0.575890;, - 0.268320;0.576004;, - 0.252500;0.576100;, - 0.412754;0.639577;, - 0.405137;0.636980;, - 0.252439;0.590600;, - 0.268320;0.591865;, - 0.977757;0.021000;, - 0.074864;0.903802;, - 0.977689;0.021000;, - 0.977438;0.021042;, - 0.012834;0.883347;, - 0.062496;0.903802;, - 0.977689;0.021042;, - 0.977438;0.021090;, - 0.062496;0.906459;, - 0.012834;0.887585;, - 0.977757;0.021042;, - 0.074864;0.906459;, - 0.063781;0.849133;, - 0.029400;0.853180;, - 0.075645;0.841937;, - 0.063781;0.839881;, - 0.062673;0.886662;, - 0.013934;0.856006;, - 0.074525;0.881221;, - 0.075645;0.834740;, - 0.075645;0.842644;, - 0.063781;0.848812;, - 0.029400;0.910185;, - 0.075645;0.834419;, - 0.074525;0.927712;, - 0.063781;0.839559;, - 0.062673;0.918856;, - 0.013934;0.907360;, - 0.031044;0.883568;, - 0.977666;0.021127;, - 0.036394;0.859947;, - 0.031032;0.887264;, - 0.977666;0.021199;, - 0.977484;0.021042;, - 0.977566;0.021123;, - 0.024245;0.883347;, - 0.977566;0.021206;, - 0.024245;0.887585;, - 0.977484;0.021090;, - 0.036394;0.903469;, - 0.816137;0.458755;, - 0.826304;0.458703;, - 0.816137;0.447730;, - 0.826304;0.447511;, - 0.816137;0.417325;, - 0.803328;0.497114;, - 0.801759;0.485217;, - 0.826304;0.485564;, - 0.803328;0.504977;, - 0.835111;0.485564;, - 0.835111;0.458703;, - 0.835111;0.447511;, - 0.816137;0.407988;, - 0.803328;0.521686;, - 0.853824;0.485564;, - 0.853824;0.458703;, - 0.853824;0.447511;, - 0.816137;0.390297;, - 0.826304;0.458703;, - 0.816137;0.458755;, - 0.816137;0.447730;, - 0.826304;0.447511;, - 0.816137;0.417325;, - 0.803328;0.497114;, - 0.826304;0.485564;, - 0.801759;0.485217;, - 0.803328;0.504977;, - 0.835111;0.485564;, - 0.835111;0.447511;, - 0.816137;0.407988;, - 0.933173;0.928821;, - 0.599021;0.965780;, - 0.580043;0.972991;, - 0.976926;0.021640;, - 0.875384;0.961844;, - 0.977010;0.022036;, - 0.875221;0.961950;, - 0.850936;0.961844;, - 0.933173;0.956989;, - 0.850649;0.961950;, - 0.977010;0.021888;, - 0.692232;0.901150;, - 0.628371;0.899765;, - 0.598963;0.972991;, - 0.977145;0.021640;, - 0.651019;0.899765;, - 0.580043;0.972991;, - 0.976926;0.021640;, - 0.599021;0.965780;, - 0.875384;0.961844;, - 0.977010;0.022036;, - 0.875221;0.961950;, - 0.692232;0.901150;, - 0.628371;0.899765;, - 0.933173;0.956989;, - 0.850649;0.961950;, - 0.850936;0.961844;, - 0.933556;0.853730;, - 0.933173;0.865984;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.699532;0.075033;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.699532;0.102968;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.713500;0.089000;, - 0.794167;0.784460;, - 0.976861;0.021786;, - 0.879137;0.783971;, - 0.599021;0.879109;, - 0.976926;0.021228;, - 0.598591;0.842129;, - 0.598639;0.842250;, - 0.977010;0.021556;, - 0.933556;0.829159;, - 0.628371;0.847567;, - 0.692232;0.849484;, - 0.977001;0.021658;, - 0.304000;0.057351;, - 0.977489;0.019676;, - 0.225106;0.071820;, - 0.225106;0.082977;, - 0.267704;0.057351;, - 0.355783;0.108129;, - 0.304000;0.084427;, - 0.224919;0.071820;, - 0.977489;0.021390;, - 0.304000;0.118257;, - 0.355667;0.082000;, - 0.267704;0.084427;, - 0.224919;0.082977;, - 0.355487;0.108129;, - 0.278335;0.108348;, - 0.355667;0.107253;, - 0.355487;0.081986;, - 0.216469;0.110778;, - 0.215825;0.065556;, - 0.220182;0.082977;, - 0.255975;0.110778;, - 0.220182;0.071820;, - 0.977045;0.021219;, - 0.255975;0.093000;, - 0.977045;0.019848;, - 0.220369;0.071820;, - 0.215825;0.047778;, - 0.220369;0.082977;, - 0.216469;0.093000;, - 0.672880;0.074825;, - 0.673214;0.103508;, - 0.672880;0.089111;, - 0.672880;0.104508;, - 0.672880;0.103397;, - 0.672880;0.090222;, - 0.846680;0.784460;, - 0.878892;0.784093;, - 0.976880;0.021786;, - 0.977145;0.021228;, - 0.598639;0.866821;, - 0.651019;0.847567;, - 0.977194;0.021658;, - 0.373696;0.108129;, - 0.236397;0.082977;, - 0.373444;0.107253;, - 0.373399;0.081986;, - 0.373444;0.082000;, - 0.373399;0.108129;, - 0.236210;0.082977;, - 0.690009;0.103508;, - 0.699532;0.075033;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.699532;0.102968;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.599021;0.879109;, - 0.976926;0.021228;, - 0.598639;0.842250;, - 0.598591;0.842129;, - 0.977010;0.021556;, - 0.933556;0.829159;, - 0.692232;0.849484;, - 0.628371;0.847567;, - 0.977001;0.021658;, - 0.304000;0.057351;, - 0.225106;0.071820;, - 0.977489;0.019676;, - 0.267704;0.057351;, - 0.225106;0.082977;, - 0.355783;0.108129;, - 0.304000;0.084427;, - 0.977489;0.021390;, - 0.224919;0.071820;, - 0.304000;0.118257;, - 0.355667;0.082000;, - 0.224919;0.082977;, - 0.355487;0.108129;, - 0.267704;0.084427;, - 0.278335;0.108348;, - 0.355487;0.081986;, - 0.355667;0.107253;, - 0.216469;0.110778;, - 0.220182;0.082977;, - 0.215825;0.065556;, - 0.220182;0.071820;, - 0.977045;0.021219;, - 0.255975;0.110778;, - 0.255975;0.093000;, - 0.977045;0.019848;, - 0.220369;0.071820;, - 0.216469;0.093000;, - 0.215825;0.047778;, - 0.220369;0.082977;, - 0.933556;0.853730;, - 0.933173;0.865984;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.304000;0.023520;, - 0.355889;0.082000;, - 0.278335;0.033429;, - 0.355783;0.081986;, - 0.355889;0.107253;, - 0.673214;0.089222;, - 0.373667;0.082000;, - 0.373667;0.107253;, - 0.373696;0.081986;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.304000;0.023520;, - 0.355889;0.082000;, - 0.278335;0.033429;, - 0.355889;0.107253;, - 0.355783;0.081986;, - 0.034693;0.444254;, - 0.150000;0.418061;, - 0.944172;0.112669;, - 0.134655;0.418061;, - 0.036224;0.418061;, - 0.034750;0.430285;, - 0.641115;0.577911;, - 0.976867;0.020671;, - 0.582179;0.498579;, - 0.579256;0.454800;, - 0.391459;0.096439;, - 0.556537;0.174932;, - 0.556327;0.186090;, - 0.802622;0.317627;, - 0.523953;0.193454;, - 0.802641;0.317638;, - 0.556327;0.193454;, - 0.525422;0.173285;, - 0.808426;0.313459;, - 0.523953;0.186090;, - 0.977141;0.022000;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.016518;0.087040;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012381;0.052598;, - 0.012437;0.059286;, - 0.977888;0.019087;, - 0.976954;0.022400;, - 0.579256;0.382686;, - 0.976971;0.021659;, - 0.437958;0.755188;, - 0.437405;0.752756;, - 0.977028;0.021682;, - 0.437345;0.757451;, - 0.977028;0.021682;, - 0.976859;0.017325;, - 0.624989;0.174932;, - 0.627550;0.186090;, - 0.981273;0.019472;, - 0.981189;0.019555;, - 0.627550;0.193454;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.064652;0.058120;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.040952;0.052598;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.036926;0.087040;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.061440;0.582196;, - 0.061440;0.582191;, - 0.061440;0.582194;, - 0.056848;0.586710;, - 0.048289;0.586332;, - 0.056848;0.586661;, - 0.057496;0.640360;, - 0.056848;0.586684;, - 0.007516;0.586332;, - 0.057496;0.595107;, - 0.056848;0.586707;, - 0.061440;0.582197;, - 0.061440;0.582191;, - 0.061440;0.582193;, - 0.976930;0.021836;, - 0.198440;0.419736;, - 0.190825;0.353778;, - 0.194000;0.361263;, - 0.976915;0.021836;, - 0.214525;0.419736;, - 0.206698;0.353778;, - 0.214741;0.467736;, - 0.206698;0.371556;, - 0.198337;0.467736;, - 0.199079;0.371556;, - 0.976930;0.021836;, - 0.206698;0.361263;, - 0.977022;0.021746;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.976941;0.021762;, - 0.976866;0.021710;, - 0.186550;0.382365;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.976874;0.021757;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021718;, - 0.976831;0.021731;, - 0.186550;0.382338;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.178570;0.404936;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.976808;0.021859;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.178570;0.404949;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.081705;0.586605;, - 0.082024;0.640360;, - 0.083616;0.582528;, - 0.083616;0.582524;, - 0.081669;0.586745;, - 0.082024;0.595107;, - 0.083616;0.582530;, - 0.083616;0.582524;, - 0.187500;0.223505;, - 0.267815;0.177636;, - 0.187000;0.166775;, - 0.187500;0.223505;, - 0.187000;0.173798;, - 0.260407;0.177636;, - 0.149345;0.309203;, - 0.932877;0.072573;, - 0.134000;0.309203;, - 0.012391;0.309203;, - 0.150000;0.333850;, - 0.944172;0.081652;, - 0.134655;0.333850;, - 0.036224;0.333850;, - 0.944104;0.072573;, - 0.036080;0.309203;, - 0.179997;0.572433;, - 0.180010;0.572431;, - 0.178385;0.640360;, - 0.223123;0.571935;, - 0.163192;0.582575;, - 0.163192;0.582584;, - 0.166048;0.586672;, - 0.164847;0.640360;, - 0.157032;0.582529;, - 0.157032;0.582520;, - 0.126288;0.582528;, - 0.126343;0.586605;, - 0.125824;0.640360;, - 0.155927;0.640360;, - 0.157021;0.586605;, - 0.179972;0.572433;, - 0.180012;0.572439;, - 0.178385;0.595107;, - 0.189418;0.571935;, - 0.166048;0.586672;, - 0.164846;0.595107;, - 0.163192;0.582575;, - 0.163192;0.582587;, - 0.157032;0.582532;, - 0.157032;0.582520;, - 0.157014;0.586745;, - 0.155927;0.595107;, - 0.126324;0.586745;, - 0.125824;0.595107;, - 0.126288;0.582528;, - 0.187500;0.223504;, - 0.187000;0.166799;, - 0.187500;0.223497;, - 0.187000;0.173799;, - 0.260518;0.177636;, - 0.255000;0.173794;, - 0.254500;0.223545;, - 0.267926;0.177636;, - 0.254500;0.223545;, - 0.255000;0.166775;, - 0.256975;0.526919;, - 0.257000;0.466000;, - 0.354975;0.527475;, - 0.257000;0.446000;, - 0.335222;0.527475;, - 0.257198;0.526919;, - 0.354969;0.527475;, - 0.257000;0.466000;, - 0.062673;0.171389;, - 0.123628;0.174197;, - 0.123573;0.174197;, - 0.062673;0.153611;, - 0.040549;0.153611;, - 0.099649;0.174197;, - 0.040549;0.171389;, - 0.099705;0.174197;, - 0.270545;0.320182;, - 0.280385;0.318542;, - 0.241037;0.320182;, - 0.976858;0.021774;, - 0.976858;0.021754;, - 0.270545;0.362200;, - 0.280385;0.360561;, - 0.241037;0.362200;, - 0.976858;0.021761;, - 0.270545;0.379708;, - 0.296785;0.384628;, - 0.297409;0.384957;, - 0.298860;0.427511;, - 0.298860;0.398356;, - 0.976859;0.021765;, - 0.241037;0.379708;, - 0.291704;0.354200;, - 0.291626;0.353945;, - 0.976859;0.021761;, - 0.291704;0.318563;, - 0.291626;0.318654;, - 0.976859;0.021754;, - 0.976859;0.021774;, - 0.768148;0.107475;, - 0.255000;0.173798;, - 0.254500;0.223468;, - 0.759941;0.107475;, - 0.254500;0.223496;, - 0.255000;0.166799;, - 0.745439;0.090556;, - 0.736667;0.086111;, - 0.760385;0.107030;, - 0.760111;0.107155;, - 0.745556;0.081667;, - 0.760428;0.107343;, - 0.768028;0.107043;, - 0.736667;0.095000;, - 0.768593;0.107030;, - 0.759889;0.107155;, - 0.745556;0.099444;, - 0.767806;0.107043;, - 0.760206;0.107343;, - 0.754444;0.095000;, - 0.768123;0.107230;, - 0.768292;0.107041;, - 0.754444;0.086111;, - 0.759885;0.107141;, - 0.768345;0.107230;, - 0.317469;0.526919;, - 0.354975;0.527364;, - 0.317000;0.465985;, - 0.335222;0.527364;, - 0.317000;0.446000;, - 0.317691;0.526919;, - 0.317000;0.465955;, - 0.354969;0.527364;, - 0.356910;0.398384;, - 0.976862;0.021761;, - 0.356911;0.427576;, - 0.361011;0.366363;, - 0.361042;0.366416;, - 0.345901;0.427576;, - 0.345718;0.427511;, - 0.349473;0.384957;, - 0.345718;0.398356;, - 0.976861;0.021765;, - 0.345901;0.398384;, - 0.361490;0.318563;, - 0.355319;0.354200;, - 0.355564;0.354180;, - 0.976862;0.021754;, - 0.976862;0.021774;, - 0.305321;0.355683;, - 0.301464;0.369666;, - 0.301466;0.370190;, - 0.342793;0.369666;, - 0.305321;0.318563;, - 0.428474;0.427576;, - 0.435854;0.366363;, - 0.436245;0.366416;, - 0.428474;0.398384;, - 0.976865;0.021761;, - 0.446824;0.427576;, - 0.470350;0.348420;, - 0.455528;0.351583;, - 0.455865;0.350599;, - 0.446824;0.398384;, - 0.487806;0.348420;, - 0.976866;0.021759;, - 0.421864;0.306189;, - 0.427871;0.354200;, - 0.427885;0.354180;, - 0.487806;0.305599;, - 0.976866;0.021774;, - 0.976866;0.021751;, - 0.470350;0.305599;, - 0.455865;0.307346;, - 0.444892;0.306189;, - 0.444966;0.306476;, - 0.444892;0.341826;, - 0.444966;0.341115;, - 0.976865;0.021751;, - 0.976865;0.021774;, - 0.977044;0.020660;, - 0.069496;0.120769;, - 0.977118;0.021875;, - 0.012437;0.120825;, - 0.047090;0.120769;, - 0.977044;0.022066;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.977141;0.022000;, - 0.016518;0.087040;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.391459;0.048318;, - 0.556537;0.147086;, - 0.556327;0.185371;, - 0.802622;0.177608;, - 0.523953;0.193199;, - 0.802641;0.177464;, - 0.556327;0.193199;, - 0.808426;0.177464;, - 0.523953;0.185371;, - 0.525422;0.149144;, - 0.977044;0.022066;, - 0.047090;0.120769;, - 0.012437;0.120825;, - 0.977044;0.020660;, - 0.977118;0.021875;, - 0.069496;0.120769;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978312;0.020660;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.036926;0.087040;, - 0.513845;0.107538;, - 0.624989;0.147086;, - 0.627550;0.185371;, - 0.981273;0.017225;, - 0.627550;0.193199;, - 0.981189;0.017225;, - 0.959048;0.472795;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.978312;0.020660;, - 0.012320;0.208577;, - 0.932877;0.040799;, - 0.149345;0.222939;, - 0.012372;0.195110;, - 0.134000;0.222939;, - 0.012391;0.222939;, - 0.036002;0.195269;, - 0.036080;0.222939;, - 0.944104;0.040799;, - 0.035950;0.208736;, - 0.976860;0.021777;, - 0.944104;0.046851;, - 0.976876;0.021732;, - 0.976860;0.021758;, - 0.036080;0.239370;, - 0.976869;0.021732;, - 0.134000;0.239370;, - 0.012391;0.239370;, - 0.149345;0.239370;, - 0.932877;0.046851;, - 0.932877;0.043825;, - 0.149345;0.231155;, - 0.944104;0.043825;, - 0.976876;0.021723;, - 0.976861;0.021745;, - 0.976869;0.021723;, - 0.036080;0.231155;, - 0.976861;0.021725;, - 0.134000;0.231155;, - 0.012391;0.231155;, - 0.241037;0.260656;, - 0.283754;0.199532;, - 0.270545;0.260656;, - 0.281983;0.258879;, - 0.282025;0.259016;, - 0.283754;0.230704;, - 0.298999;0.199532;, - 0.298999;0.230704;, - 0.298179;0.247924;, - 0.297409;0.247754;, - 0.291704;0.268942;, - 0.291626;0.270159;, - 0.361884;0.230704;, - 0.361064;0.246283;, - 0.361884;0.199532;, - 0.361490;0.259662;, - 0.361506;0.259643;, - 0.305321;0.259662;, - 0.305997;0.259643;, - 0.420957;0.230704;, - 0.470350;0.248506;, - 0.420819;0.247754;, - 0.420137;0.246283;, - 0.487806;0.248506;, - 0.420957;0.199532;, - 0.487806;0.280621;, - 0.455865;0.282116;, - 0.470350;0.280621;, - 0.455528;0.281128;, - 0.414254;0.259662;, - 0.413650;0.259643;, - 0.444892;0.287502;, - 0.444966;0.288312;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012437;0.059286;, - 0.012381;0.052598;, - 0.064652;0.058120;, - 0.040952;0.052598;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.055508;0.799522;, - 0.055172;0.801413;, - 0.041032;0.799147;, - 0.041032;0.774293;, - 0.061024;0.774863;, - 0.046266;0.754438;, - 0.049668;0.774293;, - 0.046266;0.763075;, - 0.049668;0.799147;, - 0.055172;0.805506;, - 0.978132;0.020834;, - 0.143339;0.893176;, - 0.978132;0.020876;, - 0.143339;0.895832;, - 0.978023;0.021000;, - 0.123466;0.903802;, - 0.978023;0.021042;, - 0.123466;0.906459;, - 0.144531;0.841937;, - 0.144531;0.834740;, - 0.143339;0.872366;, - 0.120558;0.834740;, - 0.119390;0.874137;, - 0.120558;0.841937;, - 0.120558;0.834419;, - 0.119390;0.929483;, - 0.120558;0.842644;, - 0.144531;0.842644;, - 0.144531;0.834419;, - 0.143339;0.929483;, - 0.094847;0.733336;, - 0.095624;0.727406;, - 0.052957;0.727665;, - 0.062312;0.727406;, - 0.062312;0.727406;, - 0.061534;0.733336;, - 0.053159;0.667221;, - 0.095624;0.706678;, - 0.053159;0.700534;, - 0.062312;0.706678;, - 0.062312;0.706678;, - 0.052957;0.706937;, - 0.094103;0.723951;, - 0.066877;0.723951;, - 0.066877;0.710133;, - 0.094103;0.710133;, - 0.097992;0.977510;, - 0.098017;0.986461;, - 0.091536;0.944197;, - 0.978578;0.023576;, - 0.091536;0.944197;, - 0.979911;0.020133;, - 0.086421;0.951453;, - 0.079639;0.951881;, - 0.980081;0.020395;, - 0.090437;0.989766;, - 0.090749;0.973784;, - 0.079639;0.974521;, - 0.694760;0.788548;, - 0.694760;0.771873;, - 0.683241;0.789919;, - 0.683241;0.739164;, - 0.682954;0.683341;, - 0.713399;0.788548;, - 0.713399;0.771873;, - 0.713112;0.684300;, - 0.713399;0.718950;, - 0.713399;0.718950;, - 0.713112;0.684300;, - 0.713399;0.743062;, - 0.730511;0.978649;, - 0.976985;0.021629;, - 0.683241;0.813119;, - 0.682954;0.707912;, - 0.694760;0.813119;, - 0.713399;0.813119;, - 0.713112;0.707912;, - 0.977169;0.021629;, - 0.694760;0.788548;, - 0.694760;0.771873;, - 0.683241;0.739164;, - 0.682954;0.683341;, - 0.683241;0.789919;, - 0.713399;0.788548;, - 0.713399;0.771873;, - 0.713112;0.684300;, - 0.713399;0.718950;, - 0.713399;0.718950;, - 0.713112;0.684300;, - 0.730511;0.978649;, - 0.976985;0.021629;, - 0.730511;0.909761;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.727468;0.075033;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.727468;0.102968;, - 0.794045;0.784020;, - 0.976861;0.021721;, - 0.943549;0.783971;, - 0.730511;0.849484;, - 0.977001;0.021494;, - 0.340296;0.057351;, - 0.355333;0.081438;, - 0.329665;0.108348;, - 0.355333;0.105852;, - 0.355667;0.056747;, - 0.340296;0.084427;, - 0.355333;0.107673;, - 0.355333;0.082673;, - 0.672880;0.089111;, - 0.673214;0.074937;, - 0.672880;0.074825;, - 0.672880;0.103397;, - 0.672880;0.075937;, - 0.846557;0.784020;, - 0.943305;0.784093;, - 0.976880;0.021721;, - 0.977194;0.021494;, - 0.373111;0.081438;, - 0.373111;0.105852;, - 0.373444;0.056747;, - 0.373111;0.082673;, - 0.373111;0.107673;, - 0.689675;0.074825;, - 0.727468;0.075033;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.727468;0.102968;, - 0.689675;0.103397;, - 0.730511;0.849484;, - 0.977001;0.021494;, - 0.355333;0.081438;, - 0.340296;0.057351;, - 0.329665;0.108348;, - 0.355333;0.105852;, - 0.355667;0.056747;, - 0.340296;0.084427;, - 0.355333;0.082673;, - 0.355333;0.107673;, - 0.690705;0.630605;, - 0.976859;0.021750;, - 0.329665;0.033429;, - 0.355889;0.056747;, - 0.355333;0.058259;, - 0.976865;0.021750;, - 0.373111;0.058259;, - 0.373667;0.056747;, - 0.690705;0.630605;, - 0.976859;0.021750;, - 0.329665;0.033429;, - 0.355333;0.058259;, - 0.355889;0.056747;, - 0.977141;0.020800;, - 0.100000;0.093505;, - 0.100000;0.059231;, - 0.012381;0.015444;, - 0.100556;0.092394;, - 0.977981;0.020800;, - 0.100556;0.058120;, - 0.040952;0.015444;, - 0.056960;0.536178;, - 0.976864;0.021741;, - 0.048288;0.536195;, - 0.976877;0.021741;, - 0.061440;0.536165;, - 0.061440;0.536148;, - 0.976866;0.021741;, - 0.976866;0.021744;, - 0.061440;0.539509;, - 0.061440;0.539497;, - 0.056960;0.539482;, - 0.976877;0.021744;, - 0.976864;0.021744;, - 0.048288;0.539582;, - 0.056960;0.536187;, - 0.976864;0.021741;, - 0.007516;0.536195;, - 0.976863;0.021741;, - 0.061440;0.536148;, - 0.976866;0.021741;, - 0.061440;0.536175;, - 0.061440;0.539509;, - 0.061440;0.539531;, - 0.976866;0.021744;, - 0.056960;0.539537;, - 0.976864;0.021744;, - 0.976863;0.021744;, - 0.007516;0.539582;, - 0.976915;0.021593;, - 0.194067;0.361263;, - 0.976930;0.021593;, - 0.190892;0.353778;, - 0.198440;0.379835;, - 0.976933;0.021711;, - 0.219463;0.361263;, - 0.976852;0.021711;, - 0.219397;0.361263;, - 0.976852;0.021665;, - 0.231033;0.413585;, - 0.219397;0.353778;, - 0.219463;0.353778;, - 0.976933;0.021665;, - 0.231033;0.387217;, - 0.206765;0.353778;, - 0.214525;0.379835;, - 0.206765;0.361263;, - 0.231249;0.461585;, - 0.976852;0.021774;, - 0.219397;0.371556;, - 0.231249;0.435217;, - 0.219463;0.371556;, - 0.976933;0.021774;, - 0.214741;0.427835;, - 0.206765;0.371556;, - 0.198337;0.427835;, - 0.199146;0.371556;, - 0.976930;0.021593;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.186550;0.382365;, - 0.976887;0.021710;, - 0.976941;0.021651;, - 0.178570;0.382418;, - 0.176404;0.382494;, - 0.976887;0.021756;, - 0.186138;0.413602;, - 0.176177;0.404762;, - 0.178572;0.404842;, - 0.178574;0.404842;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.186550;0.382334;, - 0.976853;0.021731;, - 0.976986;0.021718;, - 0.178570;0.382379;, - 0.176404;0.382508;, - 0.976853;0.021747;, - 0.976872;0.021776;, - 0.176176;0.404762;, - 0.178570;0.404934;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.186550;0.382342;, - 0.976919;0.021730;, - 0.178570;0.382383;, - 0.176404;0.382505;, - 0.976919;0.021690;, - 0.976887;0.021767;, - 0.176178;0.404770;, - 0.178570;0.404955;, - 0.083984;0.539458;, - 0.976874;0.021744;, - 0.976856;0.021700;, - 0.083984;0.536070;, - 0.976874;0.021740;, - 0.976856;0.021681;, - 0.083735;0.539458;, - 0.976874;0.021744;, - 0.083735;0.536070;, - 0.976874;0.021740;, - 0.149444;0.168841;, - 0.032025;0.171556;, - 0.090307;0.140477;, - 0.167222;0.168841;, - 0.032025;0.153778;, - 0.090251;0.140477;, - 0.167222;0.154555;, - 0.086359;0.154444;, - 0.149444;0.154555;, - 0.086414;0.154444;, - 0.149444;0.140270;, - 0.090307;0.168412;, - 0.031858;0.171389;, - 0.031858;0.153611;, - 0.090251;0.168412;, - 0.167222;0.140270;, - 0.176074;0.525865;, - 0.176073;0.525855;, - 0.179991;0.521785;, - 0.223123;0.523861;, - 0.179992;0.521776;, - 0.176111;0.568592;, - 0.176089;0.568671;, - 0.176111;0.539458;, - 0.176089;0.539508;, - 0.976907;0.021744;, - 0.163320;0.539458;, - 0.976902;0.021744;, - 0.179954;0.539508;, - 0.976908;0.021744;, - 0.223123;0.540527;, - 0.976892;0.021758;, - 0.976907;0.021740;, - 0.176111;0.536070;, - 0.176089;0.536066;, - 0.976902;0.021740;, - 0.163320;0.536070;, - 0.179954;0.536066;, - 0.976908;0.021740;, - 0.976892;0.021754;, - 0.223123;0.537322;, - 0.157168;0.546233;, - 0.976900;0.021752;, - 0.131424;0.546233;, - 0.976891;0.021752;, - 0.976977;0.021737;, - 0.976900;0.021748;, - 0.157168;0.542845;, - 0.976891;0.021748;, - 0.131424;0.542845;, - 0.976977;0.021718;, - 0.126567;0.539458;, - 0.976965;0.021700;, - 0.976965;0.021681;, - 0.126567;0.536070;, - 0.179985;0.521776;, - 0.189418;0.523861;, - 0.179993;0.521762;, - 0.176064;0.525865;, - 0.176071;0.525880;, - 0.176097;0.568606;, - 0.176086;0.568648;, - 0.163071;0.539458;, - 0.976902;0.021744;, - 0.176086;0.539458;, - 0.176041;0.539524;, - 0.976907;0.021744;, - 0.976908;0.021744;, - 0.189418;0.540527;, - 0.976876;0.021758;, - 0.180012;0.539524;, - 0.976902;0.021740;, - 0.163071;0.536070;, - 0.176086;0.536070;, - 0.176041;0.536143;, - 0.976907;0.021740;, - 0.180012;0.536143;, - 0.976876;0.021754;, - 0.189418;0.537322;, - 0.976908;0.021741;, - 0.156919;0.546233;, - 0.976900;0.021752;, - 0.976891;0.021752;, - 0.131175;0.546233;, - 0.976914;0.021737;, - 0.976891;0.021748;, - 0.131175;0.542845;, - 0.976914;0.021718;, - 0.156919;0.542845;, - 0.976900;0.021748;, - 0.126318;0.539458;, - 0.976901;0.021700;, - 0.976889;0.021744;, - 0.976889;0.021740;, - 0.126318;0.536070;, - 0.976901;0.021681;, - 0.187000;0.166801;, - 0.187400;0.177905;, - 0.187400;0.177892;, - 0.187000;0.173800;, - 0.255000;0.173817;, - 0.260518;0.224141;, - 0.254700;0.177947;, - 0.255000;0.166807;, - 0.254700;0.177947;, - 0.267926;0.224141;, - 0.250926;0.517450;, - 0.354975;0.518005;, - 0.256975;0.476414;, - 0.354975;0.476970;, - 0.257000;0.466000;, - 0.354975;0.486439;, - 0.250926;0.485884;, - 0.335222;0.486439;, - 0.335222;0.518005;, - 0.335222;0.476970;, - 0.257000;0.445997;, - 0.251148;0.517450;, - 0.354969;0.518005;, - 0.251148;0.485884;, - 0.354969;0.486439;, - 0.257198;0.476414;, - 0.354969;0.476970;, - 0.257000;0.466000;, - 0.149444;0.168619;, - 0.133026;0.140477;, - 0.071531;0.171556;, - 0.149444;0.154333;, - 0.136919;0.154444;, - 0.167222;0.154333;, - 0.136864;0.154444;, - 0.071531;0.153778;, - 0.132971;0.140477;, - 0.167222;0.168619;, - 0.149444;0.140048;, - 0.071364;0.171389;, - 0.133026;0.168412;, - 0.167222;0.140048;, - 0.071364;0.153611;, - 0.132971;0.168412;, - 0.062840;0.153778;, - 0.123573;0.134691;, - 0.062840;0.171556;, - 0.123628;0.134691;, - 0.040716;0.171556;, - 0.099705;0.134691;, - 0.040716;0.153778;, - 0.099649;0.134691;, - 0.255000;0.173799;, - 0.767548;0.056470;, - 0.254700;0.177950;, - 0.255000;0.166801;, - 0.254700;0.177957;, - 0.760341;0.056570;, - 0.745278;0.081667;, - 0.760172;0.056313;, - 0.767572;0.056213;, - 0.736389;0.086111;, - 0.759855;0.056125;, - 0.760185;0.056325;, - 0.736389;0.095000;, - 0.767593;0.056025;, - 0.760033;0.056525;, - 0.745278;0.099444;, - 0.767750;0.056213;, - 0.759950;0.056313;, - 0.208814;0.320182;, - 0.976858;0.021766;, - 0.976859;0.021766;, - 0.241037;0.320182;, - 0.976858;0.021754;, - 0.976858;0.021774;, - 0.241037;0.362200;, - 0.976858;0.021761;, - 0.241037;0.379708;, - 0.298860;0.398356;, - 0.976859;0.021765;, - 0.976859;0.021761;, - 0.976859;0.021754;, - 0.976859;0.021774;, - 0.317469;0.476414;, - 0.317000;0.465965;, - 0.354975;0.476859;, - 0.323519;0.517449;, - 0.354975;0.517894;, - 0.323519;0.485884;, - 0.354975;0.486328;, - 0.317000;0.446000;, - 0.335222;0.476859;, - 0.335222;0.486328;, - 0.335222;0.517894;, - 0.317691;0.476414;, - 0.317000;0.465935;, - 0.354969;0.476859;, - 0.323741;0.485884;, - 0.354969;0.486328;, - 0.354969;0.517894;, - 0.323741;0.517449;, - 0.754167;0.095000;, - 0.767667;0.056401;, - 0.767492;0.056136;, - 0.754167;0.086111;, - 0.759685;0.056136;, - 0.767889;0.056401;, - 0.601948;0.046861;, - 0.976943;0.021610;, - 0.602138;0.072716;, - 0.976862;0.021610;, - 0.601995;0.072716;, - 0.601948;0.054907;, - 0.976943;0.021785;, - 0.601952;0.047634;, - 0.602138;0.091960;, - 0.601952;0.054583;, - 0.601995;0.091960;, - 0.976862;0.021785;, - 0.976862;0.021766;, - 0.356910;0.398384;, - 0.976862;0.021761;, - 0.345901;0.398384;, - 0.976861;0.021765;, - 0.345718;0.398356;, - 0.976862;0.021774;, - 0.976862;0.021754;, - 0.614541;0.046861;, - 0.614364;0.059108;, - 0.632351;0.046861;, - 0.631655;0.059108;, - 0.632351;0.054907;, - 0.631513;0.059108;, - 0.614541;0.054907;, - 0.614222;0.059108;, - 0.614545;0.047634;, - 0.614364;0.105567;, - 0.614545;0.054583;, - 0.614222;0.105567;, - 0.632355;0.054583;, - 0.631513;0.105567;, - 0.631655;0.105567;, - 0.632355;0.047634;, - 0.642504;0.054907;, - 0.641371;0.059108;, - 0.642504;0.046861;, - 0.641513;0.059108;, - 0.623009;0.082338;, - 0.622867;0.082338;, - 0.509253;0.305599;, - 0.976866;0.021766;, - 0.976865;0.021766;, - 0.428474;0.398384;, - 0.976865;0.021761;, - 0.446824;0.398384;, - 0.487806;0.348420;, - 0.976866;0.021759;, - 0.487806;0.305599;, - 0.976866;0.021751;, - 0.976866;0.021774;, - 0.976865;0.021751;, - 0.976865;0.021774;, - 0.977141;0.020800;, - 0.100000;0.093505;, - 0.976866;0.021771;, - 0.664403;0.047634;, - 0.662769;0.101237;, - 0.976858;0.021771;, - 0.662627;0.101237;, - 0.664403;0.054583;, - 0.976858;0.021745;, - 0.664398;0.054907;, - 0.662627;0.072716;, - 0.664398;0.046861;, - 0.662769;0.072716;, - 0.976866;0.021745;, - 0.643881;0.091960;, - 0.644948;0.047634;, - 0.976866;0.021763;, - 0.644948;0.047634;, - 0.643881;0.072716;, - 0.643739;0.072716;, - 0.643739;0.091960;, - 0.644948;0.054583;, - 0.976858;0.021763;, - 0.644948;0.054583;, - 0.977981;0.020800;, - 0.100556;0.092394;, - 0.208814;0.260656;, - 0.283754;0.161235;, - 0.298999;0.161235;, - 0.241037;0.260656;, - 0.283754;0.199532;, - 0.298999;0.199532;, - 0.361884;0.161235;, - 0.361884;0.199532;, - 0.420957;0.161235;, - 0.509253;0.248506;, - 0.509253;0.280621;, - 0.420957;0.199532;, - 0.487806;0.248506;, - 0.487806;0.280621;, - 0.100000;0.059231;, - 0.012381;0.015444;, - 0.100556;0.058120;, - 0.040952;0.015444;, - 0.525933;0.055547;, - 0.977200;0.020086;, - 0.525933;0.088970;, - 0.977200;0.021691;, - 0.112049;0.739555;, - 0.977650;0.021116;, - 0.107912;0.774863;, - 0.098954;0.754438;, - 0.977650;0.021611;, - 0.107912;0.799522;, - 0.108081;0.801413;, - 0.114706;0.723546;, - 0.977650;0.020891;, - 0.113989;0.678436;, - 0.977710;0.020825;, - 0.113989;0.682655;, - 0.977710;0.021611;, - 0.098954;0.763075;, - 0.108081;0.805506;, - 0.977408;0.020876;, - 0.977710;0.021957;, - 0.978355;0.020834;, - 0.183867;0.893176;, - 0.978355;0.020876;, - 0.183867;0.895832;, - 0.185102;0.841937;, - 0.185102;0.834740;, - 0.183867;0.872366;, - 0.185102;0.842644;, - 0.185102;0.834419;, - 0.183867;0.929483;, - 0.094847;0.743240;, - 0.095236;0.694759;, - 0.061534;0.743240;, - 0.011573;0.727665;, - 0.061923;0.694759;, - 0.095236;0.674031;, - 0.010595;0.667221;, - 0.061923;0.674031;, - 0.010595;0.700534;, - 0.011573;0.706937;, - 0.732037;0.771873;, - 0.752646;0.815263;, - 0.732037;0.792106;, - 0.745384;0.689022;, - 0.745670;0.746966;, - 0.756254;0.782280;, - 0.783144;0.959274;, - 0.796474;0.958596;, - 0.977029;0.021491;, - 0.732037;0.813119;, - 0.773659;0.815263;, - 0.745384;0.707912;, - 0.774089;0.782280;, - 0.821046;0.958596;, - 0.977169;0.021491;, - 0.732037;0.792106;, - 0.732037;0.771873;, - 0.752646;0.815263;, - 0.745670;0.746966;, - 0.756254;0.782280;, - 0.745384;0.689022;, - 0.796474;0.958596;, - 0.977029;0.021491;, - 0.783144;0.959274;, - 0.977179;0.021888;, - 0.875221;0.929347;, - 0.875226;0.929324;, - 0.978676;0.928821;, - 0.850649;0.929347;, - 0.850654;0.929324;, - 0.768789;0.901150;, - 0.798397;0.900318;, - 0.821046;0.900318;, - 0.977179;0.021888;, - 0.875226;0.929324;, - 0.875221;0.929347;, - 0.768789;0.901150;, - 0.798397;0.900318;, - 0.978676;0.928821;, - 0.850649;0.929347;, - 0.850654;0.929324;, - 0.977179;0.021556;, - 0.875226;0.866894;, - 0.888053;0.829159;, - 0.888053;0.849635;, - 0.978676;0.865984;, - 0.850654;0.866894;, - 0.768789;0.849484;, - 0.977001;0.021331;, - 0.798397;0.848516;, - 0.977194;0.021331;, - 0.821046;0.848516;, - 0.977179;0.021556;, - 0.888053;0.829159;, - 0.875226;0.866894;, - 0.768789;0.849484;, - 0.977001;0.021331;, - 0.798397;0.848516;, - 0.888053;0.849635;, - 0.978676;0.865984;, - 0.850654;0.866894;, - 0.711138;0.630605;, - 0.976859;0.021745;, - 0.731947;0.631618;, - 0.785081;0.704734;, - 0.968087;0.704061;, - 0.976865;0.021745;, - 0.758409;0.631618;, - 0.852822;0.704734;, - 0.967843;0.704183;, - 0.711138;0.630605;, - 0.976859;0.021745;, - 0.731947;0.631618;, - 0.464119;0.857811;, - 0.977922;0.019611;, - 0.481521;0.845698;, - 0.510688;0.845698;, - 0.486403;0.033711;, - 0.977782;0.020245;, - 0.979961;0.019611;, - 0.486403;0.107756;, - 0.977782;0.021604;, - 0.479421;0.992755;, - 0.447425;0.964429;, - 0.447130;0.971190;, - 0.447425;0.932359;, - 0.978215;0.022379;, - 0.978043;0.019009;, - 0.097140;0.444659;, - 0.972515;0.112669;, - 0.097196;0.430691;, - 0.096024;0.418061;, - 0.119679;0.444805;, - 0.151500;0.418061;, - 0.982745;0.112669;, - 0.119735;0.430837;, - 0.117609;0.418061;, - 0.135500;0.418061;, - 0.724760;0.577911;, - 0.731947;0.578171;, - 0.715679;0.559671;, - 0.731947;0.559671;, - 0.714579;0.526087;, - 0.758409;0.578171;, - 0.758409;0.559671;, - 0.714579;0.552549;, - 0.724760;0.577911;, - 0.731947;0.578171;, - 0.715679;0.559671;, - 0.731947;0.559671;, - 0.714579;0.526087;, - 0.977499;0.019428;, - 0.662365;0.498579;, - 0.676086;0.498336;, - 0.464119;0.833563;, - 0.481521;0.808872;, - 0.465483;0.825413;, - 0.977782;0.019429;, - 0.465483;0.806829;, - 0.510688;0.808872;, - 0.977759;0.019088;, - 0.479421;0.872712;, - 0.447425;0.883464;, - 0.978215;0.018687;, - 0.480373;0.096439;, - 0.835909;0.220903;, - 0.978103;0.021676;, - 0.835909;0.217521;, - 0.793123;0.111296;, - 0.818815;0.126731;, - 0.818815;0.114854;, - 0.818506;0.111551;, - 0.806177;0.111554;, - 0.818477;0.111554;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.977141;0.022000;, - 0.016518;0.087040;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012437;0.059286;, - 0.012381;0.052598;, - 0.670927;0.382443;, - 0.658868;0.382686;, - 0.651163;0.438217;, - 0.676086;0.437973;, - 0.856740;0.220903;, - 0.978563;0.021676;, - 0.856740;0.217521;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.064652;0.058120;, - 0.040952;0.052598;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.036926;0.087040;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.083840;0.509236;, - 0.083840;0.509233;, - 0.083855;0.509239;, - 0.080510;0.504641;, - 0.082948;0.497871;, - 0.080480;0.504795;, - 0.048288;0.505028;, - 0.080480;0.504795;, - 0.082948;0.464938;, - 0.007516;0.505028;, - 0.080480;0.504793;, - 0.083840;0.509232;, - 0.083840;0.509222;, - 0.083840;0.509230;, - 0.187000;0.166807;, - 0.267815;0.224141;, - 0.187400;0.177905;, - 0.260407;0.224141;, - 0.187400;0.177905;, - 0.187000;0.173806;, - 0.972515;0.072573;, - 0.972515;0.081652;, - 0.096024;0.309203;, - 0.096024;0.333850;, - 0.982745;0.072573;, - 0.151500;0.309203;, - 0.982745;0.081652;, - 0.151500;0.333850;, - 0.117609;0.309203;, - 0.135500;0.309203;, - 0.117609;0.333850;, - 0.135500;0.333850;, - 0.166720;0.505346;, - 0.166720;0.505303;, - 0.223123;0.507837;, - 0.164252;0.497871;, - 0.163360;0.509056;, - 0.156752;0.504651;, - 0.155496;0.497871;, - 0.126960;0.504654;, - 0.125945;0.497871;, - 0.126505;0.509127;, - 0.126400;0.509152;, - 0.156976;0.508959;, - 0.156976;0.509006;, - 0.166720;0.505346;, - 0.189418;0.507837;, - 0.164252;0.464938;, - 0.163360;0.509056;, - 0.156752;0.504688;, - 0.155496;0.464938;, - 0.156976;0.508964;, - 0.156976;0.508959;, - 0.126400;0.509215;, - 0.126400;0.509152;, - 0.126960;0.504789;, - 0.125945;0.464938;, - 0.745394;0.090556;, - 0.270545;0.320182;, - 0.280385;0.318542;, - 0.270545;0.362200;, - 0.280385;0.360561;, - 0.270545;0.379708;, - 0.298860;0.427511;, - 0.297409;0.384957;, - 0.296785;0.384628;, - 0.291704;0.354200;, - 0.291626;0.353945;, - 0.291704;0.318563;, - 0.291626;0.318654;, - 0.356911;0.427576;, - 0.361011;0.366363;, - 0.361042;0.366416;, - 0.345901;0.427576;, - 0.345718;0.427511;, - 0.349473;0.384957;, - 0.361490;0.318563;, - 0.355319;0.354200;, - 0.355564;0.354180;, - 0.301464;0.369666;, - 0.301466;0.370190;, - 0.305321;0.355683;, - 0.342793;0.369666;, - 0.305321;0.318563;, - 0.428474;0.427576;, - 0.436245;0.366416;, - 0.435854;0.366363;, - 0.455528;0.351583;, - 0.455865;0.350599;, - 0.446824;0.427576;, - 0.470350;0.348420;, - 0.421864;0.306189;, - 0.427871;0.354200;, - 0.427885;0.354180;, - 0.470350;0.305599;, - 0.455865;0.307346;, - 0.444892;0.306189;, - 0.444966;0.306476;, - 0.444892;0.341826;, - 0.444966;0.341115;, - 0.835909;0.151790;, - 0.978103;0.020028;, - 0.835909;0.147563;, - 0.806054;0.037284;, - 0.818354;0.037284;, - 0.816593;0.026083;, - 0.818506;0.037251;, - 0.793123;0.037628;, - 0.816593;0.013880;, - 0.977044;0.022066;, - 0.047090;0.120769;, - 0.012437;0.120825;, - 0.977044;0.020660;, - 0.977118;0.021875;, - 0.069496;0.120769;, - 0.977141;0.022000;, - 0.069496;0.093505;, - 0.977118;0.020469;, - 0.016518;0.087040;, - 0.047090;0.093505;, - 0.012437;0.093561;, - 0.977044;0.020660;, - 0.069496;0.120769;, - 0.977118;0.021875;, - 0.012437;0.120825;, - 0.047090;0.120769;, - 0.977044;0.022066;, - 0.513845;0.044407;, - 0.856740;0.151790;, - 0.856740;0.147563;, - 0.978563;0.020028;, - 0.859301;0.400070;, - 0.859000;0.396004;, - 0.859000;0.396008;, - 0.859301;0.410331;, - 0.975690;0.024113;, - 0.873399;0.410331;, - 0.976407;0.024113;, - 0.873399;0.400070;, - 0.873466;0.396199;, - 0.863305;0.291435;, - 0.859200;0.327200;, - 0.863305;0.280722;, - 0.863800;0.390604;, - 0.863600;0.330400;, - 0.975690;0.020550;, - 0.978600;0.022376;, - 0.863800;0.334800;, - 0.863800;0.334805;, - 0.858768;0.334964;, - 0.070051;0.092394;, - 0.977981;0.022000;, - 0.978386;0.020469;, - 0.047645;0.092394;, - 0.041008;0.093561;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.978312;0.020660;, - 0.036926;0.087040;, - 0.978312;0.022066;, - 0.041008;0.120825;, - 0.047645;0.119658;, - 0.978312;0.020660;, - 0.978386;0.021875;, - 0.070051;0.119658;, - 0.976888;0.021758;, - 0.096024;0.239370;, - 0.976871;0.021721;, - 0.972515;0.046851;, - 0.976878;0.021721;, - 0.976888;0.021778;, - 0.095747;0.209137;, - 0.972515;0.040799;, - 0.095799;0.195670;, - 0.096024;0.222939;, - 0.117331;0.195815;, - 0.135500;0.222939;, - 0.117609;0.222939;, - 0.982745;0.040799;, - 0.151500;0.222939;, - 0.117279;0.209282;, - 0.982745;0.046851;, - 0.151500;0.239370;, - 0.117609;0.239370;, - 0.135500;0.239370;, - 0.972515;0.043825;, - 0.976889;0.021745;, - 0.976878;0.021710;, - 0.982745;0.043825;, - 0.151500;0.231155;, - 0.135500;0.231155;, - 0.117609;0.231155;, - 0.976871;0.021710;, - 0.096024;0.231155;, - 0.976889;0.021726;, - 0.283754;0.230704;, - 0.282025;0.259016;, - 0.270545;0.260656;, - 0.281983;0.258879;, - 0.298999;0.230704;, - 0.298179;0.247924;, - 0.297409;0.247754;, - 0.291704;0.268942;, - 0.291626;0.270159;, - 0.361064;0.246283;, - 0.361884;0.230704;, - 0.361490;0.259662;, - 0.361506;0.259643;, - 0.305321;0.259662;, - 0.305997;0.259643;, - 0.420957;0.230704;, - 0.470350;0.248506;, - 0.420137;0.246283;, - 0.420819;0.247754;, - 0.470350;0.280621;, - 0.455865;0.282116;, - 0.455528;0.281128;, - 0.414254;0.259662;, - 0.413650;0.259643;, - 0.444892;0.287502;, - 0.444966;0.288312;, - 0.016518;0.060366;, - 0.016513;0.060375;, - 0.064097;0.059231;, - 0.012431;0.059298;, - 0.012381;0.052598;, - 0.012437;0.059286;, - 0.146322;0.732423;, - 0.146322;0.766866;, - 0.146016;0.768382;, - 0.146863;0.801413;, - 0.146322;0.714883;, - 0.146626;0.678436;, - 0.132532;0.799522;, - 0.132939;0.801413;, - 0.146626;0.682655;, - 0.146016;0.769142;, - 0.978448;0.020876;, - 0.146863;0.805506;, - 0.978075;0.020876;, - 0.132939;0.805506;, - 0.978617;0.020834;, - 0.231518;0.893176;, - 0.978617;0.020876;, - 0.231518;0.895832;, - 0.232804;0.841937;, - 0.232804;0.834740;, - 0.231518;0.872366;, - 0.232804;0.842644;, - 0.232804;0.834419;, - 0.231518;0.929483;, - 0.183964;0.977510;, - 0.184482;0.986461;, - 0.183964;0.944197;, - 0.978578;0.018557;, - 0.147982;0.824798;, - 0.216679;0.814796;, - 0.064652;0.058120;, - 0.041008;0.059286;, - 0.041002;0.059298;, - 0.040952;0.052598;, - 0.036926;0.060366;, - 0.036921;0.060375;, - 0.463765;0.932537;, - 0.463765;0.932537;, - 0.479421;0.947429;, - 0.479421;0.947429;, - 0.479421;0.885961;, - 0.463765;0.887007;, - 0.830295;0.111366;, - 0.830238;0.111442;, - 0.841218;0.111366;, - 0.841241;0.111373;, - 0.841314;0.111442;, - 0.824024;0.108408;, - 0.824065;0.108391;, - 0.826483;0.114661;, - 0.826420;0.114626;, - 0.826483;0.126731;, - 0.843742;0.126731;, - 0.914073;0.111583;, - 0.896810;0.111583;, - 0.843742;0.114661;, - 0.843674;0.114607;, - 0.484986;0.048318;, - 0.860172;0.035810;, - 0.830283;0.035767;, - 0.830283;0.035763;, - 0.874515;0.073245;, - 0.874513;0.073311;, - 0.874515;0.043185;, - 0.874513;0.043157;, - 0.824065;0.039785;, - 0.824024;0.039738;, - 0.914073;0.072339;, - 0.896810;0.072339;, - 0.880635;0.073336;, - 0.914073;0.039635;, - 0.878714;0.013880;, - 0.878714;0.025890;, - 0.880635;0.041337;, - 0.880627;0.041351;, - 0.896810;0.039635;, - 0.862452;0.013880;, - 0.862452;0.025890;, - 0.864354;0.033144;, - 0.824507;0.013880;, - 0.824507;0.025890;, - 0.826409;0.033187;, - 0.874000;0.390598;, - 0.874000;0.390602;, - 0.977189;0.020514;, - 0.978600;0.020878;, - 0.885381;0.334233;, - 0.918247;0.169976;, - 0.918247;0.167944;, - 0.918025;0.131270;, - 0.918025;0.159841;, - 0.918247;0.168000;, - 0.918247;0.170032;, - 0.182508;0.766866;, - 0.208776;0.768315;, - 0.178079;0.768382;, - 0.191817;0.726879;, - 0.208776;0.727114;, - 0.193589;0.678436;, - 0.212995;0.768315;, - 0.182405;0.769142;, - 0.212995;0.722253;, - 0.198628;0.682655;, - 0.212995;0.722253;, - 0.198628;0.682655;, - 0.201590;0.811736;, - 0.217974;0.804906;, - 0.206868;0.780799;, - 0.217974;0.781483;, - 0.892228;0.291435;, - 0.891228;0.302435;, - 0.892228;0.280722;, - 0.892253;0.306969;, - 0.892222;0.307059;, - 0.936839;0.410331;, - 0.966333;0.367325;, - 0.979634;0.022435;, - 0.924808;0.367270;, - 0.955046;0.367325;, - 0.924796;0.367275;, - 0.936839;0.400070;, - 0.955046;0.332160;, - 0.942046;0.332160;, - 0.966333;0.332160;, - 0.966333;0.332160;, - 0.980710;0.020420;, - 0.978600;0.017357;, - 0.920741;0.363700;, - 0.920766;0.363703;, - 0.920780;0.363679;, - 0.936500;0.332500;, - 0.979993;0.020455;, - 0.978600;0.018074;, - 0.925926;0.333333;, - 0.686697;0.042090;, - 0.686383;0.041777;, - 0.711221;0.041841;, - 0.722178;0.040237;, - 0.711212;0.041930;, - 0.711058;0.017096;, - 0.710839;0.016926;, - 0.722178;0.019530;, - 0.686540;0.017172;, - 0.686540;0.017166;, - 0.943531;0.170051;, - 0.957753;0.175131;, - 0.968940;0.133152;, - 0.943531;0.167944;, - 0.943309;0.131325;, - 0.957531;0.135035;, - 0.966079;0.134702;, - 0.957753;0.173024;, - 0.943309;0.159786;, - 0.943531;0.168000;, - 0.957531;0.156076;, - 0.957753;0.173079;, - 0.966079;0.155887;, - 0.943531;0.170107;, - 0.957753;0.175186;, - 0.968940;0.157437;, - 0.966333;0.305786;, - 0.942926;0.280722;, - 0.942300;0.306196;, - 0.942300;0.306200;, - 0.955046;0.305786;, - 0.942926;0.291435;, - 0.937193;0.291435;, - 0.937193;0.302435;, - 0.937193;0.280722;, - 0.931623;0.307069;, - 0.931630;0.307059;, - 0.936303;0.309600;, - 0.713500;0.089000;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.699532;0.075033;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.699532;0.102968;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.713500;0.089000;, - 0.672880;0.074825;, - 0.673214;0.103508;, - 0.672880;0.089111;, - 0.672880;0.104508;, - 0.672880;0.103397;, - 0.672880;0.090222;, - 0.690009;0.103508;, - 0.699532;0.075033;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.693747;0.089000;, - 0.689675;0.103397;, - 0.699532;0.102968;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.713500;0.108753;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.673214;0.089222;, - 0.690009;0.089222;, - 0.713500;0.069247;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.727468;0.075033;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.727468;0.102968;, - 0.672880;0.089111;, - 0.673214;0.074937;, - 0.672880;0.074825;, - 0.672880;0.103397;, - 0.672880;0.075937;, - 0.689675;0.074825;, - 0.727468;0.075033;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.733253;0.089000;, - 0.689675;0.075937;, - 0.727468;0.102968;, - 0.689675;0.103397;, - 0.918247;0.169976;, - 0.918247;0.167944;, - 0.918025;0.131270;, - 0.918025;0.159841;, - 0.918247;0.168000;, - 0.918247;0.170032;, - 0.686697;0.042090;, - 0.686383;0.041777;, - 0.711221;0.041841;, - 0.722178;0.040237;, - 0.711212;0.041930;, - 0.711058;0.017096;, - 0.710839;0.016926;, - 0.722178;0.019530;, - 0.686540;0.017172;, - 0.686540;0.017166;, - 0.943531;0.170051;, - 0.957753;0.175131;, - 0.968940;0.133152;, - 0.943531;0.167944;, - 0.943309;0.131325;, - 0.957531;0.135035;, - 0.966079;0.134702;, - 0.957753;0.173024;, - 0.943309;0.159786;, - 0.943531;0.168000;, - 0.957531;0.156076;, - 0.957753;0.173079;, - 0.966079;0.155887;, - 0.943531;0.170107;, - 0.957753;0.175186;, - 0.968940;0.157437;, - 0.806177;0.111554;, - 0.818815;0.114854;, - 0.818477;0.111554;, - 0.818506;0.111551;, - 0.806054;0.037284;, - 0.816593;0.026083;, - 0.818506;0.037251;, - 0.818354;0.037284;, - 0.830295;0.111366;, - 0.830238;0.111442;, - 0.841218;0.111366;, - 0.841314;0.111442;, - 0.841241;0.111373;, - 0.824065;0.108391;, - 0.824024;0.108408;, - 0.826483;0.114661;, - 0.826420;0.114626;, - 0.843742;0.114661;, - 0.896810;0.111583;, - 0.843674;0.114607;, - 0.860172;0.035810;, - 0.830283;0.035767;, - 0.830283;0.035763;, - 0.874513;0.073311;, - 0.874515;0.073245;, - 0.874515;0.043185;, - 0.874513;0.043157;, - 0.824065;0.039785;, - 0.824024;0.039738;, - 0.896810;0.072339;, - 0.880635;0.073336;, - 0.896810;0.039635;, - 0.878714;0.025890;, - 0.880635;0.041337;, - 0.880627;0.041351;, - 0.862452;0.025890;, - 0.864354;0.033144;, - 0.824507;0.025890;, - 0.826409;0.033187;, - 0.977022;0.021746;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.976941;0.021762;, - 0.976866;0.021710;, - 0.186550;0.382365;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.976874;0.021757;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021718;, - 0.976831;0.021731;, - 0.186550;0.382338;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.178570;0.404936;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.976808;0.021859;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.178570;0.404949;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.186550;0.382365;, - 0.976887;0.021710;, - 0.976941;0.021651;, - 0.178570;0.382418;, - 0.176404;0.382494;, - 0.976887;0.021756;, - 0.186138;0.413602;, - 0.176177;0.404762;, - 0.178572;0.404842;, - 0.178574;0.404842;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.186550;0.382334;, - 0.976853;0.021731;, - 0.976986;0.021718;, - 0.178570;0.382379;, - 0.176404;0.382508;, - 0.976853;0.021747;, - 0.976872;0.021776;, - 0.176176;0.404762;, - 0.178570;0.404934;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.186550;0.382342;, - 0.976919;0.021730;, - 0.178570;0.382383;, - 0.176404;0.382505;, - 0.976919;0.021690;, - 0.976887;0.021767;, - 0.176178;0.404770;, - 0.178570;0.404955;, - 0.977022;0.021746;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.976941;0.021762;, - 0.976866;0.021710;, - 0.186550;0.382365;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.976874;0.021757;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021718;, - 0.976831;0.021731;, - 0.186550;0.382338;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.178570;0.404936;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.976808;0.021859;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.178570;0.404949;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.186550;0.382365;, - 0.976887;0.021710;, - 0.976941;0.021651;, - 0.178570;0.382418;, - 0.176404;0.382494;, - 0.976887;0.021756;, - 0.186138;0.413602;, - 0.176177;0.404762;, - 0.178572;0.404842;, - 0.178574;0.404842;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.186550;0.382334;, - 0.976853;0.021731;, - 0.976986;0.021718;, - 0.178570;0.382379;, - 0.176404;0.382508;, - 0.976853;0.021747;, - 0.976872;0.021776;, - 0.176176;0.404762;, - 0.178570;0.404934;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.186550;0.382342;, - 0.976919;0.021730;, - 0.178570;0.382383;, - 0.176404;0.382505;, - 0.976919;0.021690;, - 0.976887;0.021767;, - 0.176178;0.404770;, - 0.178570;0.404955;, - 0.977022;0.021746;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.976941;0.021762;, - 0.976866;0.021710;, - 0.186550;0.382365;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.976874;0.021757;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021718;, - 0.976831;0.021731;, - 0.186550;0.382338;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.178570;0.404936;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.976808;0.021859;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.178570;0.404949;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.186550;0.382365;, - 0.976887;0.021710;, - 0.976941;0.021651;, - 0.178570;0.382418;, - 0.176404;0.382494;, - 0.976887;0.021756;, - 0.186138;0.413602;, - 0.176177;0.404762;, - 0.178572;0.404842;, - 0.178574;0.404842;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.186550;0.382334;, - 0.976853;0.021731;, - 0.976986;0.021718;, - 0.178570;0.382379;, - 0.176404;0.382508;, - 0.976853;0.021747;, - 0.976872;0.021776;, - 0.176176;0.404762;, - 0.178570;0.404934;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.186550;0.382342;, - 0.976919;0.021730;, - 0.178570;0.382383;, - 0.176404;0.382505;, - 0.976919;0.021690;, - 0.976887;0.021767;, - 0.176178;0.404770;, - 0.178570;0.404955;, - 0.977022;0.021746;, - 0.186721;0.404557;, - 0.178658;0.406115;, - 0.976941;0.021762;, - 0.976866;0.021710;, - 0.186550;0.382365;, - 0.976866;0.021756;, - 0.178570;0.382418;, - 0.167968;0.382474;, - 0.976874;0.021757;, - 0.186721;0.404568;, - 0.976850;0.021747;, - 0.976874;0.021718;, - 0.976831;0.021731;, - 0.186550;0.382338;, - 0.976831;0.021747;, - 0.178570;0.382383;, - 0.167968;0.382533;, - 0.178570;0.404936;, - 0.976850;0.021776;, - 0.167965;0.404754;, - 0.976808;0.021859;, - 0.186721;0.404561;, - 0.976866;0.021727;, - 0.976808;0.021730;, - 0.186550;0.382334;, - 0.976808;0.021690;, - 0.178570;0.382372;, - 0.167968;0.382521;, - 0.178570;0.404949;, - 0.976866;0.021767;, - 0.167968;0.404757;, - 0.977022;0.021667;, - 0.186721;0.404557;, - 0.186741;0.406115;, - 0.186550;0.382365;, - 0.976887;0.021710;, - 0.976941;0.021651;, - 0.178570;0.382418;, - 0.176404;0.382494;, - 0.976887;0.021756;, - 0.186138;0.413602;, - 0.176177;0.404762;, - 0.178572;0.404842;, - 0.178574;0.404842;, - 0.179261;0.413602;, - 0.167968;0.404754;, - 0.976986;0.021757;, - 0.186721;0.404564;, - 0.976872;0.021747;, - 0.186550;0.382334;, - 0.976853;0.021731;, - 0.976986;0.021718;, - 0.178570;0.382379;, - 0.176404;0.382508;, - 0.976853;0.021747;, - 0.976872;0.021776;, - 0.176176;0.404762;, - 0.178570;0.404934;, - 0.976919;0.021859;, - 0.186721;0.404569;, - 0.976887;0.021727;, - 0.186550;0.382342;, - 0.976919;0.021730;, - 0.178570;0.382383;, - 0.176404;0.382505;, - 0.976919;0.021690;, - 0.976887;0.021767;, - 0.176178;0.404770;, - 0.178570;0.404955;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.672880;0.074825;, - 0.673214;0.103508;, - 0.672880;0.089111;, - 0.672880;0.104508;, - 0.672880;0.103397;, - 0.672880;0.090222;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.690009;0.089222;, - 0.673214;0.089222;, - 0.690009;0.089222;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.672880;0.089111;, - 0.673214;0.074937;, - 0.672880;0.074825;, - 0.672880;0.103397;, - 0.672880;0.075937;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.672880;0.074825;, - 0.673214;0.103508;, - 0.672880;0.089111;, - 0.672880;0.104508;, - 0.672880;0.103397;, - 0.672880;0.090222;, - 0.690009;0.103508;, - 0.689675;0.074825;, - 0.689675;0.089111;, - 0.689675;0.103397;, - 0.689675;0.104508;, - 0.689675;0.090222;, - 0.690009;0.089222;, - 0.673214;0.089222;, - 0.690009;0.089222;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.672880;0.089111;, - 0.673214;0.074937;, - 0.672880;0.074825;, - 0.672880;0.103397;, - 0.672880;0.075937;, - 0.689675;0.074825;, - 0.690009;0.074937;, - 0.689675;0.089111;, - 0.689675;0.075937;, - 0.689675;0.103397;, - 0.062673;0.171389;, - 0.123628;0.174197;, - 0.123573;0.174197;, - 0.062673;0.153611;, - 0.040549;0.153611;, - 0.099649;0.174197;, - 0.040549;0.171389;, - 0.099705;0.174197;, - 0.149444;0.168841;, - 0.032025;0.171556;, - 0.090307;0.140477;, - 0.167222;0.168841;, - 0.032025;0.153778;, - 0.090251;0.140477;, - 0.167222;0.154555;, - 0.086359;0.154444;, - 0.149444;0.154555;, - 0.086414;0.154444;, - 0.149444;0.140270;, - 0.090307;0.168412;, - 0.031858;0.171389;, - 0.031858;0.153611;, - 0.090251;0.168412;, - 0.167222;0.140270;, - 0.149444;0.168619;, - 0.133026;0.140477;, - 0.071531;0.171556;, - 0.149444;0.154333;, - 0.136919;0.154444;, - 0.167222;0.154333;, - 0.136864;0.154444;, - 0.071531;0.153778;, - 0.132971;0.140477;, - 0.167222;0.168619;, - 0.149444;0.140048;, - 0.071364;0.171389;, - 0.133026;0.168412;, - 0.167222;0.140048;, - 0.071364;0.153611;, - 0.132971;0.168412;, - 0.062840;0.153778;, - 0.123573;0.134691;, - 0.062840;0.171556;, - 0.123628;0.134691;, - 0.040716;0.171556;, - 0.099705;0.134691;, - 0.040716;0.153778;, - 0.099649;0.134691;, - 0.745439;0.090556;, - 0.736667;0.086111;, - 0.760385;0.107030;, - 0.760111;0.107155;, - 0.745556;0.081667;, - 0.760428;0.107343;, - 0.768028;0.107043;, - 0.736667;0.095000;, - 0.768593;0.107030;, - 0.759889;0.107155;, - 0.745556;0.099444;, - 0.767806;0.107043;, - 0.760206;0.107343;, - 0.754444;0.095000;, - 0.768123;0.107230;, - 0.768292;0.107041;, - 0.754444;0.086111;, - 0.759885;0.107141;, - 0.768345;0.107230;, - 0.745278;0.081667;, - 0.760172;0.056313;, - 0.767572;0.056213;, - 0.736389;0.086111;, - 0.759855;0.056125;, - 0.760185;0.056325;, - 0.736389;0.095000;, - 0.767593;0.056025;, - 0.760033;0.056525;, - 0.745278;0.099444;, - 0.767750;0.056213;, - 0.759950;0.056313;, - 0.754167;0.095000;, - 0.767667;0.056401;, - 0.767492;0.056136;, - 0.754167;0.086111;, - 0.759685;0.056136;, - 0.767889;0.056401;, - 0.745394;0.090556;, - 0.745439;0.090556;, - 0.736667;0.086111;, - 0.760385;0.107030;, - 0.760111;0.107155;, - 0.745556;0.081667;, - 0.760428;0.107343;, - 0.768028;0.107043;, - 0.736667;0.095000;, - 0.768593;0.107030;, - 0.759889;0.107155;, - 0.745556;0.099444;, - 0.767806;0.107043;, - 0.760206;0.107343;, - 0.754444;0.095000;, - 0.768123;0.107230;, - 0.768292;0.107041;, - 0.754444;0.086111;, - 0.759885;0.107141;, - 0.768345;0.107230;, - 0.745278;0.081667;, - 0.760172;0.056313;, - 0.767572;0.056213;, - 0.736389;0.086111;, - 0.759855;0.056125;, - 0.760185;0.056325;, - 0.736389;0.095000;, - 0.767593;0.056025;, - 0.760033;0.056525;, - 0.745278;0.099444;, - 0.767750;0.056213;, - 0.759950;0.056313;, - 0.754167;0.095000;, - 0.767667;0.056401;, - 0.767492;0.056136;, - 0.754167;0.086111;, - 0.759685;0.056136;, - 0.767889;0.056401;, - 0.745394;0.090556;, - 0.838013;0.644010;, - 0.806970;0.634953;, - 0.806582;0.610378;, - 0.806970;0.614451;, - 0.838679;0.622304;, - 0.817208;0.634953;, - 0.838013;0.636352;, - 0.822345;0.610041;, - 0.817208;0.614303;, - 0.817008;0.610276;, - 0.838556;0.622399;, - 0.838013;0.666985;, - 0.780555;0.634953;, - 0.822835;0.609487;, - 0.780463;0.610378;, - 0.780555;0.614451;, - 0.839581;0.540742;, - 0.806582;0.560659;, - 0.843483;0.559874;, - 0.817008;0.559987;, - 0.840253;0.551168;, - 0.843360;0.559970;, - 0.839581;0.514623;, - 0.780463;0.560659;, - 0.934292;0.644010;, - 0.957666;0.619028;, - 0.957666;0.611939;, - 0.957560;0.611580;, - 0.941966;0.614500;, - 0.949066;0.611580;, - 0.934760;0.622304;, - 0.949062;0.619028;, - 0.949066;0.618864;, - 0.934292;0.636352;, - 0.942099;0.614249;, - 0.983135;0.611939;, - 0.983041;0.611580;, - 0.935276;0.622399;, - 0.934292;0.666985;, - 0.983135;0.619028;, - 0.578467;0.104666;, - 0.578467;0.086889;, - 0.568063;0.070993;, - 0.957560;0.556434;, - 0.944827;0.540742;, - 0.944827;0.540742;, - 0.957560;0.556434;, - 0.941966;0.559874;, - 0.938323;0.551168;, - 0.949066;0.560596;, - 0.569556;0.104555;, - 0.569578;0.104666;, - 0.569578;0.086889;, - 0.571031;0.063828;, - 0.569556;0.086778;, - 0.578445;0.086778;, - 0.578197;0.060860;, - 0.578445;0.104555;, - 0.587356;0.104666;, - 0.569667;0.104555;, - 0.569667;0.086778;, - 0.571031;0.078159;, - 0.587356;0.086889;, - 0.578556;0.104555;, - 0.578556;0.086778;, - 0.578197;0.081127;, - 0.587556;0.104222;, - 0.587444;0.104555;, - 0.587444;0.086778;, - 0.587556;0.086444;, - 0.585362;0.078159;, - 0.578667;0.104222;, - 0.578667;0.086444;, - 0.588330;0.070993;, - 0.587333;0.104555;, - 0.569778;0.104222;, - 0.569778;0.086444;, - 0.587333;0.086778;, - 0.585362;0.063828;, - 0.578197;0.070993;, - 0.942099;0.559970;, - 0.983041;0.556434;, - 0.944827;0.514623;, - 0.578467;0.104666;, - 0.578467;0.086889;, - 0.568063;0.070993;, - 0.569556;0.104555;, - 0.569578;0.104666;, - 0.569578;0.086889;, - 0.571031;0.063828;, - 0.569556;0.086778;, - 0.578445;0.086778;, - 0.578197;0.060860;, - 0.578445;0.104555;, - 0.587356;0.104666;, - 0.569667;0.104555;, - 0.569667;0.086778;, - 0.571031;0.078159;, - 0.587356;0.086889;, - 0.578556;0.104555;, - 0.578556;0.086778;, - 0.578197;0.081127;, - 0.587556;0.104222;, - 0.587444;0.104555;, - 0.587444;0.086778;, - 0.587556;0.086444;, - 0.585362;0.078159;, - 0.578667;0.104222;, - 0.578667;0.086444;, - 0.588330;0.070993;, - 0.587333;0.104555;, - 0.569778;0.104222;, - 0.569778;0.086444;, - 0.587333;0.086778;, - 0.585362;0.063828;, - 0.578197;0.070993;, - 0.578467;0.104666;, - 0.578467;0.086889;, - 0.568063;0.070993;, - 0.569556;0.104555;, - 0.569578;0.104666;, - 0.569578;0.086889;, - 0.571031;0.063828;, - 0.569556;0.086778;, - 0.578445;0.086778;, - 0.578197;0.060860;, - 0.578445;0.104555;, - 0.587356;0.104666;, - 0.569667;0.104555;, - 0.569667;0.086778;, - 0.571031;0.078159;, - 0.587356;0.086889;, - 0.578556;0.104555;, - 0.578556;0.086778;, - 0.578197;0.081127;, - 0.587556;0.104222;, - 0.587444;0.104555;, - 0.587444;0.086778;, - 0.587556;0.086444;, - 0.585362;0.078159;, - 0.578667;0.104222;, - 0.578667;0.086444;, - 0.588330;0.070993;, - 0.587333;0.104555;, - 0.569778;0.104222;, - 0.569778;0.086444;, - 0.587333;0.086778;, - 0.585362;0.063828;, - 0.578197;0.070993;, - 0.838013;0.644010;, - 0.806970;0.634953;, - 0.806582;0.610378;, - 0.806970;0.614451;, - 0.838679;0.622304;, - 0.817208;0.634953;, - 0.838013;0.636352;, - 0.822345;0.610041;, - 0.817208;0.614303;, - 0.817008;0.610276;, - 0.838556;0.622399;, - 0.838013;0.666985;, - 0.780555;0.634953;, - 0.822835;0.609487;, - 0.780463;0.610378;, - 0.780555;0.614451;, - 0.839581;0.540742;, - 0.806582;0.560659;, - 0.843483;0.559874;, - 0.817008;0.559987;, - 0.840253;0.551168;, - 0.843360;0.559970;, - 0.839581;0.514623;, - 0.780463;0.560659;, - 0.934292;0.644010;, - 0.957666;0.619028;, - 0.957666;0.611939;, - 0.957560;0.611580;, - 0.941966;0.614500;, - 0.949066;0.611580;, - 0.934760;0.622304;, - 0.949062;0.619028;, - 0.949066;0.618864;, - 0.934292;0.636352;, - 0.942099;0.614249;, - 0.983135;0.611939;, - 0.983041;0.611580;, - 0.935276;0.622399;, - 0.934292;0.666985;, - 0.983135;0.619028;, - 0.578467;0.104666;, - 0.578467;0.086889;, - 0.568063;0.070993;, - 0.957560;0.556434;, - 0.944827;0.540742;, - 0.944827;0.540742;, - 0.957560;0.556434;, - 0.941966;0.559874;, - 0.938323;0.551168;, - 0.949066;0.560596;, - 0.569556;0.104555;, - 0.569578;0.104666;, - 0.569556;0.086778;, - 0.569578;0.086889;, - 0.571031;0.063828;, - 0.578445;0.086778;, - 0.578197;0.060860;, - 0.578445;0.104555;, - 0.587356;0.104666;, - 0.569667;0.104555;, - 0.587356;0.086889;, - 0.569667;0.086778;, - 0.571031;0.078159;, - 0.578556;0.104555;, - 0.578556;0.086778;, - 0.578197;0.081127;, - 0.587444;0.104555;, - 0.587556;0.104222;, - 0.587444;0.086778;, - 0.585362;0.078159;, - 0.587556;0.086444;, - 0.578667;0.104222;, - 0.578667;0.086444;, - 0.588330;0.070993;, - 0.569778;0.104222;, - 0.587333;0.104555;, - 0.569778;0.086444;, - 0.585362;0.063828;, - 0.587333;0.086778;, - 0.578197;0.070993;, - 0.942099;0.559970;, - 0.983041;0.556434;, - 0.944827;0.514623;, - 0.578467;0.104666;, - 0.578467;0.086889;, - 0.568063;0.070993;, - 0.569556;0.104555;, - 0.569578;0.104666;, - 0.569556;0.086778;, - 0.569578;0.086889;, - 0.571031;0.063828;, - 0.578445;0.086778;, - 0.578197;0.060860;, - 0.578445;0.104555;, - 0.587356;0.104666;, - 0.569667;0.104555;, - 0.587356;0.086889;, - 0.569667;0.086778;, - 0.571031;0.078159;, - 0.578556;0.104555;, - 0.578556;0.086778;, - 0.578197;0.081127;, - 0.587444;0.104555;, - 0.587556;0.104222;, - 0.587444;0.086778;, - 0.585362;0.078159;, - 0.587556;0.086444;, - 0.578667;0.104222;, - 0.578667;0.086444;, - 0.588330;0.070993;, - 0.569778;0.104222;, - 0.587333;0.104555;, - 0.569778;0.086444;, - 0.585362;0.063828;, - 0.587333;0.086778;, - 0.578197;0.070993;, - 0.578467;0.104666;, - 0.578467;0.086889;, - 0.568063;0.070993;, - 0.569556;0.104555;, - 0.569578;0.104666;, - 0.569556;0.086778;, - 0.569578;0.086889;, - 0.571031;0.063828;, - 0.578445;0.086778;, - 0.578197;0.060860;, - 0.578445;0.104555;, - 0.587356;0.104666;, - 0.569667;0.104555;, - 0.587356;0.086889;, - 0.569667;0.086778;, - 0.571031;0.078159;, - 0.578556;0.104555;, - 0.578556;0.086778;, - 0.578197;0.081127;, - 0.587444;0.104555;, - 0.587556;0.104222;, - 0.587444;0.086778;, - 0.585362;0.078159;, - 0.587556;0.086444;, - 0.578667;0.104222;, - 0.578667;0.086444;, - 0.588330;0.070993;, - 0.569778;0.104222;, - 0.587333;0.104555;, - 0.569778;0.086444;, - 0.585362;0.063828;, - 0.587333;0.086778;, - 0.578197;0.070993;, - 0.979667;0.022376;, - 0.863305;0.258475;, - 0.977710;0.021115;, - 0.977948;0.021115;, - 0.977710;0.021115;, - 0.979667;0.020878;, - 0.979667;0.018074;, - 0.986086;0.332160;, - 0.979667;0.017357;, - 0.892228;0.258475;, - 0.937193;0.258475;, - 0.942926;0.258475;, - 0.986086;0.305786;; - } - - VertexDuplicationIndices { - 6202; - 6201; - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 48, - 50, - 50, - 50, - 53, - 54, - 54, - 56, - 56, - 58, - 58, - 58, - 61, - 61, - 63, - 63, - 65, - 65, - 65, - 68, - 69, - 69, - 71, - 72, - 72, - 72, - 72, - 76, - 76, - 76, - 76, - 80, - 80, - 82, - 82, - 84, - 84, - 86, - 86, - 86, - 89, - 90, - 90, - 92, - 92, - 94, - 94, - 96, - 97, - 97, - 99, - 100, - 100, - 102, - 102, - 104, - 105, - 105, - 107, - 107, - 107, - 110, - 110, - 112, - 112, - 114, - 114, - 116, - 116, - 118, - 119, - 120, - 120, - 120, - 123, - 123, - 125, - 125, - 127, - 127, - 129, - 129, - 129, - 132, - 132, - 134, - 134, - 134, - 137, - 137, - 137, - 137, - 141, - 141, - 141, - 144, - 144, - 146, - 146, - 146, - 149, - 149, - 151, - 151, - 151, - 154, - 154, - 156, - 157, - 157, - 159, - 159, - 161, - 161, - 163, - 163, - 163, - 166, - 166, - 166, - 169, - 169, - 169, - 172, - 172, - 174, - 174, - 176, - 176, - 178, - 178, - 180, - 180, - 180, - 180, - 184, - 184, - 184, - 187, - 187, - 189, - 189, - 189, - 192, - 193, - 193, - 195, - 195, - 195, - 198, - 198, - 198, - 201, - 202, - 202, - 204, - 205, - 205, - 205, - 205, - 209, - 209, - 211, - 211, - 211, - 214, - 214, - 214, - 214, - 218, - 218, - 220, - 220, - 222, - 223, - 223, - 223, - 223, - 227, - 227, - 229, - 229, - 231, - 231, - 233, - 234, - 235, - 235, - 237, - 238, - 239, - 239, - 241, - 242, - 243, - 244, - 245, - 245, - 245, - 248, - 248, - 248, - 248, - 252, - 253, - 253, - 255, - 255, - 257, - 258, - 258, - 260, - 261, - 262, - 262, - 262, - 265, - 265, - 265, - 268, - 268, - 268, - 271, - 272, - 272, - 274, - 274, - 276, - 276, - 278, - 278, - 280, - 280, - 282, - 282, - 284, - 284, - 284, - 287, - 287, - 287, - 290, - 290, - 290, - 293, - 293, - 295, - 295, - 295, - 298, - 298, - 298, - 301, - 301, - 301, - 304, - 305, - 305, - 307, - 307, - 309, - 309, - 309, - 312, - 312, - 312, - 315, - 315, - 315, - 318, - 318, - 318, - 318, - 322, - 322, - 324, - 324, - 324, - 327, - 327, - 327, - 330, - 330, - 332, - 332, - 334, - 334, - 336, - 336, - 338, - 338, - 340, - 340, - 342, - 342, - 342, - 342, - 346, - 346, - 348, - 348, - 348, - 351, - 351, - 353, - 353, - 355, - 355, - 355, - 358, - 358, - 358, - 361, - 361, - 363, - 363, - 365, - 365, - 367, - 367, - 369, - 369, - 371, - 371, - 373, - 374, - 375, - 376, - 376, - 376, - 379, - 379, - 381, - 381, - 383, - 383, - 385, - 385, - 385, - 385, - 389, - 389, - 391, - 391, - 391, - 394, - 394, - 394, - 394, - 398, - 398, - 400, - 401, - 402, - 402, - 404, - 404, - 404, - 407, - 407, - 409, - 409, - 411, - 412, - 413, - 413, - 415, - 415, - 415, - 418, - 418, - 420, - 420, - 422, - 422, - 422, - 425, - 426, - 426, - 428, - 428, - 428, - 431, - 431, - 431, - 434, - 434, - 436, - 436, - 436, - 439, - 439, - 439, - 442, - 442, - 444, - 445, - 446, - 447, - 448, - 448, - 450, - 450, - 452, - 452, - 454, - 454, - 454, - 457, - 457, - 459, - 459, - 461, - 462, - 463, - 463, - 465, - 465, - 465, - 468, - 468, - 470, - 470, - 472, - 472, - 474, - 474, - 476, - 476, - 478, - 479, - 479, - 481, - 481, - 481, - 481, - 485, - 485, - 485, - 485, - 489, - 489, - 491, - 491, - 493, - 493, - 495, - 496, - 497, - 497, - 497, - 500, - 500, - 502, - 502, - 504, - 505, - 506, - 506, - 508, - 508, - 510, - 510, - 510, - 513, - 514, - 515, - 515, - 517, - 518, - 519, - 519, - 521, - 521, - 521, - 524, - 524, - 524, - 527, - 528, - 529, - 530, - 530, - 532, - 532, - 532, - 535, - 535, - 535, - 538, - 538, - 540, - 541, - 541, - 543, - 543, - 545, - 546, - 546, - 548, - 548, - 550, - 550, - 550, - 553, - 553, - 553, - 556, - 556, - 558, - 558, - 560, - 561, - 561, - 561, - 564, - 564, - 564, - 567, - 567, - 567, - 570, - 571, - 571, - 573, - 573, - 575, - 576, - 576, - 576, - 579, - 579, - 579, - 582, - 582, - 584, - 584, - 584, - 587, - 587, - 589, - 589, - 589, - 592, - 592, - 594, - 594, - 594, - 597, - 597, - 599, - 600, - 600, - 600, - 603, - 603, - 603, - 603, - 607, - 607, - 609, - 609, - 609, - 612, - 612, - 612, - 615, - 615, - 615, - 618, - 618, - 618, - 621, - 621, - 623, - 623, - 623, - 626, - 626, - 626, - 629, - 629, - 629, - 632, - 632, - 632, - 635, - 635, - 635, - 638, - 638, - 638, - 641, - 641, - 643, - 644, - 644, - 646, - 647, - 647, - 647, - 650, - 650, - 652, - 652, - 654, - 654, - 656, - 656, - 658, - 659, - 659, - 661, - 661, - 661, - 664, - 664, - 666, - 666, - 666, - 669, - 669, - 671, - 671, - 671, - 671, - 675, - 675, - 677, - 677, - 677, - 680, - 680, - 680, - 683, - 683, - 683, - 686, - 686, - 686, - 689, - 689, - 691, - 691, - 691, - 694, - 694, - 694, - 697, - 697, - 697, - 700, - 700, - 700, - 703, - 703, - 703, - 706, - 706, - 706, - 709, - 709, - 711, - 711, - 713, - 713, - 715, - 715, - 715, - 718, - 719, - 720, - 720, - 722, - 722, - 724, - 724, - 726, - 726, - 726, - 729, - 729, - 729, - 732, - 732, - 732, - 735, - 736, - 737, - 737, - 739, - 740, - 741, - 741, - 743, - 743, - 743, - 746, - 747, - 747, - 747, - 750, - 750, - 750, - 753, - 753, - 755, - 756, - 756, - 758, - 758, - 758, - 758, - 762, - 762, - 764, - 764, - 766, - 767, - 767, - 767, - 770, - 770, - 770, - 770, - 774, - 774, - 774, - 777, - 777, - 779, - 779, - 781, - 781, - 781, - 784, - 784, - 784, - 784, - 788, - 788, - 790, - 791, - 791, - 793, - 793, - 793, - 796, - 796, - 796, - 796, - 800, - 800, - 800, - 800, - 804, - 804, - 804, - 807, - 807, - 807, - 810, - 810, - 812, - 812, - 814, - 814, - 816, - 816, - 816, - 819, - 820, - 820, - 820, - 823, - 823, - 823, - 826, - 826, - 826, - 829, - 829, - 829, - 832, - 832, - 832, - 835, - 835, - 835, - 838, - 838, - 838, - 841, - 841, - 841, - 844, - 844, - 846, - 846, - 846, - 849, - 849, - 849, - 852, - 852, - 854, - 854, - 856, - 856, - 858, - 858, - 860, - 860, - 860, - 863, - 863, - 863, - 866, - 866, - 868, - 868, - 870, - 870, - 872, - 872, - 874, - 875, - 876, - 876, - 876, - 876, - 880, - 880, - 882, - 882, - 884, - 884, - 886, - 887, - 887, - 889, - 889, - 891, - 891, - 891, - 891, - 895, - 895, - 897, - 897, - 899, - 899, - 901, - 901, - 903, - 903, - 905, - 906, - 906, - 908, - 908, - 910, - 910, - 910, - 913, - 913, - 913, - 916, - 916, - 916, - 919, - 919, - 921, - 921, - 921, - 924, - 924, - 926, - 926, - 928, - 928, - 930, - 930, - 932, - 932, - 934, - 934, - 934, - 937, - 937, - 939, - 939, - 941, - 941, - 941, - 941, - 945, - 945, - 945, - 948, - 948, - 950, - 951, - 951, - 953, - 953, - 955, - 955, - 955, - 958, - 958, - 958, - 961, - 962, - 962, - 962, - 965, - 965, - 965, - 968, - 968, - 968, - 971, - 971, - 971, - 974, - 974, - 974, - 977, - 977, - 977, - 980, - 980, - 980, - 983, - 983, - 985, - 985, - 985, - 988, - 988, - 990, - 990, - 990, - 993, - 993, - 993, - 996, - 996, - 996, - 999, - 1000, - 1000, - 1002, - 1002, - 1004, - 1005, - 1005, - 1007, - 1008, - 1009, - 1009, - 1009, - 1012, - 1012, - 1014, - 1014, - 1014, - 1014, - 1018, - 1018, - 1018, - 1021, - 1022, - 1022, - 1024, - 1024, - 1024, - 1027, - 1027, - 1029, - 1029, - 1031, - 1031, - 1033, - 1033, - 1035, - 1035, - 1035, - 1038, - 1038, - 1038, - 1041, - 1041, - 1041, - 1044, - 1045, - 1045, - 1047, - 1048, - 1048, - 1050, - 1050, - 1050, - 1053, - 1054, - 1054, - 1054, - 1057, - 1057, - 1057, - 1060, - 1060, - 1060, - 1063, - 1063, - 1063, - 1066, - 1066, - 1068, - 1068, - 1068, - 1071, - 1071, - 1071, - 1074, - 1075, - 1076, - 1076, - 1076, - 1079, - 1079, - 1081, - 1082, - 1083, - 1083, - 1083, - 1086, - 1086, - 1086, - 1089, - 1089, - 1089, - 1092, - 1092, - 1092, - 1095, - 1095, - 1097, - 1097, - 1099, - 1099, - 1099, - 1102, - 1102, - 1102, - 1105, - 1105, - 1107, - 1107, - 1109, - 1109, - 1111, - 1111, - 1111, - 1114, - 1114, - 1114, - 1117, - 1117, - 1119, - 1119, - 1121, - 1121, - 1121, - 1121, - 1125, - 1126, - 1126, - 1126, - 1129, - 1129, - 1131, - 1131, - 1133, - 1134, - 1134, - 1136, - 1136, - 1138, - 1138, - 1138, - 1138, - 1142, - 1142, - 1144, - 1145, - 1145, - 1145, - 1148, - 1148, - 1150, - 1150, - 1152, - 1152, - 1154, - 1154, - 1154, - 1154, - 1158, - 1158, - 1158, - 1158, - 1162, - 1162, - 1164, - 1164, - 1164, - 1167, - 1167, - 1167, - 1170, - 1170, - 1172, - 1172, - 1174, - 1174, - 1176, - 1176, - 1178, - 1178, - 1180, - 1180, - 1182, - 1183, - 1184, - 1184, - 1186, - 1186, - 1188, - 1189, - 1190, - 1190, - 1192, - 1193, - 1194, - 1194, - 1196, - 1197, - 1198, - 1198, - 1200, - 1200, - 1200, - 1200, - 1204, - 1204, - 1206, - 1206, - 1206, - 1206, - 1210, - 1211, - 1212, - 1213, - 1214, - 1214, - 1216, - 1216, - 1216, - 1216, - 1220, - 1220, - 1220, - 1223, - 1223, - 1223, - 1226, - 1226, - 1228, - 1228, - 1230, - 1230, - 1232, - 1233, - 1233, - 1235, - 1235, - 1235, - 1238, - 1238, - 1240, - 1240, - 1240, - 1240, - 1244, - 1245, - 1245, - 1247, - 1247, - 1249, - 1250, - 1251, - 1252, - 1253, - 1253, - 1255, - 1255, - 1255, - 1258, - 1258, - 1260, - 1260, - 1260, - 1260, - 1264, - 1264, - 1266, - 1267, - 1267, - 1267, - 1270, - 1270, - 1272, - 1272, - 1272, - 1275, - 1275, - 1275, - 1278, - 1278, - 1280, - 1280, - 1282, - 1282, - 1282, - 1285, - 1285, - 1285, - 1288, - 1289, - 1289, - 1291, - 1291, - 1293, - 1293, - 1293, - 1296, - 1297, - 1298, - 1298, - 1300, - 1300, - 1302, - 1302, - 1302, - 1305, - 1305, - 1307, - 1307, - 1307, - 1310, - 1310, - 1312, - 1312, - 1314, - 1314, - 1314, - 1317, - 1317, - 1317, - 1320, - 1320, - 1322, - 1322, - 1322, - 1325, - 1326, - 1326, - 1328, - 1328, - 1330, - 1330, - 1330, - 1333, - 1333, - 1335, - 1335, - 1337, - 1337, - 1339, - 1339, - 1341, - 1341, - 1341, - 1341, - 1345, - 1345, - 1345, - 1348, - 1348, - 1348, - 1351, - 1351, - 1351, - 1351, - 1355, - 1355, - 1355, - 1355, - 1359, - 1359, - 1359, - 1362, - 1362, - 1362, - 1365, - 1365, - 1365, - 1365, - 1369, - 1369, - 1371, - 1371, - 1371, - 1374, - 1374, - 1376, - 1376, - 1378, - 1378, - 1378, - 1381, - 1381, - 1381, - 1384, - 1384, - 1386, - 1387, - 1387, - 1387, - 1390, - 1390, - 1390, - 1393, - 1393, - 1395, - 1395, - 1395, - 1398, - 1398, - 1398, - 1401, - 1401, - 1401, - 1404, - 1404, - 1404, - 1407, - 1407, - 1407, - 1410, - 1410, - 1410, - 1413, - 1413, - 1413, - 1416, - 1416, - 1416, - 1419, - 1419, - 1419, - 1422, - 1422, - 1422, - 1425, - 1425, - 1425, - 1428, - 1428, - 1430, - 1430, - 1430, - 1433, - 1433, - 1433, - 1436, - 1436, - 1436, - 1439, - 1439, - 1439, - 1442, - 1442, - 1444, - 1444, - 1446, - 1446, - 1446, - 1449, - 1449, - 1449, - 1452, - 1452, - 1454, - 1454, - 1456, - 1456, - 1456, - 1459, - 1459, - 1459, - 1462, - 1462, - 1464, - 1464, - 1464, - 1467, - 1467, - 1469, - 1469, - 1469, - 1472, - 1472, - 1474, - 1474, - 1474, - 1474, - 1478, - 1478, - 1478, - 1481, - 1481, - 1483, - 1483, - 1483, - 1483, - 1487, - 1487, - 1489, - 1489, - 1489, - 1492, - 1492, - 1494, - 1494, - 1494, - 1497, - 1497, - 1499, - 1499, - 1501, - 1501, - 1501, - 1504, - 1504, - 1506, - 1506, - 1508, - 1508, - 1510, - 1510, - 1510, - 1513, - 1513, - 1513, - 1513, - 1517, - 1517, - 1519, - 1519, - 1519, - 1522, - 1522, - 1522, - 1522, - 1526, - 1526, - 1528, - 1528, - 1528, - 1531, - 1531, - 1531, - 1534, - 1534, - 1536, - 1536, - 1536, - 1539, - 1539, - 1539, - 1542, - 1542, - 1544, - 1544, - 1546, - 1546, - 1546, - 1549, - 1549, - 1549, - 1552, - 1552, - 1554, - 1554, - 1554, - 1557, - 1557, - 1559, - 1560, - 1561, - 1561, - 1563, - 1563, - 1565, - 1565, - 1567, - 1567, - 1567, - 1570, - 1570, - 1570, - 1573, - 1573, - 1575, - 1575, - 1577, - 1577, - 1577, - 1580, - 1580, - 1580, - 1583, - 1583, - 1583, - 1586, - 1586, - 1588, - 1588, - 1590, - 1590, - 1592, - 1592, - 1594, - 1594, - 1594, - 1597, - 1597, - 1597, - 1600, - 1600, - 1600, - 1603, - 1603, - 1603, - 1606, - 1606, - 1606, - 1609, - 1609, - 1609, - 1612, - 1612, - 1614, - 1615, - 1615, - 1615, - 1618, - 1618, - 1620, - 1620, - 1620, - 1623, - 1624, - 1624, - 1626, - 1626, - 1626, - 1629, - 1629, - 1631, - 1631, - 1633, - 1633, - 1635, - 1636, - 1637, - 1637, - 1637, - 1640, - 1640, - 1642, - 1642, - 1644, - 1644, - 1644, - 1647, - 1647, - 1647, - 1650, - 1650, - 1650, - 1653, - 1653, - 1653, - 1656, - 1656, - 1656, - 1659, - 1659, - 1659, - 1662, - 1663, - 1663, - 1665, - 1665, - 1665, - 1668, - 1668, - 1670, - 1670, - 1672, - 1672, - 1674, - 1674, - 1676, - 1676, - 1678, - 1678, - 1680, - 1680, - 1682, - 1682, - 1684, - 1684, - 1686, - 1686, - 1688, - 1688, - 1690, - 1691, - 1692, - 1692, - 1694, - 1695, - 1695, - 1697, - 1697, - 1697, - 1700, - 1700, - 1700, - 1703, - 1703, - 1705, - 1705, - 1707, - 1707, - 1707, - 1710, - 1710, - 1710, - 1713, - 1713, - 1713, - 1716, - 1716, - 1716, - 1719, - 1719, - 1719, - 1719, - 1723, - 1724, - 1725, - 1725, - 1725, - 1725, - 1729, - 1729, - 1731, - 1731, - 1733, - 1734, - 1734, - 1736, - 1737, - 1738, - 1739, - 1739, - 1741, - 1742, - 1742, - 1744, - 1745, - 1745, - 1747, - 1747, - 1749, - 1749, - 1751, - 1751, - 1753, - 1753, - 1755, - 1755, - 1755, - 1758, - 1758, - 1760, - 1760, - 1760, - 1763, - 1763, - 1765, - 1765, - 1767, - 1767, - 1769, - 1770, - 1770, - 1772, - 1772, - 1772, - 1775, - 1775, - 1777, - 1777, - 1779, - 1780, - 1781, - 1781, - 1783, - 1784, - 1785, - 1785, - 1787, - 1787, - 1789, - 1789, - 1789, - 1792, - 1792, - 1794, - 1794, - 1794, - 1797, - 1797, - 1799, - 1799, - 1801, - 1801, - 1801, - 1804, - 1804, - 1804, - 1807, - 1807, - 1807, - 1810, - 1810, - 1812, - 1812, - 1814, - 1814, - 1816, - 1816, - 1816, - 1819, - 1819, - 1819, - 1822, - 1822, - 1822, - 1825, - 1825, - 1825, - 1828, - 1828, - 1828, - 1831, - 1831, - 1833, - 1834, - 1834, - 1834, - 1837, - 1837, - 1839, - 1839, - 1839, - 1842, - 1842, - 1842, - 1845, - 1845, - 1845, - 1848, - 1848, - 1848, - 1851, - 1851, - 1853, - 1853, - 1853, - 1856, - 1856, - 1856, - 1859, - 1859, - 1859, - 1862, - 1862, - 1862, - 1865, - 1865, - 1867, - 1867, - 1869, - 1869, - 1871, - 1871, - 1871, - 1874, - 1874, - 1874, - 1877, - 1877, - 1877, - 1877, - 1881, - 1882, - 1882, - 1884, - 1884, - 1884, - 1887, - 1887, - 1889, - 1889, - 1889, - 1892, - 1892, - 1894, - 1894, - 1896, - 1896, - 1898, - 1898, - 1898, - 1901, - 1901, - 1901, - 1904, - 1904, - 1906, - 1906, - 1906, - 1909, - 1910, - 1910, - 1912, - 1912, - 1914, - 1914, - 1914, - 1917, - 1917, - 1919, - 1919, - 1919, - 1922, - 1922, - 1922, - 1925, - 1925, - 1925, - 1925, - 1929, - 1929, - 1931, - 1931, - 1931, - 1934, - 1934, - 1936, - 1937, - 1937, - 1939, - 1940, - 1940, - 1942, - 1942, - 1942, - 1942, - 1946, - 1946, - 1946, - 1949, - 1950, - 1950, - 1952, - 1952, - 1954, - 1954, - 1954, - 1954, - 1958, - 1959, - 1959, - 1961, - 1961, - 1963, - 1963, - 1965, - 1965, - 1967, - 1968, - 1969, - 1969, - 1969, - 1972, - 1972, - 1974, - 1974, - 1974, - 1974, - 1978, - 1979, - 1979, - 1981, - 1981, - 1981, - 1984, - 1984, - 1984, - 1984, - 1988, - 1988, - 1988, - 1988, - 1992, - 1992, - 1992, - 1995, - 1995, - 1995, - 1998, - 1998, - 1998, - 2001, - 2002, - 2003, - 2004, - 2005, - 2005, - 2007, - 2007, - 2009, - 2009, - 2011, - 2011, - 2013, - 2013, - 2013, - 2013, - 2017, - 2018, - 2018, - 2020, - 2020, - 2022, - 2022, - 2024, - 2024, - 2026, - 2026, - 2026, - 2029, - 2030, - 2030, - 2032, - 2032, - 2034, - 2034, - 2036, - 2036, - 2038, - 2039, - 2039, - 2041, - 2041, - 2043, - 2043, - 2043, - 2043, - 2047, - 2047, - 2049, - 2049, - 2051, - 2051, - 2051, - 2054, - 2054, - 2054, - 2057, - 2058, - 2058, - 2060, - 2060, - 2062, - 2063, - 2064, - 2065, - 2065, - 2065, - 2068, - 2068, - 2068, - 2068, - 2072, - 2073, - 2073, - 2075, - 2075, - 2077, - 2077, - 2079, - 2079, - 2081, - 2082, - 2082, - 2084, - 2084, - 2084, - 2084, - 2088, - 2088, - 2090, - 2090, - 2090, - 2093, - 2093, - 2093, - 2096, - 2096, - 2096, - 2099, - 2100, - 2100, - 2102, - 2102, - 2102, - 2105, - 2105, - 2105, - 2108, - 2109, - 2110, - 2111, - 2111, - 2113, - 2113, - 2115, - 2115, - 2115, - 2118, - 2118, - 2120, - 2120, - 2122, - 2122, - 2124, - 2124, - 2126, - 2127, - 2128, - 2129, - 2129, - 2131, - 2131, - 2133, - 2134, - 2134, - 2134, - 2137, - 2137, - 2139, - 2139, - 2139, - 2142, - 2142, - 2142, - 2145, - 2146, - 2146, - 2146, - 2149, - 2149, - 2149, - 2152, - 2152, - 2152, - 2155, - 2155, - 2155, - 2158, - 2158, - 2160, - 2160, - 2162, - 2162, - 2162, - 2165, - 2165, - 2165, - 2168, - 2168, - 2170, - 2170, - 2172, - 2172, - 2172, - 2175, - 2175, - 2177, - 2177, - 2179, - 2179, - 2179, - 2182, - 2182, - 2182, - 2182, - 2186, - 2186, - 2186, - 2189, - 2189, - 2191, - 2191, - 2193, - 2193, - 2195, - 2195, - 2197, - 2197, - 2197, - 2197, - 2201, - 2201, - 2201, - 2204, - 2204, - 2206, - 2206, - 2208, - 2208, - 2210, - 2210, - 2210, - 2210, - 2214, - 2215, - 2215, - 2215, - 2218, - 2218, - 2220, - 2220, - 2222, - 2223, - 2224, - 2224, - 2226, - 2226, - 2226, - 2229, - 2230, - 2230, - 2232, - 2232, - 2234, - 2234, - 2236, - 2237, - 2237, - 2239, - 2240, - 2240, - 2242, - 2242, - 2244, - 2244, - 2246, - 2247, - 2248, - 2248, - 2250, - 2250, - 2250, - 2250, - 2254, - 2254, - 2256, - 2257, - 2257, - 2257, - 2257, - 2261, - 2261, - 2263, - 2264, - 2264, - 2266, - 2266, - 2266, - 2269, - 2269, - 2271, - 2271, - 2273, - 2274, - 2274, - 2276, - 2276, - 2276, - 2279, - 2280, - 2281, - 2281, - 2283, - 2283, - 2285, - 2285, - 2287, - 2287, - 2289, - 2290, - 2290, - 2292, - 2292, - 2294, - 2294, - 2294, - 2294, - 2298, - 2299, - 2299, - 2301, - 2302, - 2302, - 2304, - 2304, - 2306, - 2306, - 2308, - 2309, - 2310, - 2310, - 2312, - 2312, - 2314, - 2315, - 2315, - 2315, - 2318, - 2318, - 2318, - 2321, - 2321, - 2323, - 2323, - 2323, - 2323, - 2327, - 2327, - 2329, - 2329, - 2331, - 2331, - 2333, - 2333, - 2335, - 2336, - 2336, - 2338, - 2339, - 2339, - 2341, - 2341, - 2341, - 2344, - 2344, - 2344, - 2344, - 2348, - 2348, - 2350, - 2350, - 2350, - 2350, - 2354, - 2354, - 2354, - 2357, - 2358, - 2358, - 2360, - 2361, - 2361, - 2363, - 2363, - 2363, - 2366, - 2366, - 2366, - 2369, - 2369, - 2371, - 2371, - 2373, - 2373, - 2375, - 2376, - 2376, - 2378, - 2378, - 2380, - 2381, - 2381, - 2383, - 2383, - 2383, - 2386, - 2386, - 2388, - 2388, - 2388, - 2391, - 2392, - 2393, - 2393, - 2395, - 2395, - 2397, - 2398, - 2399, - 2399, - 2401, - 2401, - 2401, - 2401, - 2405, - 2405, - 2407, - 2408, - 2408, - 2410, - 2411, - 2412, - 2412, - 2412, - 2415, - 2415, - 2417, - 2417, - 2417, - 2420, - 2420, - 2422, - 2423, - 2423, - 2425, - 2426, - 2426, - 2428, - 2429, - 2429, - 2429, - 2432, - 2432, - 2434, - 2434, - 2434, - 2437, - 2437, - 2439, - 2439, - 2441, - 2442, - 2442, - 2444, - 2444, - 2444, - 2447, - 2447, - 2449, - 2449, - 2449, - 2452, - 2453, - 2453, - 2455, - 2455, - 2457, - 2457, - 2457, - 2460, - 2460, - 2462, - 2462, - 2462, - 2465, - 2466, - 2467, - 2468, - 2469, - 2470, - 2470, - 2472, - 2472, - 2474, - 2475, - 2475, - 2477, - 2477, - 2477, - 2480, - 2480, - 2480, - 2483, - 2483, - 2485, - 2485, - 2487, - 2487, - 2489, - 2490, - 2490, - 2492, - 2492, - 2494, - 2495, - 2495, - 2497, - 2497, - 2497, - 2500, - 2500, - 2502, - 2502, - 2502, - 2505, - 2506, - 2507, - 2507, - 2509, - 2509, - 2511, - 2512, - 2513, - 2513, - 2513, - 2513, - 2517, - 2517, - 2517, - 2517, - 2521, - 2521, - 2523, - 2523, - 2523, - 2526, - 2526, - 2528, - 2528, - 2530, - 2530, - 2530, - 2533, - 2534, - 2534, - 2536, - 2536, - 2538, - 2538, - 2540, - 2540, - 2542, - 2542, - 2544, - 2544, - 2544, - 2544, - 2548, - 2548, - 2550, - 2550, - 2552, - 2552, - 2552, - 2555, - 2555, - 2555, - 2558, - 2558, - 2558, - 2561, - 2561, - 2561, - 2564, - 2564, - 2564, - 2567, - 2567, - 2567, - 2570, - 2570, - 2570, - 2573, - 2573, - 2573, - 2576, - 2576, - 2578, - 2578, - 2578, - 2581, - 2581, - 2581, - 2584, - 2584, - 2584, - 2587, - 2587, - 2587, - 2590, - 2590, - 2590, - 2593, - 2593, - 2593, - 2596, - 2596, - 2596, - 2599, - 2599, - 2599, - 2602, - 2602, - 2602, - 2605, - 2605, - 2605, - 2608, - 2608, - 2608, - 2611, - 2611, - 2611, - 2614, - 2614, - 2616, - 2616, - 2616, - 2619, - 2619, - 2619, - 2622, - 2622, - 2622, - 2625, - 2625, - 2625, - 2628, - 2628, - 2628, - 2631, - 2631, - 2631, - 2634, - 2634, - 2634, - 2637, - 2637, - 2637, - 2640, - 2640, - 2640, - 2643, - 2643, - 2643, - 2646, - 2646, - 2648, - 2648, - 2648, - 2651, - 2651, - 2651, - 2654, - 2654, - 2654, - 2657, - 2657, - 2657, - 2660, - 2660, - 2660, - 2663, - 2663, - 2663, - 2666, - 2666, - 2666, - 2669, - 2669, - 2669, - 2672, - 2672, - 2672, - 2675, - 2675, - 2675, - 2678, - 2678, - 2678, - 2681, - 2681, - 2681, - 2684, - 2684, - 2686, - 2686, - 2686, - 2689, - 2689, - 2689, - 2692, - 2692, - 2692, - 2695, - 2695, - 2695, - 2698, - 2698, - 2698, - 2701, - 2701, - 2701, - 2704, - 2704, - 2704, - 2707, - 2707, - 2707, - 2710, - 2710, - 2710, - 2713, - 2713, - 2713, - 2716, - 2716, - 2718, - 2718, - 2718, - 2721, - 2721, - 2721, - 2724, - 2724, - 2724, - 2727, - 2727, - 2727, - 2730, - 2730, - 2730, - 2733, - 2733, - 2733, - 2736, - 2736, - 2736, - 2739, - 2739, - 2739, - 2742, - 2742, - 2742, - 2745, - 2745, - 2745, - 2748, - 2748, - 2748, - 2751, - 2751, - 2751, - 2754, - 2754, - 2756, - 2756, - 2756, - 2759, - 2759, - 2759, - 2762, - 2762, - 2762, - 2765, - 2765, - 2765, - 2768, - 2768, - 2768, - 2771, - 2771, - 2771, - 2774, - 2774, - 2774, - 2777, - 2777, - 2777, - 2780, - 2780, - 2780, - 2783, - 2783, - 2783, - 2786, - 2786, - 2788, - 2788, - 2788, - 2791, - 2791, - 2791, - 2794, - 2794, - 2794, - 2797, - 2797, - 2797, - 2800, - 2800, - 2800, - 2803, - 2803, - 2803, - 2806, - 2806, - 2806, - 2809, - 2809, - 2809, - 2812, - 2812, - 2812, - 2815, - 2815, - 2815, - 2818, - 2818, - 2818, - 2821, - 2821, - 2821, - 2824, - 2824, - 2826, - 2826, - 2826, - 2829, - 2829, - 2829, - 2832, - 2832, - 2834, - 2835, - 2835, - 2837, - 2838, - 2838, - 2840, - 2841, - 2841, - 2843, - 2844, - 2844, - 2846, - 2847, - 2847, - 2849, - 2850, - 2851, - 2852, - 2853, - 2853, - 2855, - 2856, - 2856, - 2858, - 2859, - 2859, - 2861, - 2861, - 2863, - 2863, - 2865, - 2866, - 2866, - 2868, - 2868, - 2870, - 2871, - 2871, - 2873, - 2874, - 2874, - 2876, - 2877, - 2877, - 2879, - 2880, - 2880, - 2882, - 2883, - 2883, - 2885, - 2886, - 2887, - 2888, - 2889, - 2889, - 2891, - 2892, - 2892, - 2894, - 2895, - 2895, - 2897, - 2897, - 2899, - 2899, - 2901, - 2902, - 2902, - 2904, - 2904, - 2906, - 2906, - 2908, - 2908, - 2910, - 2910, - 2912, - 2912, - 2912, - 2915, - 2915, - 2915, - 2918, - 2918, - 2920, - 2920, - 2922, - 2922, - 2922, - 2925, - 2925, - 2925, - 2928, - 2928, - 2928, - 2931, - 2931, - 2933, - 2933, - 2935, - 2935, - 2935, - 2938, - 2938, - 2938, - 2941, - 2941, - 2941, - 2944, - 2944, - 2946, - 2946, - 2948, - 2948, - 2950, - 2950, - 2952, - 2953, - 2953, - 2953, - 2956, - 2956, - 2956, - 2959, - 2959, - 2959, - 2962, - 2962, - 2962, - 2965, - 2965, - 2965, - 2968, - 2968, - 2968, - 2971, - 2971, - 2971, - 2974, - 2974, - 2974, - 2977, - 2977, - 2977, - 2980, - 2980, - 2980, - 2983, - 2983, - 2983, - 2986, - 2986, - 2986, - 2989, - 2990, - 2991, - 2991, - 2991, - 2994, - 2994, - 2994, - 2997, - 2997, - 2997, - 3000, - 3000, - 3000, - 3003, - 3003, - 3003, - 3006, - 3006, - 3006, - 3009, - 3009, - 3009, - 3012, - 3012, - 3012, - 3015, - 3015, - 3015, - 3018, - 3018, - 3018, - 3021, - 3021, - 3021, - 3024, - 3024, - 3024, - 3027, - 3028, - 3029, - 3030, - 3031, - 3032, - 3033, - 3034, - 3035, - 3036, - 3037, - 3038, - 3039, - 3040, - 3041, - 3042, - 3043, - 3044, - 3045, - 3046, - 3047, - 3048, - 3049, - 3050, - 3051, - 3052, - 3053, - 3054, - 3054, - 3056, - 3056, - 3056, - 3059, - 3060, - 3060, - 3062, - 3062, - 3064, - 3064, - 3064, - 3067, - 3067, - 3069, - 3069, - 3071, - 3071, - 3071, - 3074, - 3074, - 3074, - 3074, - 3078, - 3078, - 3078, - 3078, - 3082, - 3082, - 3084, - 3084, - 3084, - 3087, - 3087, - 3089, - 3089, - 3091, - 3091, - 3093, - 3094, - 3094, - 3096, - 3097, - 3097, - 3099, - 3099, - 3099, - 3102, - 3102, - 3104, - 3104, - 3106, - 3106, - 3108, - 3108, - 3110, - 3111, - 3112, - 3112, - 3112, - 3115, - 3115, - 3117, - 3117, - 3119, - 3119, - 3121, - 3121, - 3121, - 3124, - 3124, - 3126, - 3126, - 3126, - 3129, - 3129, - 3129, - 3129, - 3133, - 3133, - 3133, - 3136, - 3136, - 3138, - 3138, - 3138, - 3141, - 3141, - 3143, - 3143, - 3143, - 3146, - 3146, - 3148, - 3148, - 3150, - 3150, - 3150, - 3153, - 3153, - 3153, - 3156, - 3156, - 3156, - 3159, - 3159, - 3161, - 3161, - 3163, - 3163, - 3163, - 3163, - 3167, - 3167, - 3167, - 3170, - 3170, - 3172, - 3172, - 3172, - 3175, - 3176, - 3176, - 3178, - 3178, - 3178, - 3181, - 3181, - 3181, - 3184, - 3185, - 3185, - 3187, - 3188, - 3188, - 3188, - 3188, - 3192, - 3192, - 3194, - 3194, - 3194, - 3197, - 3197, - 3197, - 3197, - 3201, - 3202, - 3202, - 3202, - 3202, - 3206, - 3206, - 3208, - 3208, - 3210, - 3210, - 3212, - 3213, - 3214, - 3214, - 3216, - 3217, - 3218, - 3218, - 3220, - 3221, - 3222, - 3223, - 3224, - 3224, - 3224, - 3227, - 3227, - 3227, - 3227, - 3231, - 3231, - 3233, - 3233, - 3235, - 3236, - 3236, - 3238, - 3239, - 3240, - 3240, - 3240, - 3243, - 3243, - 3243, - 3246, - 3246, - 3246, - 3249, - 3250, - 3250, - 3252, - 3252, - 3254, - 3254, - 3256, - 3256, - 3258, - 3258, - 3260, - 3260, - 3262, - 3262, - 3262, - 3265, - 3265, - 3265, - 3268, - 3268, - 3268, - 3271, - 3271, - 3273, - 3273, - 3273, - 3276, - 3276, - 3276, - 3279, - 3279, - 3279, - 3282, - 3283, - 3283, - 3285, - 3285, - 3287, - 3287, - 3287, - 3290, - 3290, - 3290, - 3293, - 3293, - 3293, - 3296, - 3296, - 3296, - 3296, - 3300, - 3300, - 3302, - 3302, - 3302, - 3305, - 3305, - 3305, - 3308, - 3308, - 3310, - 3310, - 3312, - 3312, - 3314, - 3314, - 3316, - 3316, - 3318, - 3318, - 3320, - 3320, - 3320, - 3320, - 3324, - 3324, - 3326, - 3326, - 3326, - 3329, - 3329, - 3331, - 3331, - 3333, - 3333, - 3333, - 3336, - 3336, - 3336, - 3339, - 3339, - 3341, - 3341, - 3343, - 3343, - 3345, - 3345, - 3347, - 3347, - 3349, - 3349, - 3351, - 3352, - 3353, - 3354, - 3354, - 3354, - 3357, - 3357, - 3359, - 3359, - 3361, - 3361, - 3363, - 3363, - 3363, - 3363, - 3367, - 3367, - 3369, - 3369, - 3369, - 3372, - 3372, - 3372, - 3372, - 3376, - 3377, - 3377, - 3379, - 3379, - 3379, - 3382, - 3382, - 3384, - 3384, - 3386, - 3387, - 3388, - 3388, - 3390, - 3390, - 3390, - 3393, - 3393, - 3395, - 3395, - 3395, - 3398, - 3398, - 3400, - 3400, - 3400, - 3403, - 3403, - 3403, - 3406, - 3406, - 3408, - 3408, - 3408, - 3411, - 3411, - 3411, - 3414, - 3415, - 3415, - 3417, - 3417, - 3419, - 3419, - 3421, - 3421, - 3421, - 3424, - 3424, - 3426, - 3426, - 3428, - 3428, - 3430, - 3430, - 3430, - 3433, - 3433, - 3435, - 3435, - 3437, - 3437, - 3439, - 3440, - 3440, - 3442, - 3442, - 3442, - 3442, - 3446, - 3446, - 3446, - 3446, - 3450, - 3450, - 3452, - 3452, - 3454, - 3455, - 3455, - 3455, - 3458, - 3458, - 3460, - 3461, - 3461, - 3463, - 3463, - 3465, - 3465, - 3465, - 3468, - 3468, - 3470, - 3471, - 3471, - 3473, - 3473, - 3473, - 3476, - 3476, - 3476, - 3479, - 3480, - 3480, - 3482, - 3482, - 3482, - 3485, - 3485, - 3485, - 3488, - 3488, - 3490, - 3491, - 3491, - 3493, - 3493, - 3495, - 3496, - 3496, - 3498, - 3498, - 3500, - 3500, - 3500, - 3503, - 3503, - 3503, - 3506, - 3506, - 3508, - 3508, - 3510, - 3511, - 3511, - 3511, - 3514, - 3514, - 3514, - 3517, - 3517, - 3517, - 3520, - 3521, - 3521, - 3523, - 3523, - 3525, - 3526, - 3526, - 3526, - 3529, - 3529, - 3529, - 3532, - 3532, - 3534, - 3534, - 3534, - 3537, - 3537, - 3539, - 3539, - 3539, - 3542, - 3542, - 3544, - 3544, - 3544, - 3547, - 3547, - 3549, - 3550, - 3550, - 3550, - 3553, - 3553, - 3553, - 3553, - 3557, - 3557, - 3559, - 3559, - 3559, - 3562, - 3562, - 3562, - 3565, - 3565, - 3565, - 3568, - 3568, - 3568, - 3571, - 3571, - 3573, - 3573, - 3573, - 3576, - 3576, - 3576, - 3579, - 3579, - 3579, - 3582, - 3582, - 3582, - 3585, - 3585, - 3585, - 3588, - 3588, - 3588, - 3591, - 3591, - 3593, - 3594, - 3594, - 3596, - 3597, - 3597, - 3597, - 3600, - 3600, - 3602, - 3602, - 3604, - 3604, - 3606, - 3606, - 3608, - 3609, - 3609, - 3611, - 3611, - 3611, - 3614, - 3614, - 3616, - 3616, - 3616, - 3619, - 3619, - 3621, - 3621, - 3621, - 3621, - 3625, - 3625, - 3627, - 3627, - 3627, - 3630, - 3630, - 3630, - 3633, - 3633, - 3633, - 3636, - 3636, - 3636, - 3639, - 3639, - 3641, - 3641, - 3641, - 3644, - 3644, - 3644, - 3647, - 3647, - 3647, - 3650, - 3650, - 3650, - 3653, - 3653, - 3653, - 3656, - 3656, - 3656, - 3659, - 3659, - 3661, - 3661, - 3663, - 3663, - 3665, - 3665, - 3665, - 3668, - 3669, - 3670, - 3670, - 3672, - 3672, - 3674, - 3674, - 3676, - 3676, - 3676, - 3679, - 3679, - 3679, - 3682, - 3682, - 3682, - 3685, - 3686, - 3686, - 3688, - 3689, - 3690, - 3690, - 3692, - 3692, - 3692, - 3695, - 3696, - 3696, - 3696, - 3699, - 3699, - 3699, - 3702, - 3702, - 3704, - 3705, - 3705, - 3707, - 3707, - 3707, - 3707, - 3711, - 3711, - 3713, - 3714, - 3714, - 3714, - 3717, - 3717, - 3717, - 3717, - 3721, - 3721, - 3721, - 3724, - 3724, - 3726, - 3726, - 3726, - 3729, - 3729, - 3729, - 3729, - 3733, - 3733, - 3735, - 3736, - 3736, - 3738, - 3738, - 3738, - 3741, - 3741, - 3741, - 3741, - 3745, - 3745, - 3745, - 3745, - 3749, - 3749, - 3749, - 3752, - 3752, - 3752, - 3755, - 3755, - 3757, - 3757, - 3759, - 3759, - 3761, - 3761, - 3761, - 3764, - 3765, - 3765, - 3765, - 3768, - 3768, - 3768, - 3771, - 3771, - 3771, - 3774, - 3774, - 3774, - 3777, - 3777, - 3777, - 3780, - 3780, - 3780, - 3783, - 3783, - 3783, - 3786, - 3786, - 3786, - 3789, - 3789, - 3791, - 3791, - 3791, - 3794, - 3794, - 3794, - 3797, - 3797, - 3799, - 3799, - 3801, - 3801, - 3803, - 3803, - 3805, - 3805, - 3805, - 3808, - 3808, - 3808, - 3811, - 3811, - 3813, - 3813, - 3815, - 3815, - 3817, - 3817, - 3819, - 3820, - 3821, - 3821, - 3821, - 3821, - 3825, - 3825, - 3827, - 3827, - 3829, - 3829, - 3831, - 3832, - 3832, - 3834, - 3834, - 3836, - 3836, - 3836, - 3836, - 3840, - 3840, - 3842, - 3842, - 3844, - 3844, - 3846, - 3846, - 3848, - 3848, - 3850, - 3851, - 3851, - 3853, - 3853, - 3855, - 3855, - 3855, - 3858, - 3858, - 3858, - 3861, - 3861, - 3861, - 3864, - 3864, - 3866, - 3866, - 3866, - 3869, - 3869, - 3871, - 3871, - 3873, - 3873, - 3875, - 3875, - 3877, - 3877, - 3879, - 3879, - 3879, - 3882, - 3882, - 3884, - 3884, - 3886, - 3886, - 3886, - 3886, - 3890, - 3890, - 3890, - 3893, - 3893, - 3895, - 3896, - 3896, - 3898, - 3898, - 3900, - 3900, - 3900, - 3903, - 3903, - 3903, - 3906, - 3907, - 3907, - 3907, - 3910, - 3910, - 3910, - 3913, - 3913, - 3913, - 3916, - 3916, - 3916, - 3919, - 3919, - 3919, - 3922, - 3922, - 3922, - 3925, - 3925, - 3925, - 3928, - 3928, - 3930, - 3930, - 3930, - 3933, - 3933, - 3935, - 3935, - 3935, - 3938, - 3938, - 3938, - 3941, - 3941, - 3941, - 3944, - 3945, - 3945, - 3947, - 3947, - 3949, - 3950, - 3950, - 3952, - 3953, - 3954, - 3954, - 3954, - 3957, - 3957, - 3959, - 3959, - 3959, - 3959, - 3963, - 3963, - 3963, - 3966, - 3967, - 3967, - 3969, - 3969, - 3969, - 3972, - 3972, - 3974, - 3974, - 3976, - 3976, - 3978, - 3978, - 3980, - 3980, - 3980, - 3983, - 3983, - 3983, - 3986, - 3986, - 3986, - 3989, - 3990, - 3990, - 3992, - 3993, - 3993, - 3995, - 3995, - 3995, - 3998, - 3999, - 3999, - 3999, - 4002, - 4002, - 4002, - 4005, - 4005, - 4005, - 4008, - 4008, - 4008, - 4011, - 4011, - 4013, - 4013, - 4013, - 4016, - 4016, - 4016, - 4019, - 4020, - 4021, - 4021, - 4021, - 4024, - 4024, - 4026, - 4027, - 4027, - 4027, - 4030, - 4030, - 4030, - 4033, - 4033, - 4033, - 4036, - 4036, - 4036, - 4039, - 4039, - 4041, - 4041, - 4043, - 4043, - 4043, - 4046, - 4046, - 4046, - 4049, - 4049, - 4051, - 4051, - 4053, - 4053, - 4055, - 4055, - 4055, - 4058, - 4058, - 4058, - 4061, - 4061, - 4063, - 4063, - 4065, - 4065, - 4065, - 4065, - 4069, - 4070, - 4070, - 4070, - 4073, - 4073, - 4075, - 4075, - 4077, - 4078, - 4078, - 4080, - 4080, - 4082, - 4082, - 4082, - 4082, - 4086, - 4086, - 4088, - 4089, - 4089, - 4089, - 4092, - 4092, - 4094, - 4094, - 4096, - 4096, - 4098, - 4098, - 4098, - 4098, - 4102, - 4102, - 4102, - 4102, - 4106, - 4106, - 4108, - 4108, - 4108, - 4111, - 4111, - 4111, - 4114, - 4114, - 4116, - 4116, - 4118, - 4118, - 4120, - 4120, - 4122, - 4122, - 4124, - 4124, - 4126, - 4127, - 4127, - 4129, - 4129, - 4131, - 4132, - 4132, - 4134, - 4135, - 4136, - 4136, - 4138, - 4138, - 4140, - 4140, - 4140, - 4140, - 4144, - 4144, - 4146, - 4146, - 4146, - 4146, - 4150, - 4151, - 4152, - 4153, - 4154, - 4154, - 4156, - 4156, - 4156, - 4156, - 4160, - 4160, - 4160, - 4163, - 4163, - 4163, - 4166, - 4166, - 4168, - 4168, - 4168, - 4171, - 4171, - 4173, - 4173, - 4173, - 4173, - 4177, - 4178, - 4178, - 4180, - 4180, - 4182, - 4183, - 4184, - 4185, - 4186, - 4186, - 4188, - 4188, - 4188, - 4191, - 4191, - 4193, - 4193, - 4193, - 4193, - 4197, - 4197, - 4199, - 4200, - 4200, - 4200, - 4203, - 4203, - 4205, - 4205, - 4205, - 4208, - 4208, - 4208, - 4211, - 4211, - 4213, - 4213, - 4215, - 4215, - 4215, - 4218, - 4218, - 4218, - 4221, - 4222, - 4222, - 4224, - 4224, - 4226, - 4226, - 4226, - 4229, - 4230, - 4231, - 4231, - 4233, - 4233, - 4235, - 4235, - 4235, - 4238, - 4238, - 4240, - 4240, - 4240, - 4243, - 4243, - 4245, - 4245, - 4247, - 4247, - 4247, - 4250, - 4250, - 4250, - 4253, - 4253, - 4255, - 4255, - 4255, - 4258, - 4259, - 4259, - 4261, - 4261, - 4263, - 4263, - 4263, - 4266, - 4266, - 4268, - 4268, - 4270, - 4270, - 4272, - 4272, - 4274, - 4274, - 4274, - 4274, - 4278, - 4278, - 4278, - 4281, - 4281, - 4281, - 4284, - 4284, - 4284, - 4284, - 4288, - 4288, - 4288, - 4288, - 4292, - 4292, - 4292, - 4295, - 4295, - 4295, - 4298, - 4298, - 4298, - 4298, - 4302, - 4302, - 4304, - 4304, - 4304, - 4307, - 4307, - 4309, - 4309, - 4311, - 4311, - 4311, - 4314, - 4314, - 4314, - 4317, - 4317, - 4319, - 4320, - 4320, - 4320, - 4323, - 4323, - 4323, - 4326, - 4326, - 4328, - 4328, - 4328, - 4331, - 4331, - 4331, - 4334, - 4334, - 4334, - 4337, - 4337, - 4337, - 4340, - 4340, - 4340, - 4343, - 4343, - 4343, - 4346, - 4346, - 4346, - 4349, - 4349, - 4349, - 4352, - 4352, - 4352, - 4355, - 4355, - 4355, - 4358, - 4358, - 4358, - 4361, - 4361, - 4363, - 4363, - 4363, - 4366, - 4366, - 4366, - 4369, - 4369, - 4369, - 4372, - 4372, - 4372, - 4375, - 4375, - 4377, - 4377, - 4379, - 4379, - 4379, - 4382, - 4382, - 4382, - 4385, - 4385, - 4387, - 4387, - 4389, - 4389, - 4389, - 4392, - 4392, - 4392, - 4395, - 4395, - 4397, - 4397, - 4397, - 4400, - 4400, - 4402, - 4402, - 4402, - 4405, - 4405, - 4407, - 4407, - 4407, - 4407, - 4411, - 4411, - 4411, - 4414, - 4414, - 4416, - 4416, - 4416, - 4416, - 4420, - 4420, - 4422, - 4422, - 4422, - 4425, - 4425, - 4427, - 4427, - 4427, - 4430, - 4430, - 4432, - 4432, - 4434, - 4434, - 4434, - 4437, - 4437, - 4439, - 4439, - 4441, - 4441, - 4443, - 4443, - 4443, - 4446, - 4446, - 4446, - 4446, - 4450, - 4450, - 4452, - 4452, - 4452, - 4455, - 4455, - 4455, - 4455, - 4459, - 4459, - 4461, - 4461, - 4461, - 4464, - 4464, - 4464, - 4467, - 4467, - 4469, - 4469, - 4469, - 4472, - 4472, - 4472, - 4475, - 4475, - 4477, - 4477, - 4479, - 4479, - 4479, - 4482, - 4482, - 4482, - 4485, - 4485, - 4487, - 4487, - 4487, - 4490, - 4490, - 4492, - 4493, - 4494, - 4494, - 4496, - 4496, - 4498, - 4498, - 4500, - 4500, - 4500, - 4503, - 4503, - 4503, - 4506, - 4506, - 4508, - 4508, - 4510, - 4510, - 4510, - 4513, - 4513, - 4513, - 4516, - 4516, - 4516, - 4519, - 4519, - 4521, - 4521, - 4523, - 4523, - 4525, - 4525, - 4527, - 4527, - 4527, - 4530, - 4530, - 4530, - 4533, - 4533, - 4533, - 4536, - 4536, - 4536, - 4539, - 4539, - 4539, - 4542, - 4542, - 4542, - 4545, - 4545, - 4547, - 4548, - 4548, - 4548, - 4551, - 4551, - 4553, - 4553, - 4553, - 4556, - 4557, - 4557, - 4559, - 4559, - 4559, - 4562, - 4562, - 4564, - 4564, - 4566, - 4566, - 4568, - 4569, - 4570, - 4570, - 4570, - 4573, - 4573, - 4575, - 4575, - 4577, - 4577, - 4577, - 4580, - 4580, - 4580, - 4583, - 4583, - 4583, - 4586, - 4586, - 4586, - 4589, - 4589, - 4589, - 4592, - 4592, - 4592, - 4595, - 4596, - 4596, - 4598, - 4598, - 4598, - 4601, - 4601, - 4603, - 4603, - 4605, - 4605, - 4607, - 4607, - 4609, - 4609, - 4611, - 4611, - 4613, - 4613, - 4615, - 4615, - 4617, - 4617, - 4619, - 4619, - 4621, - 4621, - 4623, - 4624, - 4625, - 4625, - 4627, - 4628, - 4628, - 4630, - 4630, - 4630, - 4633, - 4633, - 4633, - 4636, - 4636, - 4638, - 4638, - 4640, - 4640, - 4640, - 4643, - 4643, - 4643, - 4646, - 4646, - 4646, - 4649, - 4649, - 4649, - 4652, - 4652, - 4652, - 4652, - 4656, - 4657, - 4658, - 4658, - 4658, - 4658, - 4662, - 4662, - 4664, - 4664, - 4666, - 4667, - 4667, - 4669, - 4670, - 4671, - 4672, - 4672, - 4674, - 4675, - 4675, - 4677, - 4678, - 4678, - 4680, - 4680, - 4682, - 4682, - 4684, - 4684, - 4686, - 4686, - 4688, - 4688, - 4688, - 4691, - 4691, - 4693, - 4693, - 4693, - 4696, - 4696, - 4698, - 4698, - 4700, - 4700, - 4700, - 4703, - 4703, - 4705, - 4705, - 4707, - 4708, - 4708, - 4710, - 4711, - 4711, - 4713, - 4713, - 4715, - 4715, - 4715, - 4718, - 4718, - 4720, - 4720, - 4720, - 4723, - 4723, - 4723, - 4726, - 4726, - 4726, - 4729, - 4729, - 4729, - 4732, - 4732, - 4734, - 4734, - 4736, - 4736, - 4738, - 4738, - 4738, - 4741, - 4741, - 4741, - 4744, - 4744, - 4744, - 4747, - 4747, - 4747, - 4750, - 4750, - 4750, - 4753, - 4753, - 4755, - 4756, - 4756, - 4756, - 4759, - 4759, - 4761, - 4761, - 4761, - 4764, - 4764, - 4764, - 4767, - 4767, - 4767, - 4770, - 4770, - 4770, - 4773, - 4773, - 4775, - 4775, - 4775, - 4778, - 4778, - 4778, - 4781, - 4781, - 4781, - 4784, - 4784, - 4784, - 4787, - 4787, - 4789, - 4789, - 4791, - 4791, - 4793, - 4793, - 4793, - 4796, - 4796, - 4796, - 4799, - 4799, - 4799, - 4799, - 4803, - 4803, - 4805, - 4805, - 4805, - 4808, - 4808, - 4808, - 4811, - 4811, - 4813, - 4813, - 4815, - 4815, - 4815, - 4818, - 4818, - 4818, - 4821, - 4821, - 4823, - 4823, - 4823, - 4826, - 4827, - 4827, - 4829, - 4829, - 4831, - 4831, - 4831, - 4834, - 4834, - 4834, - 4837, - 4837, - 4837, - 4840, - 4840, - 4840, - 4840, - 4844, - 4844, - 4844, - 4847, - 4848, - 4848, - 4850, - 4851, - 4851, - 4853, - 4853, - 4853, - 4853, - 4857, - 4857, - 4857, - 4860, - 4861, - 4861, - 4863, - 4863, - 4865, - 4865, - 4865, - 4865, - 4869, - 4869, - 4871, - 4871, - 4873, - 4873, - 4875, - 4876, - 4876, - 4876, - 4879, - 4879, - 4881, - 4881, - 4881, - 4881, - 4885, - 4886, - 4886, - 4888, - 4888, - 4888, - 4891, - 4891, - 4891, - 4891, - 4895, - 4895, - 4895, - 4895, - 4899, - 4899, - 4899, - 4902, - 4902, - 4902, - 4905, - 4905, - 4905, - 4908, - 4909, - 4910, - 4911, - 4912, - 4912, - 4914, - 4914, - 4916, - 4916, - 4918, - 4918, - 4920, - 4920, - 4920, - 4920, - 4924, - 4925, - 4925, - 4927, - 4927, - 4929, - 4929, - 4931, - 4931, - 4933, - 4933, - 4933, - 4936, - 4937, - 4937, - 4939, - 4939, - 4941, - 4941, - 4943, - 4943, - 4945, - 4946, - 4946, - 4948, - 4948, - 4950, - 4950, - 4950, - 4950, - 4954, - 4954, - 4956, - 4956, - 4958, - 4958, - 4958, - 4961, - 4961, - 4961, - 4964, - 4965, - 4965, - 4967, - 4967, - 4969, - 4970, - 4971, - 4972, - 4972, - 4972, - 4975, - 4975, - 4975, - 4975, - 4979, - 4980, - 4980, - 4982, - 4982, - 4984, - 4984, - 4986, - 4986, - 4988, - 4989, - 4989, - 4991, - 4991, - 4991, - 4991, - 4995, - 4995, - 4997, - 4997, - 4997, - 5000, - 5000, - 5000, - 5003, - 5003, - 5003, - 5006, - 5007, - 5007, - 5009, - 5009, - 5009, - 5012, - 5012, - 5012, - 5015, - 5016, - 5017, - 5017, - 5019, - 5019, - 5019, - 5022, - 5022, - 5024, - 5024, - 5026, - 5026, - 5028, - 5028, - 5030, - 5031, - 5032, - 5033, - 5033, - 5035, - 5035, - 5037, - 5038, - 5038, - 5038, - 5041, - 5041, - 5043, - 5043, - 5043, - 5046, - 5046, - 5046, - 5049, - 5050, - 5050, - 5050, - 5053, - 5053, - 5053, - 5056, - 5056, - 5056, - 5059, - 5059, - 5059, - 5062, - 5062, - 5064, - 5064, - 5066, - 5066, - 5066, - 5069, - 5069, - 5069, - 5072, - 5072, - 5074, - 5074, - 5076, - 5076, - 5076, - 5079, - 5079, - 5081, - 5081, - 5083, - 5083, - 5083, - 5086, - 5086, - 5086, - 5086, - 5090, - 5090, - 5090, - 5093, - 5093, - 5095, - 5095, - 5097, - 5097, - 5099, - 5099, - 5101, - 5101, - 5101, - 5101, - 5105, - 5105, - 5105, - 5108, - 5108, - 5110, - 5110, - 5112, - 5112, - 5114, - 5114, - 5114, - 5114, - 5118, - 5119, - 5119, - 5119, - 5122, - 5122, - 5124, - 5124, - 5126, - 5127, - 5127, - 5127, - 5130, - 5130, - 5132, - 5132, - 5134, - 5134, - 5136, - 5137, - 5137, - 5139, - 5140, - 5140, - 5142, - 5142, - 5144, - 5144, - 5146, - 5146, - 5148, - 5148, - 5148, - 5148, - 5152, - 5152, - 5154, - 5154, - 5154, - 5154, - 5158, - 5158, - 5160, - 5160, - 5162, - 5162, - 5162, - 5165, - 5165, - 5167, - 5167, - 5169, - 5170, - 5170, - 5172, - 5172, - 5172, - 5175, - 5176, - 5177, - 5177, - 5179, - 5179, - 5181, - 5181, - 5183, - 5183, - 5185, - 5186, - 5186, - 5188, - 5188, - 5190, - 5190, - 5190, - 5190, - 5194, - 5195, - 5195, - 5197, - 5198, - 5198, - 5200, - 5200, - 5202, - 5202, - 5204, - 5205, - 5206, - 5206, - 5208, - 5208, - 5210, - 5211, - 5211, - 5211, - 5214, - 5214, - 5214, - 5217, - 5217, - 5219, - 5219, - 5219, - 5219, - 5223, - 5223, - 5225, - 5225, - 5227, - 5227, - 5229, - 5230, - 5230, - 5232, - 5232, - 5232, - 5235, - 5235, - 5235, - 5235, - 5239, - 5239, - 5241, - 5241, - 5241, - 5241, - 5245, - 5245, - 5245, - 5248, - 5249, - 5249, - 5251, - 5252, - 5252, - 5254, - 5254, - 5254, - 5257, - 5257, - 5257, - 5260, - 5260, - 5262, - 5263, - 5263, - 5265, - 5265, - 5267, - 5267, - 5267, - 5270, - 5270, - 5272, - 5272, - 5272, - 5275, - 5276, - 5276, - 5278, - 5278, - 5280, - 5280, - 5280, - 5280, - 5284, - 5284, - 5286, - 5287, - 5287, - 5289, - 5290, - 5291, - 5291, - 5291, - 5294, - 5294, - 5296, - 5296, - 5296, - 5299, - 5299, - 5301, - 5302, - 5302, - 5304, - 5305, - 5305, - 5307, - 5308, - 5308, - 5308, - 5311, - 5311, - 5313, - 5313, - 5313, - 5316, - 5316, - 5318, - 5318, - 5320, - 5321, - 5321, - 5323, - 5323, - 5323, - 5326, - 5326, - 5328, - 5328, - 5328, - 5331, - 5332, - 5332, - 5334, - 5334, - 5336, - 5336, - 5336, - 5339, - 5339, - 5341, - 5341, - 5341, - 5344, - 5345, - 5345, - 5347, - 5347, - 5349, - 5350, - 5350, - 5352, - 5352, - 5352, - 5355, - 5355, - 5355, - 5358, - 5358, - 5360, - 5361, - 5361, - 5363, - 5363, - 5365, - 5365, - 5365, - 5368, - 5368, - 5370, - 5370, - 5370, - 5373, - 5374, - 5374, - 5376, - 5376, - 5376, - 5376, - 5380, - 5380, - 5380, - 5380, - 5384, - 5384, - 5386, - 5386, - 5386, - 5389, - 5389, - 5391, - 5391, - 5393, - 5393, - 5393, - 5396, - 5397, - 5397, - 5399, - 5399, - 5401, - 5401, - 5403, - 5403, - 5405, - 5405, - 5407, - 5407, - 5407, - 5407, - 5411, - 5411, - 5413, - 5413, - 5415, - 5415, - 5415, - 5418, - 5418, - 5418, - 5421, - 5421, - 5421, - 5424, - 5424, - 5424, - 5427, - 5427, - 5427, - 5430, - 5430, - 5430, - 5433, - 5433, - 5433, - 5436, - 5436, - 5436, - 5439, - 5439, - 5441, - 5441, - 5441, - 5444, - 5444, - 5444, - 5447, - 5447, - 5447, - 5450, - 5450, - 5450, - 5453, - 5453, - 5453, - 5456, - 5456, - 5456, - 5459, - 5459, - 5459, - 5462, - 5462, - 5462, - 5465, - 5465, - 5465, - 5468, - 5468, - 5468, - 5471, - 5471, - 5471, - 5474, - 5474, - 5474, - 5477, - 5477, - 5479, - 5479, - 5479, - 5482, - 5482, - 5482, - 5485, - 5485, - 5485, - 5488, - 5488, - 5488, - 5491, - 5491, - 5491, - 5494, - 5494, - 5494, - 5497, - 5497, - 5497, - 5500, - 5500, - 5500, - 5503, - 5503, - 5503, - 5506, - 5506, - 5506, - 5509, - 5509, - 5511, - 5511, - 5511, - 5514, - 5514, - 5514, - 5517, - 5517, - 5517, - 5520, - 5520, - 5520, - 5523, - 5523, - 5523, - 5526, - 5526, - 5526, - 5529, - 5529, - 5529, - 5532, - 5532, - 5532, - 5535, - 5535, - 5535, - 5538, - 5538, - 5538, - 5541, - 5541, - 5541, - 5544, - 5544, - 5544, - 5547, - 5547, - 5549, - 5549, - 5549, - 5552, - 5552, - 5552, - 5555, - 5555, - 5555, - 5558, - 5558, - 5558, - 5561, - 5561, - 5561, - 5564, - 5564, - 5564, - 5567, - 5567, - 5567, - 5570, - 5570, - 5570, - 5573, - 5573, - 5573, - 5576, - 5576, - 5576, - 5579, - 5579, - 5581, - 5581, - 5581, - 5584, - 5584, - 5584, - 5587, - 5587, - 5587, - 5590, - 5590, - 5590, - 5593, - 5593, - 5593, - 5596, - 5596, - 5596, - 5599, - 5599, - 5599, - 5602, - 5602, - 5602, - 5605, - 5605, - 5605, - 5608, - 5608, - 5608, - 5611, - 5611, - 5611, - 5614, - 5614, - 5614, - 5617, - 5617, - 5619, - 5619, - 5619, - 5622, - 5622, - 5622, - 5625, - 5625, - 5625, - 5628, - 5628, - 5628, - 5631, - 5631, - 5631, - 5634, - 5634, - 5634, - 5637, - 5637, - 5637, - 5640, - 5640, - 5640, - 5643, - 5643, - 5643, - 5646, - 5646, - 5646, - 5649, - 5649, - 5651, - 5651, - 5651, - 5654, - 5654, - 5654, - 5657, - 5657, - 5657, - 5660, - 5660, - 5660, - 5663, - 5663, - 5663, - 5666, - 5666, - 5666, - 5669, - 5669, - 5669, - 5672, - 5672, - 5672, - 5675, - 5675, - 5675, - 5678, - 5678, - 5678, - 5681, - 5681, - 5681, - 5684, - 5684, - 5684, - 5687, - 5687, - 5689, - 5689, - 5689, - 5692, - 5692, - 5692, - 5695, - 5695, - 5697, - 5698, - 5698, - 5700, - 5701, - 5701, - 5703, - 5704, - 5704, - 5706, - 5707, - 5707, - 5709, - 5710, - 5710, - 5712, - 5713, - 5714, - 5715, - 5716, - 5716, - 5718, - 5719, - 5719, - 5721, - 5722, - 5722, - 5724, - 5724, - 5726, - 5726, - 5728, - 5729, - 5729, - 5731, - 5731, - 5733, - 5734, - 5734, - 5736, - 5737, - 5737, - 5739, - 5740, - 5740, - 5742, - 5743, - 5743, - 5745, - 5746, - 5746, - 5748, - 5749, - 5750, - 5751, - 5752, - 5752, - 5754, - 5755, - 5755, - 5757, - 5758, - 5758, - 5760, - 5760, - 5762, - 5762, - 5764, - 5765, - 5765, - 5767, - 5767, - 5769, - 5769, - 5771, - 5771, - 5773, - 5773, - 5775, - 5775, - 5775, - 5778, - 5778, - 5778, - 5781, - 5781, - 5783, - 5783, - 5785, - 5785, - 5785, - 5788, - 5788, - 5788, - 5791, - 5791, - 5791, - 5794, - 5794, - 5796, - 5796, - 5798, - 5798, - 5798, - 5801, - 5801, - 5801, - 5804, - 5804, - 5804, - 5807, - 5807, - 5809, - 5809, - 5811, - 5811, - 5813, - 5813, - 5815, - 5816, - 5816, - 5816, - 5819, - 5819, - 5819, - 5822, - 5822, - 5822, - 5825, - 5825, - 5825, - 5828, - 5828, - 5828, - 5831, - 5831, - 5831, - 5834, - 5834, - 5834, - 5837, - 5837, - 5837, - 5840, - 5840, - 5840, - 5843, - 5843, - 5843, - 5846, - 5846, - 5846, - 5849, - 5849, - 5849, - 5852, - 5853, - 5854, - 5854, - 5854, - 5857, - 5857, - 5857, - 5860, - 5860, - 5860, - 5863, - 5863, - 5863, - 5866, - 5866, - 5866, - 5869, - 5869, - 5869, - 5872, - 5872, - 5872, - 5875, - 5875, - 5875, - 5878, - 5878, - 5878, - 5881, - 5881, - 5881, - 5884, - 5884, - 5884, - 5887, - 5887, - 5887, - 5890, - 5891, - 5891, - 5893, - 5893, - 5895, - 5895, - 5895, - 5898, - 5898, - 5898, - 5901, - 5901, - 5901, - 5904, - 5904, - 5904, - 5907, - 5907, - 5909, - 5909, - 5909, - 5912, - 5912, - 5912, - 5915, - 5915, - 5917, - 5917, - 5919, - 5919, - 5921, - 5921, - 5921, - 5921, - 5925, - 5925, - 5925, - 5928, - 5928, - 5928, - 5931, - 5932, - 5932, - 5934, - 5934, - 5934, - 5934, - 5938, - 5938, - 5938, - 5941, - 5941, - 5943, - 5943, - 5943, - 5946, - 5946, - 5948, - 5949, - 5949, - 5951, - 5951, - 5951, - 5954, - 5955, - 5955, - 5957, - 5957, - 5959, - 5959, - 5959, - 5962, - 5963, - 5963, - 5965, - 5965, - 5967, - 5967, - 5967, - 5970, - 5971, - 5971, - 5971, - 5974, - 5975, - 5975, - 5977, - 5977, - 5979, - 5979, - 5979, - 5982, - 5982, - 5984, - 5985, - 5985, - 5987, - 5987, - 5987, - 5990, - 5991, - 5991, - 5993, - 5993, - 5995, - 5995, - 5995, - 5998, - 5999, - 5999, - 6001, - 6001, - 6003, - 6003, - 6003, - 6006, - 6007, - 6008, - 6008, - 6010, - 6010, - 6012, - 6012, - 6012, - 6015, - 6015, - 6017, - 6018, - 6018, - 6020, - 6020, - 6020, - 6023, - 6024, - 6024, - 6026, - 6026, - 6028, - 6028, - 6028, - 6031, - 6032, - 6032, - 6034, - 6034, - 6036, - 6036, - 6036, - 6039, - 6040, - 6040, - 6042, - 6042, - 6044, - 6044, - 6044, - 6047, - 6047, - 6047, - 6050, - 6050, - 6050, - 6053, - 6053, - 6053, - 6056, - 6056, - 6058, - 6058, - 6058, - 6061, - 6061, - 6061, - 6064, - 6064, - 6066, - 6066, - 6068, - 6068, - 6070, - 6070, - 6070, - 6070, - 6074, - 6074, - 6074, - 6077, - 6077, - 6077, - 6080, - 6081, - 6081, - 6083, - 6083, - 6083, - 6083, - 6087, - 6087, - 6087, - 6090, - 6090, - 6092, - 6092, - 6092, - 6095, - 6095, - 6097, - 6098, - 6098, - 6100, - 6100, - 6100, - 6103, - 6104, - 6104, - 6106, - 6106, - 6108, - 6108, - 6108, - 6111, - 6112, - 6112, - 6114, - 6114, - 6116, - 6116, - 6116, - 6119, - 6120, - 6120, - 6120, - 6123, - 6124, - 6124, - 6126, - 6126, - 6128, - 6128, - 6128, - 6131, - 6131, - 6133, - 6134, - 6134, - 6136, - 6136, - 6136, - 6139, - 6140, - 6140, - 6142, - 6142, - 6144, - 6144, - 6144, - 6147, - 6148, - 6148, - 6150, - 6150, - 6152, - 6152, - 6152, - 6155, - 6156, - 6157, - 6157, - 6159, - 6159, - 6161, - 6161, - 6161, - 6164, - 6164, - 6166, - 6167, - 6167, - 6169, - 6169, - 6169, - 6172, - 6173, - 6173, - 6175, - 6175, - 6177, - 6177, - 6177, - 6180, - 6181, - 6181, - 6183, - 6183, - 6185, - 6185, - 6185, - 6188, - 6189, - 6190, - 6191, - 6192, - 6193, - 6194, - 6195, - 6196, - 6196, - 6198, - 6199, - 6200, - 6200; - } - - MeshMaterialList { - 1; - 4816; - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0; - - Material { - 1.000000;1.000000;1.000000;1.000000;; - 34.560001; - 0.315000;0.315000;0.315000;; - 0.000000;0.000000;0.000000;; - TextureFilename { - "texture/SSR06_Born2_dif.png"; - } - BumpMapFilename { - "texture/SSR06_Born2_bp_base.png"; - } - } - } - - XSkinMeshHeader { - 1; - 1; - 33; - } - - SkinWeights { - "Bone01"; - 1077; - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100, - 101, - 102, - 103, - 104, - 105, - 106, - 178, - 179, - 180, - 181, - 182, - 183, - 184, - 185, - 186, - 187, - 188, - 189, - 190, - 191, - 192, - 193, - 194, - 195, - 196, - 197, - 198, - 199, - 200, - 201, - 202, - 203, - 204, - 205, - 206, - 207, - 208, - 209, - 210, - 211, - 212, - 213, - 214, - 215, - 216, - 217, - 218, - 219, - 220, - 221, - 222, - 223, - 224, - 225, - 226, - 227, - 228, - 229, - 230, - 231, - 232, - 233, - 234, - 235, - 236, - 237, - 238, - 239, - 240, - 241, - 242, - 243, - 244, - 245, - 246, - 247, - 248, - 249, - 250, - 251, - 252, - 420, - 421, - 422, - 423, - 424, - 425, - 426, - 427, - 446, - 447, - 448, - 449, - 450, - 451, - 452, - 453, - 454, - 455, - 456, - 457, - 458, - 459, - 460, - 461, - 462, - 463, - 464, - 465, - 466, - 467, - 468, - 469, - 470, - 471, - 472, - 473, - 474, - 475, - 476, - 477, - 478, - 529, - 736, - 737, - 738, - 739, - 740, - 741, - 742, - 743, - 744, - 745, - 746, - 747, - 748, - 749, - 750, - 751, - 752, - 753, - 754, - 755, - 756, - 757, - 758, - 759, - 760, - 761, - 762, - 763, - 764, - 765, - 766, - 767, - 768, - 769, - 770, - 771, - 772, - 773, - 774, - 775, - 776, - 777, - 778, - 779, - 780, - 781, - 782, - 783, - 784, - 785, - 786, - 787, - 788, - 789, - 790, - 791, - 792, - 1035, - 1036, - 1037, - 1038, - 1039, - 1040, - 1041, - 1042, - 1043, - 1044, - 1045, - 1046, - 1047, - 1048, - 1049, - 1050, - 1051, - 1052, - 1053, - 1054, - 1055, - 1056, - 1057, - 1058, - 1059, - 1060, - 1061, - 1062, - 1063, - 1064, - 1065, - 1066, - 1067, - 1068, - 1069, - 1070, - 1071, - 1072, - 1073, - 1074, - 1075, - 1076, - 1077, - 1078, - 1079, - 1080, - 1081, - 1082, - 1083, - 1084, - 1085, - 1086, - 1087, - 1088, - 1152, - 1153, - 1154, - 1155, - 1156, - 1157, - 1158, - 1159, - 1160, - 1161, - 1162, - 1163, - 1333, - 1334, - 1335, - 1336, - 1337, - 1338, - 1339, - 1340, - 1705, - 1706, - 1729, - 1730, - 1745, - 1746, - 1747, - 1748, - 1749, - 1750, - 1751, - 1752, - 1797, - 1798, - 1799, - 1800, - 1917, - 1918, - 1919, - 1920, - 1921, - 1936, - 1937, - 1938, - 1939, - 1940, - 1941, - 1942, - 1943, - 1944, - 1945, - 1946, - 1947, - 1948, - 1949, - 1950, - 1951, - 1952, - 1953, - 1954, - 1955, - 1956, - 1957, - 1958, - 1959, - 1960, - 1961, - 1962, - 1963, - 1964, - 1965, - 1966, - 1967, - 1968, - 1969, - 1970, - 1971, - 1972, - 1973, - 1974, - 1975, - 1976, - 1977, - 1978, - 1979, - 1980, - 2081, - 2082, - 2083, - 2084, - 2085, - 2086, - 2087, - 2088, - 2089, - 2090, - 2091, - 2092, - 2093, - 2094, - 2095, - 2096, - 2097, - 2098, - 2099, - 2100, - 2101, - 2102, - 2103, - 2104, - 2105, - 2106, - 2107, - 2108, - 2109, - 2110, - 2111, - 2112, - 2113, - 2114, - 2115, - 2116, - 2117, - 2118, - 2119, - 2120, - 2121, - 2122, - 2123, - 2124, - 2125, - 2126, - 2127, - 2128, - 2129, - 2130, - 2131, - 2132, - 2133, - 2134, - 2135, - 2136, - 2137, - 2138, - 2139, - 2140, - 2141, - 2142, - 2143, - 2144, - 2145, - 2146, - 2147, - 2148, - 2149, - 2150, - 2151, - 2208, - 2209, - 2210, - 2211, - 2212, - 2213, - 2250, - 2251, - 2252, - 2253, - 2254, - 2255, - 2264, - 2265, - 2266, - 2267, - 2268, - 2269, - 2270, - 2271, - 2272, - 2273, - 2274, - 2275, - 2276, - 2277, - 2278, - 2279, - 2280, - 2281, - 2282, - 2283, - 2284, - 2285, - 2286, - 2287, - 2288, - 2289, - 2290, - 2291, - 2292, - 2293, - 2294, - 2295, - 2296, - 2297, - 2298, - 2299, - 2300, - 2301, - 2302, - 2303, - 2304, - 2305, - 2306, - 2307, - 2308, - 2336, - 2337, - 2338, - 2339, - 2340, - 2341, - 2342, - 2343, - 2344, - 2345, - 2346, - 2347, - 2348, - 2349, - 2350, - 2351, - 2352, - 2353, - 2354, - 2355, - 2356, - 2357, - 2358, - 2359, - 2360, - 2399, - 2400, - 2401, - 2402, - 2403, - 2404, - 2405, - 2406, - 2407, - 2408, - 2409, - 2410, - 2513, - 2514, - 2515, - 2516, - 2517, - 2518, - 2519, - 2520, - 2521, - 2522, - 2523, - 2524, - 2525, - 2526, - 2527, - 2528, - 2529, - 2530, - 2531, - 2532, - 2533, - 2534, - 2535, - 2536, - 2537, - 2538, - 2539, - 2540, - 2541, - 2542, - 2543, - 2544, - 2545, - 2546, - 2547, - 2548, - 2549, - 2550, - 2551, - 3028, - 3029, - 3030, - 3031, - 3032, - 3033, - 3037, - 3038, - 3082, - 3083, - 3084, - 3085, - 3086, - 3087, - 3088, - 3089, - 3090, - 3091, - 3092, - 3093, - 3094, - 3095, - 3096, - 3097, - 3098, - 3161, - 3162, - 3163, - 3164, - 3165, - 3166, - 3167, - 3168, - 3169, - 3170, - 3171, - 3172, - 3173, - 3174, - 3175, - 3176, - 3177, - 3178, - 3179, - 3180, - 3181, - 3182, - 3183, - 3184, - 3185, - 3186, - 3187, - 3188, - 3189, - 3190, - 3191, - 3192, - 3193, - 3194, - 3195, - 3196, - 3197, - 3198, - 3199, - 3200, - 3201, - 3202, - 3203, - 3204, - 3205, - 3206, - 3207, - 3208, - 3209, - 3210, - 3211, - 3212, - 3213, - 3214, - 3215, - 3216, - 3217, - 3218, - 3219, - 3220, - 3221, - 3222, - 3223, - 3224, - 3225, - 3226, - 3227, - 3228, - 3229, - 3230, - 3395, - 3396, - 3397, - 3398, - 3399, - 3414, - 3415, - 3416, - 3417, - 3418, - 3419, - 3420, - 3421, - 3422, - 3423, - 3424, - 3425, - 3426, - 3427, - 3428, - 3429, - 3430, - 3431, - 3432, - 3433, - 3434, - 3435, - 3436, - 3437, - 3438, - 3439, - 3686, - 3687, - 3688, - 3689, - 3690, - 3691, - 3692, - 3693, - 3694, - 3695, - 3696, - 3697, - 3698, - 3699, - 3700, - 3701, - 3702, - 3703, - 3704, - 3705, - 3706, - 3707, - 3708, - 3709, - 3710, - 3711, - 3712, - 3713, - 3714, - 3715, - 3716, - 3717, - 3718, - 3719, - 3720, - 3721, - 3722, - 3723, - 3724, - 3725, - 3726, - 3727, - 3728, - 3729, - 3730, - 3731, - 3732, - 3733, - 3734, - 3735, - 3736, - 3737, - 3980, - 3981, - 3982, - 3983, - 3984, - 3985, - 3986, - 3987, - 3988, - 3989, - 3990, - 3991, - 3992, - 3993, - 3994, - 3995, - 3996, - 3997, - 3998, - 3999, - 4000, - 4001, - 4002, - 4003, - 4004, - 4005, - 4006, - 4007, - 4008, - 4009, - 4010, - 4011, - 4012, - 4013, - 4014, - 4015, - 4016, - 4017, - 4018, - 4019, - 4020, - 4021, - 4022, - 4023, - 4024, - 4025, - 4026, - 4027, - 4028, - 4029, - 4030, - 4031, - 4032, - 4096, - 4097, - 4098, - 4099, - 4100, - 4101, - 4102, - 4103, - 4104, - 4105, - 4106, - 4107, - 4266, - 4267, - 4268, - 4269, - 4270, - 4271, - 4272, - 4273, - 4638, - 4639, - 4662, - 4663, - 4678, - 4679, - 4680, - 4681, - 4682, - 4683, - 4684, - 4685, - 4834, - 4835, - 4836, - 4847, - 4848, - 4849, - 4850, - 4851, - 4852, - 4853, - 4854, - 4855, - 4856, - 4857, - 4858, - 4859, - 4860, - 4861, - 4862, - 4863, - 4864, - 4865, - 4866, - 4867, - 4868, - 4869, - 4870, - 4871, - 4872, - 4873, - 4874, - 4875, - 4876, - 4877, - 4878, - 4879, - 4880, - 4881, - 4882, - 4883, - 4884, - 4885, - 4886, - 4887, - 4988, - 4989, - 4990, - 4991, - 4992, - 4993, - 4994, - 4995, - 4996, - 4997, - 4998, - 4999, - 5000, - 5001, - 5002, - 5003, - 5004, - 5005, - 5006, - 5007, - 5008, - 5009, - 5010, - 5011, - 5012, - 5013, - 5014, - 5015, - 5016, - 5017, - 5018, - 5019, - 5020, - 5021, - 5022, - 5023, - 5024, - 5025, - 5026, - 5027, - 5028, - 5029, - 5030, - 5031, - 5032, - 5033, - 5034, - 5035, - 5036, - 5037, - 5038, - 5039, - 5040, - 5041, - 5042, - 5043, - 5044, - 5045, - 5046, - 5047, - 5048, - 5049, - 5050, - 5051, - 5052, - 5053, - 5054, - 5055, - 5112, - 5113, - 5114, - 5115, - 5116, - 5117, - 5148, - 5149, - 5150, - 5151, - 5152, - 5153, - 5160, - 5161, - 5162, - 5163, - 5164, - 5165, - 5166, - 5167, - 5168, - 5169, - 5170, - 5171, - 5172, - 5173, - 5174, - 5175, - 5176, - 5177, - 5178, - 5179, - 5180, - 5181, - 5182, - 5183, - 5184, - 5185, - 5186, - 5187, - 5188, - 5189, - 5190, - 5191, - 5192, - 5193, - 5194, - 5195, - 5196, - 5197, - 5198, - 5199, - 5200, - 5201, - 5202, - 5203, - 5204, - 5227, - 5228, - 5229, - 5230, - 5231, - 5232, - 5233, - 5234, - 5235, - 5236, - 5237, - 5238, - 5239, - 5240, - 5241, - 5242, - 5243, - 5244, - 5245, - 5246, - 5247, - 5248, - 5249, - 5250, - 5251, - 5278, - 5279, - 5280, - 5281, - 5282, - 5283, - 5284, - 5285, - 5286, - 5287, - 5288, - 5289, - 5376, - 5377, - 5378, - 5379, - 5380, - 5381, - 5382, - 5383, - 5384, - 5385, - 5386, - 5387, - 5388, - 5389, - 5390, - 5391, - 5392, - 5393, - 5394, - 5395, - 5396, - 5397, - 5398, - 5399, - 5400, - 5401, - 5402, - 5403, - 5404, - 5405, - 5406, - 5407, - 5408, - 5409, - 5410, - 5411, - 5412, - 5413, - 5414, - 6189, - 6190, - 6194, - 6195, - 6196, - 6197, - 6198, - 6199, - 6200, - 6201; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,-0.000000,-0.000000,-6.600000,1.000000;; - } - - SkinWeights { - "L_Kata_Base"; - 56; - 4583, - 4584, - 4585, - 4586, - 4587, - 4588, - 4589, - 4590, - 4591, - 4592, - 4593, - 4594, - 4603, - 4604, - 4605, - 4606, - 4607, - 4608, - 4609, - 4610, - 4611, - 4612, - 4613, - 4614, - 4615, - 4616, - 4617, - 4618, - 4619, - 4620, - 4621, - 4622, - 4623, - 4624, - 4640, - 4641, - 4642, - 4643, - 4644, - 4645, - 4646, - 4647, - 4648, - 4649, - 4650, - 4651, - 4652, - 4653, - 4654, - 4655, - 4656, - 4657, - 4658, - 4659, - 4660, - 4661; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.000000,-0.000000,1.000000,0.000000,1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-9.450001,-0.449997,-1.051190,1.000000;; - } - - SkinWeights { - "L_Ueude"; - 52; - 3861, - 3862, - 3863, - 3864, - 3865, - 3866, - 3867, - 3868, - 3925, - 3926, - 3927, - 3928, - 3929, - 3930, - 3931, - 3932, - 4485, - 4486, - 4487, - 4488, - 4489, - 4490, - 4491, - 4492, - 4493, - 4494, - 4495, - 4496, - 4497, - 4498, - 4499, - 4500, - 4501, - 4502, - 4559, - 4560, - 4561, - 4562, - 4563, - 4564, - 4565, - 4566, - 4567, - 4568, - 4569, - 4570, - 4571, - 4572, - 4573, - 4574, - 4575, - 4576; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.000000,-0.000000,1.000000,0.000000,1.000000,-0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-9.480000,-0.459996,-2.051189,1.000000;; - } - - SkinWeights { - "L_Hizi"; - 48; - 5767, - 5768, - 5769, - 5770, - 5771, - 5772, - 5773, - 5774, - 5775, - 5776, - 5777, - 5778, - 5779, - 5780, - 5781, - 5782, - 5783, - 5784, - 5785, - 5786, - 5787, - 5788, - 5789, - 5790, - 5791, - 5792, - 5793, - 5794, - 5795, - 5796, - 5797, - 5798, - 5799, - 5800, - 5801, - 5802, - 5803, - 5804, - 5805, - 5806, - 5807, - 5808, - 5809, - 5810, - 5811, - 5812, - 5813, - 5814; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000001,-0.000000,1.000000,0.000000,1.000000,-0.000000,0.000001,0.000000,0.000000,1.000000,0.000000,0.000000,-9.479997,-0.459996,-3.551198,1.000000;; - } - - SkinWeights { - "L_Sitaude"; - 209; - 3738, - 3739, - 3740, - 3741, - 3742, - 3743, - 3744, - 3745, - 3746, - 3747, - 3748, - 3749, - 3750, - 3751, - 3797, - 3798, - 3799, - 3800, - 3801, - 3802, - 3803, - 3804, - 3821, - 3822, - 3823, - 3824, - 3825, - 3826, - 3827, - 3828, - 3829, - 3830, - 3831, - 3832, - 3833, - 3834, - 3835, - 3836, - 3837, - 3838, - 3839, - 3840, - 3841, - 3842, - 3843, - 3844, - 3845, - 3846, - 3847, - 3848, - 3849, - 3850, - 4274, - 4275, - 4276, - 4277, - 4278, - 4279, - 4280, - 4281, - 4282, - 4283, - 4284, - 4285, - 4286, - 4287, - 4288, - 4289, - 4290, - 4291, - 4292, - 4293, - 4294, - 4295, - 4296, - 4297, - 4298, - 4299, - 4300, - 4301, - 4369, - 4370, - 4371, - 4372, - 4373, - 4374, - 4375, - 4376, - 4377, - 4378, - 4395, - 4396, - 4397, - 4398, - 4399, - 4400, - 4401, - 4402, - 4403, - 4404, - 4405, - 4406, - 4407, - 4408, - 4409, - 4410, - 4411, - 4412, - 4413, - 4414, - 4415, - 4416, - 4417, - 4418, - 4419, - 4420, - 4421, - 4422, - 4423, - 4424, - 4425, - 4426, - 4427, - 4428, - 4429, - 4430, - 4431, - 4432, - 4433, - 4434, - 4435, - 4436, - 4437, - 4438, - 4439, - 4440, - 4441, - 4442, - 4443, - 4444, - 4445, - 4446, - 4447, - 4448, - 4449, - 4450, - 4451, - 4452, - 4453, - 4454, - 4455, - 4456, - 4457, - 4458, - 4459, - 4460, - 4461, - 4462, - 4463, - 4464, - 4465, - 4466, - 4467, - 4468, - 4469, - 4470, - 4471, - 4472, - 4473, - 4474, - 4888, - 4889, - 4890, - 4891, - 4892, - 4893, - 4894, - 4895, - 4896, - 4897, - 4898, - 4899, - 4900, - 4901, - 4920, - 4921, - 4922, - 4923, - 4924, - 4925, - 4926, - 4927, - 4928, - 4929, - 4930, - 4931, - 4932, - 4933, - 4934, - 4935, - 4936, - 4937, - 4938, - 4939, - 4940, - 4941, - 4942, - 4943, - 4944; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000001,-0.000000,1.000000,0.000000,1.000000,-0.000000,0.000001,0.000000,0.000000,1.000000,0.000000,0.000000,-9.479997,-0.459996,-4.001198,1.000000;; - } - - SkinWeights { - "L_kata_Armer"; - 220; - 3877, - 3878, - 3879, - 3880, - 3881, - 3882, - 3883, - 3884, - 3885, - 3886, - 3887, - 3888, - 3889, - 3890, - 3891, - 3892, - 3893, - 3894, - 3895, - 3896, - 3897, - 3898, - 3899, - 3933, - 3934, - 3935, - 3936, - 3937, - 3938, - 3939, - 3940, - 3941, - 3942, - 3943, - 3944, - 3945, - 3946, - 3947, - 3948, - 3949, - 3950, - 3951, - 3952, - 3953, - 3954, - 3955, - 3956, - 3957, - 3958, - 3959, - 3960, - 3961, - 3962, - 3963, - 3964, - 3965, - 3966, - 3967, - 3968, - 3969, - 3970, - 3971, - 3972, - 3973, - 3974, - 3975, - 3976, - 3977, - 3978, - 3979, - 4063, - 4064, - 4065, - 4066, - 4067, - 4068, - 4069, - 4070, - 4071, - 4072, - 4073, - 4074, - 4075, - 4076, - 4077, - 4078, - 4079, - 4080, - 4081, - 4082, - 4083, - 4084, - 4085, - 4086, - 4087, - 4088, - 4089, - 4090, - 4091, - 4092, - 4093, - 4094, - 4095, - 4545, - 4546, - 4547, - 4548, - 4549, - 4550, - 4551, - 4552, - 4553, - 4554, - 4555, - 4556, - 4557, - 4558, - 4595, - 4596, - 4597, - 4598, - 4599, - 4600, - 4601, - 4602, - 4625, - 4626, - 4627, - 4628, - 4629, - 4630, - 4631, - 4632, - 4633, - 4634, - 4635, - 4636, - 4637, - 4664, - 4665, - 4666, - 4667, - 4668, - 4669, - 4670, - 4671, - 4672, - 4673, - 4674, - 4675, - 4676, - 4677, - 4946, - 4947, - 4948, - 4949, - 4950, - 4951, - 4952, - 4953, - 4954, - 4955, - 4956, - 4957, - 4958, - 4959, - 4960, - 4961, - 4962, - 4963, - 4964, - 4965, - 4966, - 4967, - 4968, - 4969, - 4970, - 4971, - 4972, - 4973, - 4974, - 4975, - 4976, - 4977, - 4978, - 4979, - 4980, - 4981, - 4982, - 4983, - 4984, - 4985, - 4986, - 4987, - 5086, - 5087, - 5088, - 5089, - 5090, - 5091, - 5092, - 5093, - 5094, - 5095, - 5096, - 5097, - 5098, - 5099, - 5100, - 5101, - 5102, - 5103, - 5104, - 5105, - 5106, - 5107, - 5108, - 5109, - 5110, - 5111; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.234641,-0.000000,0.972082,0.000000,0.972082,-0.000000,0.234641,0.000000,0.000000,1.000000,0.000000,0.000000,-8.798740,-0.449997,-3.822448,1.000000;; - } - - SkinWeights { - "L_Kata_S_Joint_1"; - 96; - 3851, - 3852, - 3853, - 3854, - 3900, - 3901, - 3902, - 3903, - 3904, - 3905, - 4475, - 4476, - 4477, - 4478, - 4527, - 4528, - 4529, - 4530, - 4531, - 4532, - 5815, - 5816, - 5817, - 5818, - 5819, - 5820, - 5821, - 5822, - 5823, - 5824, - 5825, - 5826, - 5827, - 5828, - 5829, - 5830, - 5831, - 5832, - 5833, - 5834, - 5835, - 5836, - 5837, - 5838, - 5839, - 5840, - 5841, - 5842, - 5843, - 5844, - 5845, - 5846, - 5847, - 5848, - 5849, - 5850, - 5851, - 5852, - 5853, - 5854, - 5855, - 5856, - 5857, - 5858, - 5859, - 5860, - 5861, - 5862, - 5863, - 5864, - 5865, - 5866, - 5867, - 5868, - 5869, - 5870, - 5871, - 5872, - 5873, - 5874, - 5875, - 5876, - 5877, - 5878, - 5879, - 5880, - 5881, - 5882, - 5883, - 5884, - 5885, - 5886, - 5887, - 5888, - 5889, - 5890; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.036128,-0.000000,0.999347,0.000000,0.999347,-0.000000,0.036128,0.000000,0.000000,1.000000,0.000000,0.000000,-9.681562,-0.449997,-3.453222,1.000000;; - } - - SkinWeights { - "L_kata_S_Joint_2"; - 62; - 3805, - 3806, - 3807, - 3808, - 3809, - 3810, - 3855, - 3856, - 3857, - 3858, - 3859, - 3860, - 3906, - 3907, - 3908, - 3909, - 3910, - 3911, - 3912, - 3913, - 3914, - 3915, - 3916, - 3917, - 3918, - 3919, - 3920, - 3921, - 3922, - 3923, - 3924, - 4479, - 4480, - 4481, - 4482, - 4483, - 4484, - 4533, - 4534, - 4535, - 4536, - 4537, - 4538, - 4539, - 4540, - 4541, - 4542, - 4543, - 4544, - 4577, - 4578, - 4579, - 4580, - 4581, - 4582, - 4902, - 4903, - 4904, - 4905, - 4906, - 4907, - 4945; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.036128,-0.000000,0.999347,0.000000,0.999347,-0.000000,0.036128,0.000000,0.000000,1.000000,0.000000,0.000000,-9.681562,-0.449997,-4.803222,1.000000;; - } - - SkinWeights { - "L_Kata_S_End"; - 98; - 3679, - 3680, - 3681, - 3682, - 3683, - 3684, - 3811, - 3812, - 3813, - 3814, - 3815, - 3816, - 3817, - 3818, - 3819, - 3820, - 4033, - 4034, - 4035, - 4036, - 4037, - 4038, - 4039, - 4040, - 4041, - 4042, - 4043, - 4044, - 4045, - 4046, - 4047, - 4048, - 4049, - 4050, - 4051, - 4052, - 4053, - 4054, - 4055, - 4056, - 4057, - 4058, - 4059, - 4060, - 4061, - 4062, - 4811, - 4812, - 4813, - 4814, - 4815, - 4816, - 4817, - 4818, - 4819, - 4820, - 4908, - 4909, - 4910, - 4911, - 4912, - 4913, - 4914, - 4915, - 4916, - 4917, - 4918, - 4919, - 5056, - 5057, - 5058, - 5059, - 5060, - 5061, - 5062, - 5063, - 5064, - 5065, - 5066, - 5067, - 5068, - 5069, - 5070, - 5071, - 5072, - 5073, - 5074, - 5075, - 5076, - 5077, - 5078, - 5079, - 5080, - 5081, - 5082, - 5083, - 5084, - 5085; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.999347,-0.000000,0.036128,0.000000,0.036128,-0.000000,-0.999347,0.000000,0.000000,1.000000,-0.000000,0.000000,-6.153222,-0.449997,9.681562,1.000000;; - } - - SkinWeights { - "L_Hand"; - 440; - 3752, - 3753, - 3754, - 3755, - 3756, - 3757, - 3758, - 3759, - 3760, - 3761, - 3762, - 3763, - 3764, - 3765, - 3766, - 3767, - 3768, - 3769, - 3770, - 3771, - 3772, - 3773, - 3774, - 3775, - 3776, - 3777, - 3778, - 3779, - 3780, - 3781, - 3782, - 3783, - 3784, - 3785, - 3786, - 3787, - 3788, - 3789, - 3790, - 3791, - 3792, - 3793, - 3794, - 3795, - 3796, - 3869, - 3870, - 3871, - 3872, - 3873, - 3874, - 3875, - 3876, - 4302, - 4303, - 4304, - 4305, - 4306, - 4307, - 4308, - 4309, - 4310, - 4311, - 4312, - 4313, - 4314, - 4315, - 4316, - 4317, - 4318, - 4319, - 4320, - 4321, - 4322, - 4323, - 4324, - 4325, - 4326, - 4327, - 4328, - 4329, - 4330, - 4331, - 4332, - 4333, - 4334, - 4335, - 4336, - 4337, - 4338, - 4339, - 4340, - 4341, - 4342, - 4343, - 4344, - 4345, - 4346, - 4347, - 4348, - 4349, - 4350, - 4351, - 4352, - 4353, - 4354, - 4355, - 4356, - 4357, - 4358, - 4359, - 4360, - 4361, - 4362, - 4363, - 4364, - 4365, - 4366, - 4367, - 4368, - 4379, - 4380, - 4381, - 4382, - 4383, - 4384, - 4385, - 4386, - 4387, - 4388, - 4389, - 4390, - 4391, - 4392, - 4393, - 4394, - 4503, - 4504, - 4505, - 4506, - 4507, - 4508, - 4509, - 4510, - 4511, - 4512, - 4513, - 4514, - 4515, - 4516, - 4517, - 4518, - 4519, - 4520, - 4521, - 4522, - 4523, - 4524, - 4525, - 4526, - 5415, - 5416, - 5417, - 5418, - 5419, - 5420, - 5421, - 5422, - 5423, - 5424, - 5425, - 5426, - 5427, - 5428, - 5429, - 5430, - 5431, - 5432, - 5433, - 5434, - 5435, - 5436, - 5437, - 5438, - 5439, - 5440, - 5441, - 5442, - 5443, - 5444, - 5445, - 5446, - 5447, - 5448, - 5449, - 5450, - 5451, - 5452, - 5453, - 5454, - 5455, - 5456, - 5457, - 5458, - 5459, - 5460, - 5461, - 5462, - 5463, - 5464, - 5465, - 5466, - 5467, - 5468, - 5469, - 5470, - 5471, - 5472, - 5473, - 5474, - 5475, - 5476, - 5477, - 5478, - 5479, - 5480, - 5481, - 5482, - 5483, - 5484, - 5485, - 5486, - 5487, - 5488, - 5489, - 5490, - 5491, - 5492, - 5493, - 5494, - 5495, - 5496, - 5497, - 5498, - 5499, - 5500, - 5501, - 5502, - 5503, - 5504, - 5505, - 5506, - 5507, - 5508, - 5509, - 5510, - 5511, - 5512, - 5513, - 5514, - 5515, - 5516, - 5517, - 5518, - 5519, - 5520, - 5521, - 5522, - 5523, - 5524, - 5525, - 5526, - 5527, - 5528, - 5529, - 5530, - 5531, - 5532, - 5533, - 5534, - 5535, - 5536, - 5537, - 5538, - 5539, - 5540, - 5541, - 5542, - 5543, - 5544, - 5545, - 5546, - 5547, - 5548, - 5549, - 5550, - 5551, - 5552, - 5553, - 5554, - 5555, - 5556, - 5557, - 5558, - 5559, - 5560, - 5561, - 5562, - 5563, - 5564, - 5565, - 5566, - 5567, - 5568, - 5569, - 5570, - 5571, - 5572, - 5573, - 5574, - 5575, - 5576, - 5577, - 5578, - 5579, - 5580, - 5581, - 5582, - 5583, - 5584, - 5585, - 5586, - 5587, - 5588, - 5589, - 5590, - 5591, - 5592, - 5593, - 5594, - 5595, - 5596, - 5597, - 5598, - 5599, - 5600, - 5601, - 5602, - 5603, - 5604, - 5605, - 5606, - 5607, - 5608, - 5609, - 5610, - 5611, - 5612, - 5613, - 5614, - 5615, - 5616, - 5617, - 5618, - 5619, - 5620, - 5621, - 5622, - 5623, - 5624, - 5625, - 5626, - 5627, - 5628, - 5629, - 5630, - 5631, - 5632, - 5633, - 5634, - 5635, - 5636, - 5637, - 5638, - 5639, - 5640, - 5641, - 5642, - 5643, - 5644, - 5645, - 5646, - 5647, - 5648, - 5649, - 5650, - 5651, - 5652, - 5653, - 5654, - 5655, - 5656, - 5657, - 5658, - 5659, - 5660, - 5661, - 5662, - 5663, - 5664, - 5665, - 5666, - 5667, - 5668, - 5669, - 5670, - 5671, - 5672, - 5673, - 5674, - 5675, - 5676, - 5677, - 5678, - 5679, - 5680, - 5681, - 5682, - 5683, - 5684, - 5685, - 5686, - 5687, - 5688, - 5689, - 5690, - 5691, - 5692, - 5693, - 5694; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000001,-0.000000,1.000000,0.000000,1.000000,-0.000000,0.000001,0.000000,0.000000,1.000000,0.000000,0.000000,-9.479997,-0.739996,-6.001198,1.000000;; - } - - SkinWeights { - "Kosi"; - 399; - 10, - 11, - 12, - 13, - 27, - 28, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 137, - 138, - 139, - 140, - 141, - 142, - 143, - 144, - 145, - 146, - 147, - 148, - 149, - 150, - 151, - 152, - 153, - 154, - 155, - 156, - 157, - 158, - 159, - 160, - 161, - 162, - 163, - 164, - 165, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 174, - 175, - 176, - 177, - 385, - 386, - 387, - 388, - 389, - 390, - 391, - 392, - 393, - 394, - 395, - 396, - 397, - 398, - 399, - 400, - 401, - 428, - 429, - 430, - 431, - 432, - 433, - 434, - 435, - 436, - 437, - 438, - 439, - 440, - 441, - 442, - 443, - 444, - 445, - 1874, - 1875, - 1876, - 1877, - 1878, - 1879, - 1880, - 1881, - 1882, - 1883, - 1884, - 1885, - 1886, - 1887, - 1888, - 1889, - 1890, - 1891, - 1892, - 1893, - 1922, - 1923, - 1924, - 1925, - 1926, - 1927, - 1928, - 1929, - 1930, - 1931, - 1932, - 1933, - 1934, - 1935, - 2256, - 2257, - 2258, - 2259, - 2260, - 2261, - 2262, - 2263, - 2832, - 2833, - 2834, - 2835, - 2836, - 2837, - 2838, - 2839, - 2840, - 2841, - 2842, - 2843, - 2844, - 2845, - 2846, - 2847, - 2848, - 2849, - 2850, - 2851, - 2852, - 2853, - 2854, - 2855, - 2856, - 2857, - 2858, - 2859, - 2860, - 2861, - 2862, - 2863, - 2864, - 2865, - 2866, - 2867, - 2868, - 2869, - 2870, - 2871, - 2872, - 2873, - 2874, - 2875, - 2876, - 2877, - 2878, - 2879, - 2880, - 2881, - 2882, - 2883, - 2884, - 2885, - 2886, - 2887, - 2888, - 2889, - 2890, - 2891, - 2892, - 2893, - 2894, - 2895, - 2896, - 2897, - 2898, - 2899, - 2900, - 2901, - 2902, - 2903, - 3034, - 3035, - 3067, - 3068, - 3069, - 3070, - 3071, - 3072, - 3073, - 3074, - 3075, - 3076, - 3077, - 3078, - 3079, - 3080, - 3081, - 3129, - 3130, - 3131, - 3132, - 3133, - 3134, - 3135, - 3136, - 3137, - 3138, - 3139, - 3140, - 3141, - 3142, - 3143, - 3144, - 3145, - 3146, - 3147, - 3148, - 3149, - 3150, - 3151, - 3152, - 3153, - 3154, - 3155, - 3156, - 3157, - 3158, - 3159, - 3160, - 3363, - 3364, - 3365, - 3366, - 3367, - 3368, - 3369, - 3370, - 3371, - 3372, - 3373, - 3374, - 3375, - 3376, - 3400, - 3401, - 3402, - 3403, - 3404, - 3405, - 3406, - 3407, - 3408, - 3409, - 3410, - 3411, - 3412, - 3413, - 4796, - 4797, - 4798, - 4799, - 4800, - 4801, - 4802, - 4803, - 4804, - 4805, - 4806, - 4807, - 4808, - 4809, - 4810, - 4837, - 4838, - 4839, - 4840, - 4841, - 4842, - 4843, - 4844, - 4845, - 4846, - 5154, - 5155, - 5156, - 5157, - 5158, - 5159, - 5695, - 5696, - 5697, - 5698, - 5699, - 5700, - 5701, - 5702, - 5703, - 5704, - 5705, - 5706, - 5707, - 5708, - 5709, - 5710, - 5711, - 5712, - 5713, - 5714, - 5715, - 5716, - 5717, - 5718, - 5719, - 5720, - 5721, - 5722, - 5723, - 5724, - 5725, - 5726, - 5727, - 5728, - 5729, - 5730, - 5731, - 5732, - 5733, - 5734, - 5735, - 5736, - 5737, - 5738, - 5739, - 5740, - 5741, - 5742, - 5743, - 5744, - 5745, - 5746, - 5747, - 5748, - 5749, - 5750, - 5751, - 5752, - 5753, - 5754, - 5755, - 5756, - 5757, - 5758, - 5759, - 5760, - 5761, - 5762, - 5763, - 5764, - 5765, - 5766; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,6.600000,1.000000;; - } - - SkinWeights { - "L_momo"; - 285; - 3042, - 3121, - 3122, - 3123, - 3124, - 3125, - 3126, - 3127, - 3128, - 3336, - 3337, - 3338, - 3339, - 3340, - 3347, - 3348, - 3349, - 3350, - 3354, - 3355, - 3356, - 3377, - 3378, - 3379, - 3380, - 3381, - 3382, - 3383, - 3384, - 3385, - 3386, - 3387, - 3388, - 3389, - 3390, - 3391, - 3392, - 3393, - 3394, - 3550, - 3551, - 3552, - 3597, - 3598, - 3599, - 3685, - 4208, - 4209, - 4210, - 4226, - 4227, - 4228, - 4253, - 4254, - 4258, - 4261, - 4262, - 4784, - 4785, - 4786, - 4787, - 4788, - 4789, - 4790, - 4791, - 4792, - 4793, - 4794, - 4795, - 4821, - 4822, - 4823, - 4824, - 4825, - 4826, - 4827, - 4828, - 4829, - 4830, - 4831, - 4832, - 4833, - 5290, - 5291, - 5292, - 5293, - 5294, - 5295, - 5296, - 5297, - 5298, - 5299, - 5300, - 5301, - 5302, - 5303, - 5304, - 5305, - 5306, - 5307, - 5308, - 5309, - 5310, - 5311, - 5312, - 5313, - 5314, - 5315, - 5316, - 5317, - 5318, - 5319, - 5320, - 5321, - 5322, - 5323, - 5324, - 5325, - 5326, - 5327, - 5328, - 5329, - 5330, - 5331, - 5332, - 5333, - 5334, - 5335, - 5336, - 5337, - 5338, - 5339, - 5340, - 5341, - 5342, - 5343, - 6040, - 6041, - 6042, - 6043, - 6044, - 6045, - 6046, - 6047, - 6048, - 6049, - 6050, - 6051, - 6052, - 6053, - 6054, - 6055, - 6056, - 6057, - 6058, - 6059, - 6060, - 6061, - 6062, - 6063, - 6064, - 6065, - 6066, - 6067, - 6068, - 6069, - 6070, - 6071, - 6072, - 6073, - 6074, - 6075, - 6076, - 6077, - 6078, - 6079, - 6080, - 6081, - 6082, - 6083, - 6084, - 6085, - 6086, - 6087, - 6088, - 6089, - 6090, - 6091, - 6092, - 6093, - 6094, - 6095, - 6096, - 6097, - 6098, - 6099, - 6100, - 6101, - 6102, - 6103, - 6104, - 6105, - 6106, - 6107, - 6108, - 6109, - 6110, - 6111, - 6112, - 6113, - 6114, - 6115, - 6116, - 6117, - 6118, - 6119, - 6120, - 6121, - 6122, - 6123, - 6124, - 6125, - 6126, - 6127, - 6128, - 6129, - 6130, - 6131, - 6132, - 6133, - 6134, - 6135, - 6136, - 6137, - 6138, - 6139, - 6140, - 6141, - 6142, - 6143, - 6144, - 6145, - 6146, - 6147, - 6148, - 6149, - 6150, - 6151, - 6152, - 6153, - 6154, - 6155, - 6156, - 6157, - 6158, - 6159, - 6160, - 6161, - 6162, - 6163, - 6164, - 6165, - 6166, - 6167, - 6168, - 6169, - 6170, - 6171, - 6172, - 6173, - 6174, - 6175, - 6176, - 6177, - 6178, - 6179, - 6180, - 6181, - 6182, - 6183, - 6184, - 6185, - 6186, - 6187, - 6188; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,-0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-1.650000,-0.000000,5.950000,1.000000;; - } - - SkinWeights { - "L_Hiza"; - 119; - 3308, - 3309, - 3310, - 3311, - 3316, - 3317, - 3318, - 3319, - 3329, - 3330, - 3331, - 3332, - 3562, - 3563, - 3564, - 3565, - 3566, - 3567, - 3568, - 3569, - 3570, - 3571, - 3572, - 3573, - 3574, - 3575, - 3576, - 3577, - 3578, - 3579, - 3580, - 3581, - 3582, - 3583, - 3584, - 3585, - 3586, - 3587, - 3588, - 3589, - 3590, - 3604, - 3605, - 3606, - 3607, - 3608, - 3609, - 3610, - 3630, - 3631, - 3632, - 3633, - 3634, - 3635, - 3636, - 3637, - 3638, - 3639, - 3640, - 3641, - 3642, - 3643, - 3644, - 3645, - 3646, - 3647, - 3648, - 3649, - 3650, - 3651, - 3652, - 3653, - 3654, - 3655, - 3656, - 3657, - 3658, - 3663, - 3664, - 3665, - 3666, - 3667, - 3669, - 3670, - 3671, - 3674, - 3675, - 3676, - 3677, - 3678, - 4213, - 4214, - 4215, - 4216, - 4217, - 4218, - 4219, - 4220, - 4230, - 4231, - 4232, - 4233, - 4234, - 4245, - 4246, - 4247, - 4248, - 4249, - 4250, - 4251, - 4252, - 4255, - 4256, - 4257, - 4259, - 4260, - 4263, - 4264, - 4265; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,-0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-1.650000,-0.000000,4.550000,1.000000;; - } - - SkinWeights { - "L_Sune"; - 245; - 3041, - 3043, - 3044, - 3045, - 3046, - 3047, - 3053, - 3246, - 3247, - 3248, - 3254, - 3255, - 3268, - 3269, - 3270, - 3271, - 3272, - 3273, - 3274, - 3275, - 3276, - 3277, - 3278, - 3279, - 3280, - 3281, - 3282, - 3283, - 3284, - 3285, - 3286, - 3287, - 3288, - 3289, - 3290, - 3291, - 3292, - 3293, - 3294, - 3295, - 3296, - 3297, - 3298, - 3299, - 3300, - 3301, - 3302, - 3303, - 3304, - 3305, - 3306, - 3307, - 3312, - 3313, - 3314, - 3315, - 3320, - 3321, - 3322, - 3323, - 3324, - 3325, - 3326, - 3327, - 3328, - 3333, - 3334, - 3335, - 3341, - 3342, - 3343, - 3344, - 3345, - 3346, - 3351, - 3352, - 3353, - 3357, - 3358, - 3359, - 3360, - 3361, - 3362, - 3510, - 3511, - 3512, - 3513, - 3514, - 3515, - 3516, - 3517, - 3518, - 3519, - 3520, - 3521, - 3522, - 3523, - 3524, - 3525, - 3526, - 3527, - 3528, - 3529, - 3530, - 3531, - 3532, - 3533, - 3534, - 3535, - 3536, - 3537, - 3538, - 3539, - 3540, - 3541, - 3542, - 3543, - 3544, - 3545, - 3546, - 3547, - 3548, - 3549, - 3553, - 3554, - 3555, - 3556, - 3557, - 3558, - 3559, - 3560, - 3561, - 3591, - 3592, - 3593, - 3594, - 3595, - 3596, - 3600, - 3601, - 3602, - 3603, - 3611, - 3612, - 3613, - 3614, - 3615, - 3616, - 3617, - 3618, - 3619, - 3620, - 3621, - 3622, - 3623, - 3624, - 3625, - 3626, - 3627, - 3628, - 3629, - 3659, - 3660, - 3661, - 3662, - 3668, - 3672, - 3673, - 4178, - 4179, - 4185, - 4197, - 4198, - 4199, - 4200, - 4201, - 4202, - 4203, - 4204, - 4205, - 4206, - 4207, - 4211, - 4212, - 4221, - 4222, - 4223, - 4224, - 4225, - 4229, - 4235, - 4236, - 4237, - 4238, - 4239, - 4240, - 4241, - 4242, - 4243, - 4244, - 4729, - 4730, - 4731, - 4736, - 4737, - 4744, - 4745, - 4746, - 4747, - 4748, - 4749, - 4750, - 4751, - 4752, - 4753, - 4754, - 4755, - 4756, - 4757, - 4758, - 4759, - 4760, - 4761, - 4762, - 4763, - 4764, - 4765, - 4766, - 4767, - 4768, - 4769, - 4770, - 4771, - 4772, - 4773, - 4774, - 4775, - 4776, - 4777, - 4778, - 4779, - 4780, - 4781, - 4782, - 4783; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,-0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-1.650000,-0.000000,3.750000,1.000000;; - } - - SkinWeights { - "L_Kakato"; - 45; - 3048, - 4166, - 4167, - 4168, - 4169, - 4170, - 4171, - 4172, - 4173, - 4174, - 4175, - 4176, - 4177, - 4180, - 4181, - 4182, - 4183, - 4184, - 4186, - 4187, - 4188, - 4189, - 4190, - 4191, - 4192, - 4193, - 4194, - 4195, - 4196, - 4723, - 4724, - 4725, - 4726, - 4727, - 4728, - 4732, - 4733, - 4734, - 4735, - 4738, - 4739, - 4740, - 4741, - 4742, - 4743; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.006428,-1.612427,0.929109,1.000000;; - } - - SkinWeights { - "L_Tumasaki"; - 103; - 3039, - 3040, - 3049, - 3050, - 3051, - 3052, - 3054, - 3055, - 3056, - 3057, - 3058, - 3059, - 3060, - 3061, - 3062, - 3063, - 3064, - 3065, - 3066, - 3099, - 3100, - 3101, - 3102, - 3103, - 3104, - 3105, - 3106, - 3107, - 3108, - 3109, - 3110, - 3111, - 3112, - 3113, - 3114, - 3115, - 3116, - 3117, - 3118, - 3119, - 3120, - 3231, - 3232, - 3233, - 3234, - 3235, - 3236, - 3237, - 3238, - 3239, - 3240, - 3241, - 3242, - 3243, - 3244, - 3245, - 3249, - 3250, - 3251, - 3252, - 3253, - 3256, - 3257, - 3258, - 3259, - 3260, - 3261, - 3262, - 3263, - 3264, - 3265, - 3266, - 3267, - 3480, - 3481, - 3482, - 3483, - 3484, - 3485, - 3486, - 3487, - 3488, - 3489, - 3490, - 3491, - 3492, - 3493, - 3494, - 3495, - 3496, - 3497, - 3498, - 3499, - 3500, - 3501, - 3502, - 3503, - 3504, - 3505, - 3506, - 3507, - 3508, - 3509; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000000,1.000000,-0.000000,0.000000,0.984808,0.000000,-0.173648,0.000000,-0.173648,-0.000000,-0.984808,0.000000,-0.374465,-1.612427,0.059501,1.000000;; - } - - SkinWeights { - "R_Kata_Base"; - 56; - 1650, - 1651, - 1652, - 1653, - 1654, - 1655, - 1656, - 1657, - 1658, - 1659, - 1660, - 1661, - 1670, - 1671, - 1672, - 1673, - 1674, - 1675, - 1676, - 1677, - 1678, - 1679, - 1680, - 1681, - 1682, - 1683, - 1684, - 1685, - 1686, - 1687, - 1688, - 1689, - 1690, - 1691, - 1707, - 1708, - 1709, - 1710, - 1711, - 1712, - 1713, - 1714, - 1715, - 1716, - 1717, - 1718, - 1719, - 1720, - 1721, - 1722, - 1723, - 1724, - 1725, - 1726, - 1727, - 1728; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.064755,0.044223,-0.996921,0.000000,-0.947266,0.316913,-0.047472,0.000000,0.313838,0.947423,0.062413,0.000000,8.916395,-3.387360,-0.625533,1.000000;; - } - - SkinWeights { - "R_Ueude"; - 52; - 916, - 917, - 918, - 919, - 920, - 921, - 922, - 923, - 980, - 981, - 982, - 983, - 984, - 985, - 986, - 987, - 1552, - 1553, - 1554, - 1555, - 1556, - 1557, - 1558, - 1559, - 1560, - 1561, - 1562, - 1563, - 1564, - 1565, - 1566, - 1567, - 1568, - 1569, - 1626, - 1627, - 1628, - 1629, - 1630, - 1631, - 1632, - 1633, - 1634, - 1635, - 1636, - 1637, - 1638, - 1639, - 1640, - 1641, - 1642, - 1643; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.064755,0.044223,-0.996921,0.000000,-0.947266,0.316913,-0.047472,0.000000,0.313838,0.947423,0.062413,0.000000,8.886395,-3.397360,-1.625533,1.000000;; - } - - SkinWeights { - "R_Hizi"; - 48; - 2904, - 2905, - 2906, - 2907, - 2908, - 2909, - 2910, - 2911, - 2912, - 2913, - 2914, - 2915, - 2916, - 2917, - 2918, - 2919, - 2920, - 2921, - 2922, - 2923, - 2924, - 2925, - 2926, - 2927, - 2928, - 2929, - 2930, - 2931, - 2932, - 2933, - 2934, - 2935, - 2936, - 2937, - 2938, - 2939, - 2940, - 2941, - 2942, - 2943, - 2944, - 2945, - 2946, - 2947, - 2948, - 2949, - 2950, - 2951; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.064754,0.044223,-0.996921,0.000000,-0.947266,0.316913,-0.047471,0.000000,0.313838,0.947423,0.062413,0.000000,8.886393,-3.397360,-3.125541,1.000000;; - } - - SkinWeights { - "R_Sitaude"; - 209; - 793, - 794, - 795, - 796, - 797, - 798, - 799, - 800, - 801, - 802, - 803, - 804, - 805, - 806, - 852, - 853, - 854, - 855, - 856, - 857, - 858, - 859, - 876, - 877, - 878, - 879, - 880, - 881, - 882, - 883, - 884, - 885, - 886, - 887, - 888, - 889, - 890, - 891, - 892, - 893, - 894, - 895, - 896, - 897, - 898, - 899, - 900, - 901, - 902, - 903, - 904, - 905, - 1341, - 1342, - 1343, - 1344, - 1345, - 1346, - 1347, - 1348, - 1349, - 1350, - 1351, - 1352, - 1353, - 1354, - 1355, - 1356, - 1357, - 1358, - 1359, - 1360, - 1361, - 1362, - 1363, - 1364, - 1365, - 1366, - 1367, - 1368, - 1436, - 1437, - 1438, - 1439, - 1440, - 1441, - 1442, - 1443, - 1444, - 1445, - 1462, - 1463, - 1464, - 1465, - 1466, - 1467, - 1468, - 1469, - 1470, - 1471, - 1472, - 1473, - 1474, - 1475, - 1476, - 1477, - 1478, - 1479, - 1480, - 1481, - 1482, - 1483, - 1484, - 1485, - 1486, - 1487, - 1488, - 1489, - 1490, - 1491, - 1492, - 1493, - 1494, - 1495, - 1496, - 1497, - 1498, - 1499, - 1500, - 1501, - 1502, - 1503, - 1504, - 1505, - 1506, - 1507, - 1508, - 1509, - 1510, - 1511, - 1512, - 1513, - 1514, - 1515, - 1516, - 1517, - 1518, - 1519, - 1520, - 1521, - 1522, - 1523, - 1524, - 1525, - 1526, - 1527, - 1528, - 1529, - 1530, - 1531, - 1532, - 1533, - 1534, - 1535, - 1536, - 1537, - 1538, - 1539, - 1540, - 1541, - 1981, - 1982, - 1983, - 1984, - 1985, - 1986, - 1987, - 1988, - 1989, - 1990, - 1991, - 1992, - 1993, - 1994, - 2013, - 2014, - 2015, - 2016, - 2017, - 2018, - 2019, - 2020, - 2021, - 2022, - 2023, - 2024, - 2025, - 2026, - 2027, - 2028, - 2029, - 2030, - 2031, - 2032, - 2033, - 2034, - 2035, - 2036, - 2037; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.064754,0.044223,-0.996921,0.000000,-0.947266,0.316913,-0.047471,0.000000,0.313838,0.947423,0.062413,0.000000,8.886393,-3.397360,-3.575541,1.000000;; - } - - SkinWeights { - "R_kata_Armer"; - 220; - 932, - 933, - 934, - 935, - 936, - 937, - 938, - 939, - 940, - 941, - 942, - 943, - 944, - 945, - 946, - 947, - 948, - 949, - 950, - 951, - 952, - 953, - 954, - 988, - 989, - 990, - 991, - 992, - 993, - 994, - 995, - 996, - 997, - 998, - 999, - 1000, - 1001, - 1002, - 1003, - 1004, - 1005, - 1006, - 1007, - 1008, - 1009, - 1010, - 1011, - 1012, - 1013, - 1014, - 1015, - 1016, - 1017, - 1018, - 1019, - 1020, - 1021, - 1022, - 1023, - 1024, - 1025, - 1026, - 1027, - 1028, - 1029, - 1030, - 1031, - 1032, - 1033, - 1034, - 1119, - 1120, - 1121, - 1122, - 1123, - 1124, - 1125, - 1126, - 1127, - 1128, - 1129, - 1130, - 1131, - 1132, - 1133, - 1134, - 1135, - 1136, - 1137, - 1138, - 1139, - 1140, - 1141, - 1142, - 1143, - 1144, - 1145, - 1146, - 1147, - 1148, - 1149, - 1150, - 1151, - 1612, - 1613, - 1614, - 1615, - 1616, - 1617, - 1618, - 1619, - 1620, - 1621, - 1622, - 1623, - 1624, - 1625, - 1662, - 1663, - 1664, - 1665, - 1666, - 1667, - 1668, - 1669, - 1692, - 1693, - 1694, - 1695, - 1696, - 1697, - 1698, - 1699, - 1700, - 1701, - 1702, - 1703, - 1704, - 1731, - 1732, - 1733, - 1734, - 1735, - 1736, - 1737, - 1738, - 1739, - 1740, - 1741, - 1742, - 1743, - 1744, - 2039, - 2040, - 2041, - 2042, - 2043, - 2044, - 2045, - 2046, - 2047, - 2048, - 2049, - 2050, - 2051, - 2052, - 2053, - 2054, - 2055, - 2056, - 2057, - 2058, - 2059, - 2060, - 2061, - 2062, - 2063, - 2064, - 2065, - 2066, - 2067, - 2068, - 2069, - 2070, - 2071, - 2072, - 2073, - 2074, - 2075, - 2076, - 2077, - 2078, - 2079, - 2080, - 2182, - 2183, - 2184, - 2185, - 2186, - 2187, - 2188, - 2189, - 2190, - 2191, - 2192, - 2193, - 2194, - 2195, - 2196, - 2197, - 2198, - 2199, - 2200, - 2201, - 2202, - 2203, - 2204, - 2205, - 2206, - 2207; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.146871,0.044223,-0.988167,0.000000,-0.935984,0.316913,0.153298,0.000000,0.319942,0.947423,-0.005153,0.000000,8.457630,-3.387360,-3.077746,1.000000;; - } - - SkinWeights { - "R_Kata_S_Joint_1"; - 96; - 906, - 907, - 908, - 909, - 955, - 956, - 957, - 958, - 959, - 960, - 1542, - 1543, - 1544, - 1545, - 1594, - 1595, - 1596, - 1597, - 1598, - 1599, - 2952, - 2953, - 2954, - 2955, - 2956, - 2957, - 2958, - 2959, - 2960, - 2961, - 2962, - 2963, - 2964, - 2965, - 2966, - 2967, - 2968, - 2969, - 2970, - 2971, - 2972, - 2973, - 2974, - 2975, - 2976, - 2977, - 2978, - 2979, - 2980, - 2981, - 2982, - 2983, - 2984, - 2985, - 2986, - 2987, - 2988, - 2989, - 2990, - 2991, - 2992, - 2993, - 2994, - 2995, - 2996, - 2997, - 2998, - 2999, - 3000, - 3001, - 3002, - 3003, - 3004, - 3005, - 3006, - 3007, - 3008, - 3009, - 3010, - 3011, - 3012, - 3013, - 3014, - 3015, - 3016, - 3017, - 3018, - 3019, - 3020, - 3021, - 3022, - 3023, - 3024, - 3025, - 3026, - 3027; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.025210,0.044223,-0.998703,0.000000,-0.948403,0.316913,-0.009907,0.000000,0.316064,0.947423,0.049931,0.000000,9.117301,-3.387360,-3.047236,1.000000;; - } - - SkinWeights { - "R_kata_S_Joint_2"; - 62; - 860, - 861, - 862, - 863, - 864, - 865, - 910, - 911, - 912, - 913, - 914, - 915, - 961, - 962, - 963, - 964, - 965, - 966, - 967, - 968, - 969, - 970, - 971, - 972, - 973, - 974, - 975, - 976, - 977, - 978, - 979, - 1546, - 1547, - 1548, - 1549, - 1550, - 1551, - 1600, - 1601, - 1602, - 1603, - 1604, - 1605, - 1606, - 1607, - 1608, - 1609, - 1610, - 1611, - 1644, - 1645, - 1646, - 1647, - 1648, - 1649, - 1995, - 1996, - 1997, - 1998, - 1999, - 2000, - 2038; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.025210,0.044223,-0.998703,0.000000,-0.948403,0.316913,-0.009907,0.000000,0.316064,0.947423,0.049931,0.000000,9.117301,-3.387360,-4.397236,1.000000;; - } - - SkinWeights { - "R_Kata_S_End"; - 98; - 729, - 730, - 731, - 732, - 733, - 734, - 866, - 867, - 868, - 869, - 870, - 871, - 872, - 873, - 874, - 875, - 1089, - 1090, - 1091, - 1092, - 1093, - 1094, - 1095, - 1096, - 1097, - 1098, - 1099, - 1100, - 1101, - 1102, - 1103, - 1104, - 1105, - 1106, - 1107, - 1108, - 1109, - 1110, - 1111, - 1112, - 1113, - 1114, - 1115, - 1116, - 1117, - 1118, - 1894, - 1895, - 1896, - 1897, - 1898, - 1899, - 1900, - 1901, - 1902, - 1903, - 2001, - 2002, - 2003, - 2004, - 2005, - 2006, - 2007, - 2008, - 2009, - 2010, - 2011, - 2012, - 2152, - 2153, - 2154, - 2155, - 2156, - 2157, - 2158, - 2159, - 2160, - 2161, - 2162, - 2163, - 2164, - 2165, - 2166, - 2167, - 2168, - 2169, - 2170, - 2171, - 2172, - 2173, - 2174, - 2175, - 2176, - 2177, - 2178, - 2179, - 2180, - 2181; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.998703,0.044223,0.025210,0.000000,0.009907,0.316913,-0.948403,0.000000,-0.049931,0.947423,0.316064,0.000000,5.747236,-3.387360,9.117301,1.000000;; - } - - SkinWeights { - "R_Hand"; - 440; - 807, - 808, - 809, - 810, - 811, - 812, - 813, - 814, - 815, - 816, - 817, - 818, - 819, - 820, - 821, - 822, - 823, - 824, - 825, - 826, - 827, - 828, - 829, - 830, - 831, - 832, - 833, - 834, - 835, - 836, - 837, - 838, - 839, - 840, - 841, - 842, - 843, - 844, - 845, - 846, - 847, - 848, - 849, - 850, - 851, - 924, - 925, - 926, - 927, - 928, - 929, - 930, - 931, - 1369, - 1370, - 1371, - 1372, - 1373, - 1374, - 1375, - 1376, - 1377, - 1378, - 1379, - 1380, - 1381, - 1382, - 1383, - 1384, - 1385, - 1386, - 1387, - 1388, - 1389, - 1390, - 1391, - 1392, - 1393, - 1394, - 1395, - 1396, - 1397, - 1398, - 1399, - 1400, - 1401, - 1402, - 1403, - 1404, - 1405, - 1406, - 1407, - 1408, - 1409, - 1410, - 1411, - 1412, - 1413, - 1414, - 1415, - 1416, - 1417, - 1418, - 1419, - 1420, - 1421, - 1422, - 1423, - 1424, - 1425, - 1426, - 1427, - 1428, - 1429, - 1430, - 1431, - 1432, - 1433, - 1434, - 1435, - 1446, - 1447, - 1448, - 1449, - 1450, - 1451, - 1452, - 1453, - 1454, - 1455, - 1456, - 1457, - 1458, - 1459, - 1460, - 1461, - 1570, - 1571, - 1572, - 1573, - 1574, - 1575, - 1576, - 1577, - 1578, - 1579, - 1580, - 1581, - 1582, - 1583, - 1584, - 1585, - 1586, - 1587, - 1588, - 1589, - 1590, - 1591, - 1592, - 1593, - 2552, - 2553, - 2554, - 2555, - 2556, - 2557, - 2558, - 2559, - 2560, - 2561, - 2562, - 2563, - 2564, - 2565, - 2566, - 2567, - 2568, - 2569, - 2570, - 2571, - 2572, - 2573, - 2574, - 2575, - 2576, - 2577, - 2578, - 2579, - 2580, - 2581, - 2582, - 2583, - 2584, - 2585, - 2586, - 2587, - 2588, - 2589, - 2590, - 2591, - 2592, - 2593, - 2594, - 2595, - 2596, - 2597, - 2598, - 2599, - 2600, - 2601, - 2602, - 2603, - 2604, - 2605, - 2606, - 2607, - 2608, - 2609, - 2610, - 2611, - 2612, - 2613, - 2614, - 2615, - 2616, - 2617, - 2618, - 2619, - 2620, - 2621, - 2622, - 2623, - 2624, - 2625, - 2626, - 2627, - 2628, - 2629, - 2630, - 2631, - 2632, - 2633, - 2634, - 2635, - 2636, - 2637, - 2638, - 2639, - 2640, - 2641, - 2642, - 2643, - 2644, - 2645, - 2646, - 2647, - 2648, - 2649, - 2650, - 2651, - 2652, - 2653, - 2654, - 2655, - 2656, - 2657, - 2658, - 2659, - 2660, - 2661, - 2662, - 2663, - 2664, - 2665, - 2666, - 2667, - 2668, - 2669, - 2670, - 2671, - 2672, - 2673, - 2674, - 2675, - 2676, - 2677, - 2678, - 2679, - 2680, - 2681, - 2682, - 2683, - 2684, - 2685, - 2686, - 2687, - 2688, - 2689, - 2690, - 2691, - 2692, - 2693, - 2694, - 2695, - 2696, - 2697, - 2698, - 2699, - 2700, - 2701, - 2702, - 2703, - 2704, - 2705, - 2706, - 2707, - 2708, - 2709, - 2710, - 2711, - 2712, - 2713, - 2714, - 2715, - 2716, - 2717, - 2718, - 2719, - 2720, - 2721, - 2722, - 2723, - 2724, - 2725, - 2726, - 2727, - 2728, - 2729, - 2730, - 2731, - 2732, - 2733, - 2734, - 2735, - 2736, - 2737, - 2738, - 2739, - 2740, - 2741, - 2742, - 2743, - 2744, - 2745, - 2746, - 2747, - 2748, - 2749, - 2750, - 2751, - 2752, - 2753, - 2754, - 2755, - 2756, - 2757, - 2758, - 2759, - 2760, - 2761, - 2762, - 2763, - 2764, - 2765, - 2766, - 2767, - 2768, - 2769, - 2770, - 2771, - 2772, - 2773, - 2774, - 2775, - 2776, - 2777, - 2778, - 2779, - 2780, - 2781, - 2782, - 2783, - 2784, - 2785, - 2786, - 2787, - 2788, - 2789, - 2790, - 2791, - 2792, - 2793, - 2794, - 2795, - 2796, - 2797, - 2798, - 2799, - 2800, - 2801, - 2802, - 2803, - 2804, - 2805, - 2806, - 2807, - 2808, - 2809, - 2810, - 2811, - 2812, - 2813, - 2814, - 2815, - 2816, - 2817, - 2818, - 2819, - 2820, - 2821, - 2822, - 2823, - 2824, - 2825, - 2826, - 2827, - 2828, - 2829, - 2830, - 2831; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.064754,0.044223,-0.996921,0.000000,-0.947266,0.316913,-0.047471,0.000000,0.313838,0.947423,0.062413,0.000000,8.886393,-3.397360,-5.575541,1.000000;; - } - - SkinWeights { - "R_momo"; - 285; - 36, - 129, - 130, - 131, - 132, - 133, - 134, - 135, - 136, - 358, - 359, - 360, - 361, - 362, - 369, - 370, - 371, - 372, - 376, - 377, - 378, - 402, - 403, - 404, - 405, - 406, - 407, - 408, - 409, - 410, - 411, - 412, - 413, - 414, - 415, - 416, - 417, - 418, - 419, - 600, - 601, - 602, - 647, - 648, - 649, - 735, - 1275, - 1276, - 1277, - 1293, - 1294, - 1295, - 1320, - 1321, - 1325, - 1328, - 1329, - 1862, - 1863, - 1864, - 1865, - 1866, - 1867, - 1868, - 1869, - 1870, - 1871, - 1872, - 1873, - 1904, - 1905, - 1906, - 1907, - 1908, - 1909, - 1910, - 1911, - 1912, - 1913, - 1914, - 1915, - 1916, - 2411, - 2412, - 2413, - 2414, - 2415, - 2416, - 2417, - 2418, - 2419, - 2420, - 2421, - 2422, - 2423, - 2424, - 2425, - 2426, - 2427, - 2428, - 2429, - 2430, - 2431, - 2432, - 2433, - 2434, - 2435, - 2436, - 2437, - 2438, - 2439, - 2440, - 2441, - 2442, - 2443, - 2444, - 2445, - 2446, - 2447, - 2448, - 2449, - 2450, - 2451, - 2452, - 2453, - 2454, - 2455, - 2456, - 2457, - 2458, - 2459, - 2460, - 2461, - 2462, - 2463, - 2464, - 5891, - 5892, - 5893, - 5894, - 5895, - 5896, - 5897, - 5898, - 5899, - 5900, - 5901, - 5902, - 5903, - 5904, - 5905, - 5906, - 5907, - 5908, - 5909, - 5910, - 5911, - 5912, - 5913, - 5914, - 5915, - 5916, - 5917, - 5918, - 5919, - 5920, - 5921, - 5922, - 5923, - 5924, - 5925, - 5926, - 5927, - 5928, - 5929, - 5930, - 5931, - 5932, - 5933, - 5934, - 5935, - 5936, - 5937, - 5938, - 5939, - 5940, - 5941, - 5942, - 5943, - 5944, - 5945, - 5946, - 5947, - 5948, - 5949, - 5950, - 5951, - 5952, - 5953, - 5954, - 5955, - 5956, - 5957, - 5958, - 5959, - 5960, - 5961, - 5962, - 5963, - 5964, - 5965, - 5966, - 5967, - 5968, - 5969, - 5970, - 5971, - 5972, - 5973, - 5974, - 5975, - 5976, - 5977, - 5978, - 5979, - 5980, - 5981, - 5982, - 5983, - 5984, - 5985, - 5986, - 5987, - 5988, - 5989, - 5990, - 5991, - 5992, - 5993, - 5994, - 5995, - 5996, - 5997, - 5998, - 5999, - 6000, - 6001, - 6002, - 6003, - 6004, - 6005, - 6006, - 6007, - 6008, - 6009, - 6010, - 6011, - 6012, - 6013, - 6014, - 6015, - 6016, - 6017, - 6018, - 6019, - 6020, - 6021, - 6022, - 6023, - 6024, - 6025, - 6026, - 6027, - 6028, - 6029, - 6030, - 6031, - 6032, - 6033, - 6034, - 6035, - 6036, - 6037, - 6038, - 6039; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,1.650000,-0.000000,5.950000,1.000000;; - } - - SkinWeights { - "R_Hiza"; - 119; - 330, - 331, - 332, - 333, - 338, - 339, - 340, - 341, - 351, - 352, - 353, - 354, - 612, - 613, - 614, - 615, - 616, - 617, - 618, - 619, - 620, - 621, - 622, - 623, - 624, - 625, - 626, - 627, - 628, - 629, - 630, - 631, - 632, - 633, - 634, - 635, - 636, - 637, - 638, - 639, - 640, - 654, - 655, - 656, - 657, - 658, - 659, - 660, - 680, - 681, - 682, - 683, - 684, - 685, - 686, - 687, - 688, - 689, - 690, - 691, - 692, - 693, - 694, - 695, - 696, - 697, - 698, - 699, - 700, - 701, - 702, - 703, - 704, - 705, - 706, - 707, - 708, - 713, - 714, - 715, - 716, - 717, - 719, - 720, - 721, - 724, - 725, - 726, - 727, - 728, - 1280, - 1281, - 1282, - 1283, - 1284, - 1285, - 1286, - 1287, - 1297, - 1298, - 1299, - 1300, - 1301, - 1312, - 1313, - 1314, - 1315, - 1316, - 1317, - 1318, - 1319, - 1322, - 1323, - 1324, - 1326, - 1327, - 1330, - 1331, - 1332; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,1.650000,-0.000000,4.550000,1.000000;; - } - - SkinWeights { - "R_Sune"; - 245; - 35, - 37, - 38, - 39, - 40, - 41, - 47, - 268, - 269, - 270, - 276, - 277, - 290, - 291, - 292, - 293, - 294, - 295, - 296, - 297, - 298, - 299, - 300, - 301, - 302, - 303, - 304, - 305, - 306, - 307, - 308, - 309, - 310, - 311, - 312, - 313, - 314, - 315, - 316, - 317, - 318, - 319, - 320, - 321, - 322, - 323, - 324, - 325, - 326, - 327, - 328, - 329, - 334, - 335, - 336, - 337, - 342, - 343, - 344, - 345, - 346, - 347, - 348, - 349, - 350, - 355, - 356, - 357, - 363, - 364, - 365, - 366, - 367, - 368, - 373, - 374, - 375, - 379, - 380, - 381, - 382, - 383, - 384, - 560, - 561, - 562, - 563, - 564, - 565, - 566, - 567, - 568, - 569, - 570, - 571, - 572, - 573, - 574, - 575, - 576, - 577, - 578, - 579, - 580, - 581, - 582, - 583, - 584, - 585, - 586, - 587, - 588, - 589, - 590, - 591, - 592, - 593, - 594, - 595, - 596, - 597, - 598, - 599, - 603, - 604, - 605, - 606, - 607, - 608, - 609, - 610, - 611, - 641, - 642, - 643, - 644, - 645, - 646, - 650, - 651, - 652, - 653, - 661, - 662, - 663, - 664, - 665, - 666, - 667, - 668, - 669, - 670, - 671, - 672, - 673, - 674, - 675, - 676, - 677, - 678, - 679, - 709, - 710, - 711, - 712, - 718, - 722, - 723, - 1245, - 1246, - 1252, - 1264, - 1265, - 1266, - 1267, - 1268, - 1269, - 1270, - 1271, - 1272, - 1273, - 1274, - 1278, - 1279, - 1288, - 1289, - 1290, - 1291, - 1292, - 1296, - 1302, - 1303, - 1304, - 1305, - 1306, - 1307, - 1308, - 1309, - 1310, - 1311, - 1807, - 1808, - 1809, - 1814, - 1815, - 1822, - 1823, - 1824, - 1825, - 1826, - 1827, - 1828, - 1829, - 1830, - 1831, - 1832, - 1833, - 1834, - 1835, - 1836, - 1837, - 1838, - 1839, - 1840, - 1841, - 1842, - 1843, - 1844, - 1845, - 1846, - 1847, - 1848, - 1849, - 1850, - 1851, - 1852, - 1853, - 1854, - 1855, - 1856, - 1857, - 1858, - 1859, - 1860, - 1861; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,1.650000,-0.000000,3.750000,1.000000;; - } - - SkinWeights { - "R_Kakato"; - 45; - 42, - 1233, - 1234, - 1235, - 1236, - 1237, - 1238, - 1239, - 1240, - 1241, - 1242, - 1243, - 1244, - 1247, - 1248, - 1249, - 1250, - 1251, - 1253, - 1254, - 1255, - 1256, - 1257, - 1258, - 1259, - 1260, - 1261, - 1262, - 1263, - 1801, - 1802, - 1803, - 1804, - 1805, - 1806, - 1810, - 1811, - 1812, - 1813, - 1816, - 1817, - 1818, - 1819, - 1820, - 1821; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,1.650000,0.856365,1.000000;; - } - - SkinWeights { - "R_Tumasaki"; - 103; - 29, - 30, - 43, - 44, - 45, - 46, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120, - 121, - 122, - 123, - 124, - 125, - 126, - 127, - 128, - 253, - 254, - 255, - 256, - 257, - 258, - 259, - 260, - 261, - 262, - 263, - 264, - 265, - 266, - 267, - 271, - 272, - 273, - 274, - 275, - 278, - 279, - 280, - 281, - 282, - 283, - 284, - 285, - 286, - 287, - 288, - 289, - 530, - 531, - 532, - 533, - 534, - 535, - 536, - 537, - 538, - 539, - 540, - 541, - 542, - 543, - 544, - 545, - 546, - 547, - 548, - 549, - 550, - 551, - 552, - 553, - 554, - 555, - 556, - 557, - 558, - 559; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - -0.000000,1.000000,-0.000000,0.000000,0.984808,0.000000,-0.173648,0.000000,-0.173648,-0.000000,-0.984808,0.000000,-0.301711,1.650000,0.053200,1.000000;; - } - - SkinWeights { - "Bone_Head"; - 410; - 14, - 15, - 16, - 17, - 18, - 479, - 480, - 481, - 482, - 483, - 484, - 485, - 486, - 487, - 488, - 489, - 490, - 491, - 492, - 493, - 494, - 495, - 496, - 497, - 498, - 499, - 500, - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520, - 521, - 522, - 523, - 524, - 525, - 526, - 527, - 528, - 1164, - 1165, - 1166, - 1167, - 1168, - 1169, - 1170, - 1171, - 1172, - 1173, - 1174, - 1175, - 1176, - 1177, - 1178, - 1179, - 1180, - 1181, - 1182, - 1183, - 1184, - 1185, - 1186, - 1187, - 1188, - 1189, - 1190, - 1191, - 1192, - 1193, - 1194, - 1195, - 1196, - 1197, - 1198, - 1199, - 1200, - 1201, - 1202, - 1203, - 1204, - 1205, - 1206, - 1207, - 1208, - 1209, - 1210, - 1211, - 1212, - 1213, - 1214, - 1215, - 1216, - 1217, - 1218, - 1219, - 1220, - 1221, - 1222, - 1223, - 1224, - 1225, - 1226, - 1227, - 1228, - 1229, - 1230, - 1231, - 1232, - 1753, - 1754, - 1755, - 1756, - 1757, - 1758, - 1759, - 1760, - 1761, - 1762, - 1763, - 1764, - 1765, - 1766, - 1767, - 1768, - 1769, - 1770, - 1771, - 1772, - 1773, - 1774, - 1775, - 1776, - 1777, - 1778, - 1779, - 1780, - 1781, - 1782, - 1783, - 1784, - 1785, - 1786, - 1787, - 1788, - 1789, - 1790, - 1791, - 1792, - 1793, - 1794, - 1795, - 1796, - 2214, - 2215, - 2216, - 2217, - 2218, - 2219, - 2220, - 2221, - 2222, - 2223, - 2224, - 2225, - 2226, - 2227, - 2228, - 2229, - 2230, - 2231, - 2232, - 2233, - 2234, - 2235, - 2236, - 2237, - 2238, - 2239, - 2240, - 2241, - 2242, - 2243, - 2244, - 2245, - 2246, - 2247, - 2248, - 2249, - 2315, - 2316, - 2317, - 2318, - 2319, - 2320, - 2321, - 2322, - 2323, - 2324, - 2325, - 2326, - 2327, - 2328, - 2329, - 2330, - 2331, - 2332, - 2333, - 2334, - 2335, - 3036, - 3440, - 3441, - 3442, - 3443, - 3444, - 3445, - 3446, - 3447, - 3448, - 3449, - 3450, - 3451, - 3452, - 3453, - 3454, - 3455, - 3456, - 3457, - 3458, - 3459, - 3460, - 3461, - 3462, - 3463, - 3464, - 3465, - 3466, - 3467, - 3468, - 3469, - 3470, - 3471, - 3472, - 3473, - 3474, - 3475, - 3476, - 3477, - 3478, - 3479, - 4108, - 4109, - 4110, - 4111, - 4112, - 4113, - 4114, - 4115, - 4116, - 4117, - 4118, - 4119, - 4120, - 4121, - 4122, - 4123, - 4124, - 4125, - 4126, - 4127, - 4128, - 4129, - 4130, - 4131, - 4132, - 4133, - 4134, - 4135, - 4136, - 4137, - 4138, - 4139, - 4140, - 4141, - 4142, - 4143, - 4144, - 4145, - 4146, - 4147, - 4148, - 4149, - 4150, - 4151, - 4152, - 4153, - 4154, - 4155, - 4156, - 4157, - 4158, - 4159, - 4160, - 4161, - 4162, - 4163, - 4164, - 4165, - 4686, - 4687, - 4688, - 4689, - 4690, - 4691, - 4692, - 4693, - 4694, - 4695, - 4696, - 4697, - 4698, - 4699, - 4700, - 4701, - 4702, - 4703, - 4704, - 4705, - 4706, - 4707, - 4708, - 4709, - 4710, - 4711, - 4712, - 4713, - 4714, - 4715, - 4716, - 4717, - 4718, - 4719, - 4720, - 4721, - 4722, - 5118, - 5119, - 5120, - 5121, - 5122, - 5123, - 5124, - 5125, - 5126, - 5127, - 5128, - 5129, - 5130, - 5131, - 5132, - 5133, - 5134, - 5135, - 5136, - 5137, - 5138, - 5139, - 5140, - 5141, - 5142, - 5143, - 5144, - 5145, - 5146, - 5147, - 5211, - 5212, - 5213, - 5214, - 5215, - 5216, - 5217, - 5218, - 5219, - 5220, - 5221, - 5222, - 5223, - 5224, - 5225, - 5226, - 6191, - 6192, - 6193; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 0.001465,0.999999,0.000000,0.000000,0.999999,-0.001465,-0.000000,0.000000,-0.000000,0.000000,-1.000000,0.000000,-11.007184,0.014063,0.000000,1.000000;; - } - - SkinWeights { - "BarniaBaseR"; - 80; - 2465, - 2466, - 2467, - 2468, - 2469, - 2470, - 2471, - 2472, - 2473, - 2474, - 2475, - 2476, - 2477, - 2478, - 2479, - 2480, - 2481, - 2482, - 2483, - 2484, - 2485, - 2486, - 2487, - 2488, - 2489, - 2490, - 2491, - 2492, - 2493, - 2494, - 2495, - 2496, - 2497, - 2498, - 2499, - 2500, - 2501, - 2502, - 2503, - 2504, - 2505, - 2506, - 2507, - 2508, - 2509, - 2510, - 2511, - 2512, - 5344, - 5345, - 5346, - 5347, - 5348, - 5349, - 5350, - 5351, - 5352, - 5353, - 5354, - 5355, - 5356, - 5357, - 5358, - 5359, - 5360, - 5361, - 5362, - 5363, - 5364, - 5365, - 5366, - 5367, - 5368, - 5369, - 5370, - 5371, - 5372, - 5373, - 5374, - 5375; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,-0.000000,0.000000,0.000000,0.000000,0.998290,-0.058451,0.000000,0.000000,0.058451,0.998290,0.000000,-0.000000,-9.583588,-1.987662,1.000000;; - } - - SkinWeights { - "BarniaBaseL"; - 80; - 31, - 32, - 33, - 34, - 2309, - 2310, - 2311, - 2312, - 2313, - 2314, - 2361, - 2362, - 2363, - 2364, - 2365, - 2366, - 2367, - 2368, - 2369, - 2370, - 2371, - 2372, - 2373, - 2374, - 2375, - 2376, - 2377, - 2378, - 2379, - 2380, - 2381, - 2382, - 2383, - 2384, - 2385, - 2386, - 2387, - 2388, - 2389, - 2390, - 2391, - 2392, - 2393, - 2394, - 2395, - 2396, - 2397, - 2398, - 5205, - 5206, - 5207, - 5208, - 5209, - 5210, - 5252, - 5253, - 5254, - 5255, - 5256, - 5257, - 5258, - 5259, - 5260, - 5261, - 5262, - 5263, - 5264, - 5265, - 5266, - 5267, - 5268, - 5269, - 5270, - 5271, - 5272, - 5273, - 5274, - 5275, - 5276, - 5277; - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000, - 1.000000; - 1.000000,-0.000000,-0.000000,0.000000,0.000000,0.999678,-0.025383,0.000000,0.000000,0.025383,0.999678,0.000000,-0.000000,-8.745961,-1.851950,1.000000;; - } - } - - Frame Bone01 { - - FrameTransformMatrix { - 0.000000,-0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,6.600000,0.000000,1.000000;; - } - - Frame L_Mune_A { - - FrameTransformMatrix { - 0.000000,-0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,3.000000,1.000000;; - } - - Frame L_Kata_Base { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.150000,0.450000,1.051190,1.000000;; - } - - Frame L_Ueude { - - FrameTransformMatrix { - 1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.030000,0.010000,0.800000,1.000000;; - } - - Frame L_Hizi { - - FrameTransformMatrix { - 1.000000,0.000000,-0.000001,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000001,0.000000,1.000000,0.000000,-0.000000,0.000000,1.500000,1.000000;; - } - - Frame L_Sitaude { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.450000,1.000000;; - } - - Frame L_Hand { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.280000,2.000000,1.000000;; - } - - Frame L_Wpn { - - FrameTransformMatrix { - 0.999848,0.000000,-0.017452,0.000000,0.000000,1.000000,0.000000,0.000000,0.017452,0.000000,0.999848,0.000000,0.000000,0.000000,0.800001,1.000000;; - } - } - } - } - } - } - - Frame L_kata_Armer { - - FrameTransformMatrix { - 0.972082,-0.000000,-0.234641,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.234641,0.000000,0.972082,0.000000,-0.050000,-0.000000,0.800000,1.000000;; - } - - Frame L_Kata_S_Joint_1 { - - FrameTransformMatrix { - 0.979925,0.000000,0.199368,0.000000,0.000000,1.000000,0.000000,0.000000,-0.199368,0.000000,0.979925,0.000000,0.000000,-0.000000,1.491643,1.000000;; - } - - Frame L_kata_S_Joint_2 { - - FrameTransformMatrix { - 1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,1.350000,1.000000;; - } - - Frame L_Kata_S_End { - - FrameTransformMatrix { - -0.000000,-0.000000,1.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.350000,1.000000;; - } - } - } - } - } - } - - Frame L_Mune_A2 { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.051190,1.000000;; - } - } - } - - Frame R_Mune { - - FrameTransformMatrix { - -0.000000,-0.000000,-1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,3.000000,1.000000;; - } - - Frame R_Mune2 { - - FrameTransformMatrix { - 0.999848,0.000000,0.017452,0.000000,0.000000,1.000000,0.000000,0.000000,-0.017452,0.000000,0.999848,0.000000,0.000000,0.000000,1.051190,1.000000;; - } - - Frame R_Kata_Base { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.110000,0.450000,0.000000,1.000000;; - } - - Frame R_Ueude { - - FrameTransformMatrix { - 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.030000,0.010000,0.800000,1.000000;; - } - - Frame R_Hizi { - - FrameTransformMatrix { - 1.000000,-0.000000,0.000001,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000001,0.000000,1.000000,0.000000,-0.000000,-0.000000,1.500000,1.000000;; - } - - Frame R_Sitaude { - - FrameTransformMatrix { - 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.450000,1.000000;; - } - - Frame R_Hand { - - FrameTransformMatrix { - 1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,2.000000,1.000000;; - } - - Frame R_Wpn2 { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.100000,-0.265000,0.600000,1.000000;; - } - } - } - } - } - } - - Frame R_kata_Armer { - - FrameTransformMatrix { - 0.977525,0.000000,0.210820,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.210820,0.000000,0.977525,0.000000,-0.050000,0.000000,0.800000,1.000000;; - } - - Frame R_Kata_S_Joint_1 { - - FrameTransformMatrix { - 0.985109,0.000000,-0.171929,0.000000,0.000000,1.000000,0.000000,0.000000,0.171929,0.000000,0.985109,0.000000,0.000000,0.000000,1.491643,1.000000;; - } - - Frame R_kata_S_Joint_2 { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.350000,1.000000;; - } - - Frame R_Kata_S_End { - - FrameTransformMatrix { - 0.000000,-0.000000,-1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.350000,1.000000;; - } - } - } - } - } - } - } - } - - Frame Bone_neck { - - FrameTransformMatrix { - 1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,3.000000,1.000000;; - } - - Frame Bone_Head { - - FrameTransformMatrix { - 0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.407194,1.000000;; - } - } - } - - Frame SW2_R_mp { - - FrameTransformMatrix { - 0.732543,0.000000,-0.680721,0.000000,0.000000,1.000000,0.000000,0.000000,0.680721,0.000000,0.732543,0.000000,1.300000,-1.000000,3.000000,1.000000;; - } - - Frame SW2_R_mp_2 { - - FrameTransformMatrix { - -0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,1.000000;; - } - } - } - - Frame SW2_L_mp { - - FrameTransformMatrix { - 0.732543,0.000000,-0.680721,0.000000,0.000000,1.000000,0.000000,0.000000,0.680721,0.000000,0.732543,0.000000,1.300000,1.000000,3.000000,1.000000;; - } - - Frame SW2_L_mp_2 { - - FrameTransformMatrix { - -0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,1.000000;; - } - } - } - - Frame M_barnia1_1 { - - FrameTransformMatrix { - -0.058452,0.000000,-0.998290,0.000000,0.017423,0.999848,-0.001020,0.000000,0.998138,-0.017452,-0.058443,0.000000,0.000000,0.000000,3.000000,1.000000;; - } - - Frame M_barnia1_2 { - - FrameTransformMatrix { - 0.029667,0.000000,0.999560,0.000000,0.000000,1.000000,0.000000,0.000000,-0.999560,0.000000,0.029667,0.000000,0.000000,0.000000,2.548788,1.000000;; - } - - Frame BarniaBaseR { - - FrameTransformMatrix { - -0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.033058,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; - } - - Frame BarniaBaseR_2 { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,0.999848,0.017452,0.000000,0.000000,-0.017452,0.999848,0.000000,0.000000,0.000000,0.500000,1.000000;; - } - } - } - } - } - - Frame M_barnia2_1 { - - FrameTransformMatrix { - -0.399620,0.000000,-0.916681,0.000000,0.015998,0.999848,-0.006974,0.000000,0.916541,-0.017452,-0.399560,0.000000,0.000000,0.000000,3.000000,1.000000;; - } - - Frame M_barnia2_2 { - - FrameTransformMatrix { - -0.277314,0.000000,0.960779,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.960779,-0.000000,-0.277314,0.000000,0.000000,0.000000,2.261806,1.000000;; - } - - Frame BarniaBaseL { - - FrameTransformMatrix { - -0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.033058,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;; - } - - Frame BarniaBaseL_2 { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,0.999848,0.017452,0.000000,0.000000,-0.017452,0.999848,0.000000,0.000000,0.000000,0.500000,1.000000;; - } - } - } - } - } - } - - Frame Kosi { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,6.600000,0.000000,1.000000;; - } - - Frame L_Kosi_Momo { - - FrameTransformMatrix { - -0.000000,-0.017452,-0.999848,0.000000,-0.000000,0.999848,-0.017452,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,0.650000,1.000000;; - } - - Frame L_momo { - - FrameTransformMatrix { - 0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.650000,1.000000;; - } - - Frame L_Hiza { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.400000,1.000000;; - } - - Frame L_Sune { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.800000,1.000000;; - } - - Frame L_Kakato { - - FrameTransformMatrix { - 0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.037573,-0.006428,2.820891,1.000000;; - } - - Frame L_Tumasaki { - - FrameTransformMatrix { - 0.173648,0.000000,-0.984808,0.000000,0.000000,1.000000,0.000000,0.000000,0.984808,0.000000,0.173648,0.000000,-0.000000,-0.000000,0.550000,1.000000;; - } - } - } - } - } - } - } - - Frame R_Kosi_Momo { - - FrameTransformMatrix { - -0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,0.650000,1.000000;; - } - - Frame R_momo { - - FrameTransformMatrix { - 0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.650000,1.000000;; - } - - Frame R_Hiza { - - FrameTransformMatrix { - 1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,1.400000,1.000000;; - } - - Frame R_Sune { - - FrameTransformMatrix { - 1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.800000,1.000000;; - } - - Frame R_Kakato { - - FrameTransformMatrix { - -0.000000,-1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,2.893634,1.000000;; - } - - Frame R_Tumasaki { - - FrameTransformMatrix { - 0.173648,0.000000,-0.984808,0.000000,0.000000,1.000000,0.000000,0.000000,0.984808,0.000000,0.173648,0.000000,-0.000000,-0.000000,0.550000,1.000000;; - } - } - } - } - } - } - } - } - } -} diff --git a/examples/models/xfile/attack.x b/examples/models/xfile/attack.x deleted file mode 100644 index 46f59f79b00240..00000000000000 --- a/examples/models/xfile/attack.x +++ /dev/null @@ -1,1725 +0,0 @@ -xof 0303txt 0032 - -AnimationSet attack { - - Animation Animation0 { - { AllPutting_2_Layer1 } - AnimationKey { - 0; - 6; - 0;4;0.987841,0.012387,0.150064,-0.038708;;, - 20;4;0.976107,-0.000000,0.217292,0.000000;;, - 30;4;0.976107,0.000000,0.217291,0.000000;;, - 35;4;0.995480,0.000000,0.094977,0.000000;;, - 60;4;0.994613,0.002604,0.103625,0.000271;;, - 90;4;0.999177,-0.000502,-0.013080,-0.038385;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,5.856758,-0.062740;;, - 20;3;0.000000,5.845902,-0.091000;;, - 30;3;0.000000,5.845902,-0.091000;;, - 35;3;0.000000,6.225361,-0.091000;;, - 60;3;0.000000,6.313510,-0.091000;;, - 90;3;0.000000,5.938871,-0.091000;;; - } - } - - Animation Animation1 { - { Bone01 } - AnimationKey { - 0; - 6; - 0;4;0.451257,0.487074,0.550830,0.505679;;, - 20;4;0.272745,0.364789,0.758306,0.466381;;, - 30;4;0.272745,0.364789,0.758306,0.466381;;, - 35;4;0.653986,0.646423,0.294823,0.259845;;, - 60;4;0.670031,0.660427,0.254645,0.223720;;, - 90;4;0.681220,0.670043,0.224849,0.190853;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,6.600000,0.000000;;, - 20;3;0.000000,6.600000,0.000000;;, - 30;3;0.000000,6.600000,0.000000;;, - 35;3;0.000000,6.600000,0.000000;;, - 60;3;0.000000,6.600000,0.000000;;, - 90;3;0.000000,6.600000,0.000000;;; - } - } - - Animation Animation2 { - { L_Mune_A } - AnimationKey { - 0; - 6; - 0;4;0.511753,0.487964,0.487964,0.511753;;, - 20;4;0.511753,0.487964,0.487964,0.511753;;, - 30;4;0.511753,0.487964,0.487964,0.511753;;, - 35;4;0.511753,0.487964,0.487964,0.511753;;, - 60;4;0.511753,0.487964,0.487964,0.511753;;, - 90;4;0.511753,0.487964,0.487964,0.511753;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 30;3;0.000000,0.000000,3.000000;;, - 35;3;0.000000,0.000000,3.000000;;, - 60;3;0.000000,0.000000,3.000000;;, - 90;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation3 { - { L_Kata_Base } - AnimationKey { - 0; - 9; - 0;4;0.978161,0.004560,-0.006265,0.207702;;, - 20;4;0.976765,0.031387,0.003479,0.211972;;, - 30;4;0.976765,0.031387,0.003479,0.211972;;, - 31;4;0.985447,0.035415,-0.017560,-0.165323;;, - 32;4;0.866654,0.029761,-0.046497,-0.495846;;, - 33;4;0.800810,0.024557,-0.067449,-0.594601;;, - 35;4;0.771915,0.021256,-0.092849,-0.628549;;, - 60;4;0.699105,0.010164,-0.102947,-0.707496;;, - 90;4;0.771916,0.021256,-0.092849,-0.628549;;; - } - AnimationKey { - 1; - 9; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 31;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;, - 33;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 9; - 0;3;-0.150000,0.450000,1.051190;;, - 20;3;-0.150000,0.450000,1.051190;;, - 30;3;-0.150000,0.450000,1.051190;;, - 31;3;-0.150000,0.450000,1.051190;;, - 32;3;-0.150000,0.450000,1.051190;;, - 33;3;-0.150000,0.450000,1.051190;;, - 35;3;-0.150000,0.450000,1.051190;;, - 60;3;-0.150000,0.450000,1.051190;;, - 90;3;-0.150000,0.450000,1.051190;;; - } - } - - Animation Animation4 { - { L_Ueude } - AnimationKey { - 0; - 7; - 0;4;0.963341,-0.002906,0.268061,0.010443;;, - 20;4;0.977966,0.000000,0.208765,-0.000000;;, - 30;4;0.977966,0.000000,0.208765,-0.000000;;, - 33;4;0.701808,-0.294626,0.414491,0.498856;;, - 35;4;0.602140,-0.396791,0.512462,0.466227;;, - 60;4;0.533988,-0.465659,0.512112,0.485551;;, - 90;4;0.688209,-0.277490,0.585712,0.326050;;; - } - AnimationKey { - 1; - 7; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 33;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 7; - 0;3;0.030000,0.010000,0.800000;;, - 20;3;0.030000,0.010000,0.800000;;, - 30;3;0.030000,0.010000,0.800000;;, - 33;3;0.030000,0.010000,0.800000;;, - 35;3;0.030000,0.010000,0.800000;;, - 60;3;0.030000,0.010000,0.800000;;, - 90;3;0.030000,0.010000,0.800000;;; - } - } - - Animation Animation5 { - { L_Hizi } - AnimationKey { - 0; - 7; - 0;4;0.988102,-0.153798,-0.000000,0.000000;;, - 20;4;0.989016,-0.147809,-0.000000,0.000000;;, - 30;4;0.989016,-0.147809,-0.000000,0.000000;;, - 33;4;1.000000,-0.000001,-0.000000,0.000000;;, - 35;4;0.979750,-0.200224,-0.000000,0.000000;;, - 60;4;0.978451,-0.206477,-0.000000,0.000000;;, - 90;4;0.979750,-0.200223,-0.000000,0.000000;;; - } - AnimationKey { - 1; - 7; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 33;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 7; - 0;3;-0.000000,0.000000,1.500000;;, - 20;3;-0.000000,0.000000,1.500000;;, - 30;3;-0.000000,0.000000,1.500000;;, - 33;3;-0.000000,0.000000,1.500000;;, - 35;3;-0.000000,0.000000,1.500000;;, - 60;3;-0.000000,0.000000,1.500000;;, - 90;3;-0.000000,0.000000,1.500000;;; - } - } - - Animation Animation6 { - { L_Sitaude } - AnimationKey { - 0; - 6; - 0;4;0.999245,-0.038453,0.005539,-0.000213;;, - 20;4;0.994792,0.101925,-0.000000,-0.000000;;, - 30;4;0.994792,0.101924,0.000000,0.000000;;, - 35;4;0.972166,-0.234295,0.000000,0.000000;;, - 60;4;0.961846,-0.273590,0.000000,0.000000;;, - 90;4;0.972166,-0.234294,0.000000,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,0.000000,0.450000;;, - 20;3;-0.000000,0.000000,0.450000;;, - 30;3;-0.000000,0.000000,0.450000;;, - 35;3;-0.000000,0.000000,0.450000;;, - 60;3;-0.000000,0.000000,0.450000;;, - 90;3;-0.000000,0.000000,0.450000;;; - } - } - - Animation Animation7 { - { L_kata_Armer } - AnimationKey { - 0; - 6; - 0;4;0.970438,0.000000,-0.241350,-0.000000;;, - 20;4;0.973836,0.000000,-0.227250,0.000000;;, - 30;4;0.973836,0.000000,-0.227250,0.000000;;, - 35;4;0.973836,0.000000,-0.227250,0.000000;;, - 60;4;0.973836,0.000000,-0.227250,0.000000;;, - 90;4;0.973836,0.000000,-0.227250,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.050000,-0.000000,0.800000;;, - 20;3;-0.050000,-0.000000,0.800000;;, - 30;3;-0.050000,-0.000000,0.800000;;, - 35;3;-0.050000,-0.000000,0.800000;;, - 60;3;-0.050000,-0.000000,0.800000;;, - 90;3;-0.050000,-0.000000,0.800000;;; - } - } - - Animation Animation8 { - { L_Kata_S_Joint_1 } - AnimationKey { - 0; - 6; - 0;4;0.840844,-0.000000,0.541277,-0.000000;;, - 20;4;0.894660,0.000000,0.446748,0.000000;;, - 30;4;0.894660,0.000000,0.446748,0.000000;;, - 35;4;0.894660,0.000000,0.446748,0.000000;;, - 60;4;0.894660,0.000000,0.446748,0.000000;;, - 90;4;0.894660,0.000000,0.446748,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,-0.000000,1.491643;;, - 20;3;-0.000000,-0.000000,1.491643;;, - 30;3;-0.000000,-0.000000,1.491643;;, - 35;3;-0.000000,-0.000000,1.491643;;, - 60;3;-0.000000,-0.000000,1.491643;;, - 90;3;-0.000000,-0.000000,1.491643;;; - } - } - - Animation Animation9 { - { L_kata_S_Joint_2 } - AnimationKey { - 0; - 6; - 0;4;0.769971,0.000000,-0.638079,0.000000;;, - 20;4;0.831469,0.000000,-0.555571,0.000000;;, - 30;4;0.831469,0.000000,-0.555571,0.000000;;, - 35;4;0.831469,0.000000,-0.555571,0.000000;;, - 60;4;0.831469,0.000000,-0.555571,0.000000;;, - 90;4;0.831469,0.000000,-0.555571,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,0.000000,1.350000;;, - 20;3;-0.000000,0.000000,1.350000;;, - 30;3;-0.000000,0.000000,1.350000;;, - 35;3;-0.000000,0.000000,1.350000;;, - 60;3;-0.000000,0.000000,1.350000;;, - 90;3;-0.000000,0.000000,1.350000;;; - } - } - - Animation Animation10 { - { L_Kata_S_End } - AnimationKey { - 0; - 6; - 0;4;0.601703,-0.000000,0.798720,0.000000;;, - 20;4;0.625243,-0.000000,0.780430,0.000000;;, - 30;4;0.625243,-0.000000,0.780430,0.000000;;, - 35;4;0.625243,-0.000000,0.780430,0.000000;;, - 60;4;0.625243,-0.000000,0.780430,0.000000;;, - 90;4;0.625243,-0.000000,0.780430,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,-0.000000,1.350000;;, - 20;3;-0.000000,-0.000000,1.350000;;, - 30;3;-0.000000,-0.000000,1.350000;;, - 35;3;-0.000000,-0.000000,1.350000;;, - 60;3;-0.000000,-0.000000,1.350000;;, - 90;3;-0.000000,-0.000000,1.350000;;; - } - } - - Animation Animation11 { - { L_Hand } - AnimationKey { - 0; - 6; - 0;4;0.985927,-0.004809,0.167104,-0.000815;;, - 20;4;0.999984,0.000000,0.005712,0.000000;;, - 30;4;0.999984,-0.000000,0.005712,-0.000000;;, - 35;4;0.959509,-0.280581,-0.023830,0.006969;;, - 60;4;0.989832,-0.138231,-0.033229,0.004640;;, - 90;4;0.999856,-0.000000,-0.016976,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,0.280000,2.000000;;, - 20;3;-0.000000,0.280000,2.000000;;, - 30;3;-0.000000,0.280000,2.000000;;, - 35;3;-0.000000,0.280000,2.000000;;, - 60;3;-0.000000,0.280000,2.000000;;, - 90;3;-0.000000,0.280000,2.000000;;; - } - } - - Animation Animation12 { - { Kosi } - AnimationKey { - 0; - 6; - 0;4;0.803388,-0.595456,-0.000520,0.000701;;, - 20;4;0.852195,-0.517160,0.068112,-0.040861;;, - 30;4;0.852195,-0.517161,0.068112,-0.040861;;, - 35;4;0.803857,-0.594822,-0.000519,0.000702;;, - 60;4;0.803857,-0.594822,-0.000519,0.000702;;, - 90;4;0.784076,-0.580115,-0.177231,0.131454;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,6.600000,0.000000;;, - 20;3;0.000000,6.600000,0.000000;;, - 30;3;0.000000,6.600000,0.000000;;, - 35;3;0.000000,6.600000,0.000000;;, - 60;3;0.000000,6.600000,0.000000;;, - 90;3;0.000000,6.600000,0.000000;;; - } - } - - Animation Animation13 { - { L_Kosi_Momo } - AnimationKey { - 0; - 6; - 0;4;0.707107,0.000000,-0.707107,0.000000;;, - 20;4;0.707107,0.000000,-0.707107,0.000000;;, - 30;4;0.707107,0.000000,-0.707107,0.000000;;, - 35;4;0.707107,0.000000,-0.707107,0.000000;;, - 60;4;0.707107,0.000000,-0.707107,0.000000;;, - 90;4;0.707107,0.000000,-0.707107,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,0.650000;;, - 20;3;0.000000,0.000000,0.650000;;, - 30;3;0.000000,0.000000,0.650000;;, - 35;3;0.000000,0.000000,0.650000;;, - 60;3;0.000000,0.000000,0.650000;;, - 90;3;0.000000,0.000000,0.650000;;; - } - } - - Animation Animation14 { - { L_momo } - AnimationKey { - 0; - 6; - 0;4;0.804208,-0.200953,0.499509,-0.251708;;, - 20;4;0.801941,-0.063680,0.479474,-0.350628;;, - 30;4;0.801941,-0.063681,0.479474,-0.350627;;, - 35;4;0.807354,-0.248834,0.484865,-0.226201;;, - 60;4;0.807354,-0.248833,0.484865,-0.226201;;, - 90;4;0.809322,0.048748,0.456864,-0.365920;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,-0.000000,1.650000;;, - 20;3;0.000000,-0.000000,1.650000;;, - 30;3;0.000000,-0.000000,1.650000;;, - 35;3;0.000000,-0.000000,1.650000;;, - 60;3;0.000000,-0.000000,1.650000;;, - 90;3;0.000000,-0.000000,1.650000;;; - } - } - - Animation Animation15 { - { L_Hiza } - AnimationKey { - 0; - 6; - 0;4;0.994572,0.104049,0.000000,0.000000;;, - 20;4;0.999743,-0.022688,0.000000,0.000000;;, - 30;4;0.999743,-0.022687,0.000000,0.000000;;, - 35;4;0.994430,0.105397,0.000000,0.000000;;, - 60;4;0.994430,0.105396,0.000000,0.000000;;, - 90;4;0.994430,0.105396,0.000000,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,1.400000;;, - 20;3;0.000000,0.000000,1.400000;;, - 30;3;0.000000,0.000000,1.400000;;, - 35;3;0.000000,0.000000,1.400000;;, - 60;3;0.000000,0.000000,1.400000;;, - 90;3;0.000000,0.000000,1.400000;;; - } - } - - Animation Animation16 { - { L_Sune } - AnimationKey { - 0; - 6; - 0;4;0.991406,0.130820,0.000000,0.000000;;, - 20;4;0.990509,0.137445,0.000000,0.000000;;, - 30;4;0.990509,0.137445,0.000000,0.000000;;, - 35;4;0.990509,0.137445,0.000000,0.000000;;, - 60;4;0.990509,0.137445,0.000000,0.000000;;, - 90;4;0.990509,0.137445,0.000000,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,0.800000;;, - 20;3;0.000000,0.000000,0.800000;;, - 30;3;0.000000,0.000000,0.800000;;, - 35;3;0.000000,0.000000,0.800000;;, - 60;3;0.000000,0.000000,0.800000;;, - 90;3;0.000000,0.000000,0.800000;;; - } - } - - Animation Animation17 { - { L_Kakato } - AnimationKey { - 0; - 6; - 0;4;0.617099,-0.136931,0.169958,0.756011;;, - 20;4;0.640824,-0.169494,0.113764,0.740050;;, - 30;4;0.640824,-0.169494,0.113764,0.740050;;, - 35;4;0.640824,-0.169494,0.113764,0.740050;;, - 60;4;0.640824,-0.169494,0.113764,0.740050;;, - 90;4;0.640824,-0.169494,0.113764,0.740050;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.037573,-0.006428,2.820891;;, - 20;3;-0.037573,-0.006428,2.820891;;, - 30;3;-0.037573,-0.006428,2.820891;;, - 35;3;-0.037573,-0.006428,2.820891;;, - 60;3;-0.037573,-0.006428,2.820891;;, - 90;3;-0.037573,-0.006428,2.820891;;; - } - } - - Animation Animation18 { - { L_Tumasaki } - AnimationKey { - 0; - 6; - 0;4;0.744785,0.000000,-0.667305,-0.000000;;, - 20;4;0.784738,0.000000,-0.619828,-0.000000;;, - 30;4;0.784737,0.000000,-0.619828,-0.000000;;, - 35;4;0.784737,0.000000,-0.619828,-0.000000;;, - 60;4;0.784737,0.000000,-0.619828,-0.000000;;, - 90;4;0.784737,0.000000,-0.619828,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,-0.000000,0.550000;;, - 20;3;-0.000000,-0.000000,0.550000;;, - 30;3;-0.000000,-0.000000,0.550000;;, - 35;3;-0.000000,-0.000000,0.550000;;, - 60;3;-0.000000,-0.000000,0.550000;;, - 90;3;-0.000000,-0.000000,0.550000;;; - } - } - - Animation Animation19 { - { R_Mune } - AnimationKey { - 0; - 6; - 0;4;0.501189,-0.476897,-0.498808,0.522082;;, - 20;4;0.511753,-0.487964,-0.487964,0.511753;;, - 30;4;0.511753,-0.487964,-0.487964,0.511753;;, - 35;4;0.511753,-0.487964,-0.487964,0.511753;;, - 60;4;0.511753,-0.487964,-0.487964,0.511753;;, - 90;4;0.511753,-0.487964,-0.487964,0.511753;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 30;3;0.000000,0.000000,3.000000;;, - 35;3;0.000000,0.000000,3.000000;;, - 60;3;0.000000,0.000000,3.000000;;, - 90;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation20 { - { R_Kata_Base } - AnimationKey { - 0; - 6; - 0;4;0.859300,0.017395,0.022978,0.510660;;, - 20;4;0.881323,0.035819,0.038528,0.469578;;, - 30;4;0.881323,0.035819,0.038528,0.469578;;, - 35;4;0.881323,0.035819,0.038528,0.469578;;, - 60;4;0.881323,0.035819,0.038528,0.469578;;, - 90;4;0.881323,0.035819,0.038528,0.469578;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.110000,0.450000,0.000000;;, - 20;3;0.110000,0.450000,0.000000;;, - 30;3;0.110000,0.450000,0.000000;;, - 35;3;0.110000,0.450000,0.000000;;, - 60;3;0.110000,0.450000,0.000000;;, - 90;3;0.110000,0.450000,0.000000;;; - } - } - - Animation Animation21 { - { R_Ueude } - AnimationKey { - 0; - 6; - 0;4;0.740594,-0.254373,-0.487024,-0.386812;;, - 20;4;0.669997,-0.311630,-0.371385,-0.562195;;, - 30;4;0.669998,-0.311630,-0.371386,-0.562195;;, - 35;4;0.669998,-0.311630,-0.371386,-0.562195;;, - 60;4;0.669998,-0.311630,-0.371386,-0.562195;;, - 90;4;0.811788,-0.180435,-0.449982,-0.325514;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.030000,0.010000,0.800000;;, - 20;3;0.030000,0.010000,0.800000;;, - 30;3;0.030000,0.010000,0.800000;;, - 35;3;0.030000,0.010000,0.800000;;, - 60;3;0.030000,0.010000,0.800000;;, - 90;3;0.030000,0.010000,0.800000;;; - } - } - - Animation Animation22 { - { R_Hizi } - AnimationKey { - 0; - 6; - 0;4;0.987311,-0.158801,0.000000,-0.000000;;, - 20;4;0.984503,-0.175366,0.000000,-0.000000;;, - 30;4;0.984503,-0.175366,0.000000,-0.000000;;, - 35;4;0.984503,-0.175366,0.000000,-0.000000;;, - 60;4;0.984503,-0.175366,0.000000,-0.000000;;, - 90;4;0.984503,-0.175366,0.000000,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,-0.000000,1.500000;;, - 20;3;-0.000000,-0.000000,1.500000;;, - 30;3;-0.000000,-0.000000,1.500000;;, - 35;3;-0.000000,-0.000000,1.500000;;, - 60;3;-0.000000,-0.000000,1.500000;;, - 90;3;-0.000000,-0.000000,1.500000;;; - } - } - - Animation Animation23 { - { R_Sitaude } - AnimationKey { - 0; - 6; - 0;4;0.942090,-0.335134,-0.011595,0.004125;;, - 20;4;0.900933,-0.433590,-0.016083,0.007740;;, - 30;4;0.900934,-0.433590,-0.016083,0.007740;;, - 35;4;0.900934,-0.433590,-0.016083,0.007740;;, - 60;4;0.900934,-0.433590,-0.016083,0.007740;;, - 90;4;0.900934,-0.433590,-0.016083,0.007740;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,-0.000000,0.450000;;, - 20;3;0.000000,-0.000000,0.450000;;, - 30;3;0.000000,-0.000000,0.450000;;, - 35;3;0.000000,-0.000000,0.450000;;, - 60;3;0.000000,-0.000000,0.450000;;, - 90;3;0.000000,-0.000000,0.450000;;; - } - } - - Animation Animation24 { - { R_kata_Armer } - AnimationKey { - 0; - 6; - 0;4;0.954398,0.000000,0.298537,0.000000;;, - 20;4;0.938281,0.000000,0.345875,0.000000;;, - 30;4;0.938281,0.000000,0.345875,0.000000;;, - 35;4;0.938281,0.000000,0.345875,0.000000;;, - 60;4;0.938281,0.000000,0.345875,0.000000;;, - 90;4;0.938281,0.000000,0.345875,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.050000,0.000000,0.800000;;, - 20;3;-0.050000,0.000000,0.800000;;, - 30;3;-0.050000,0.000000,0.800000;;, - 35;3;-0.050000,0.000000,0.800000;;, - 60;3;-0.050000,0.000000,0.800000;;, - 90;3;-0.050000,0.000000,0.800000;;; - } - } - - Animation Animation25 { - { R_Kata_S_Joint_1 } - AnimationKey { - 0; - 6; - 0;4;0.713266,0.000000,-0.700893,-0.000000;;, - 20;4;0.761140,0.000000,-0.648588,-0.000000;;, - 30;4;0.761140,0.000000,-0.648588,-0.000000;;, - 35;4;0.761140,0.000000,-0.648588,-0.000000;;, - 60;4;0.761140,0.000000,-0.648588,-0.000000;;, - 90;4;0.761140,0.000000,-0.648588,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,1.491643;;, - 20;3;0.000000,0.000000,1.491643;;, - 30;3;0.000000,0.000000,1.491643;;, - 35;3;0.000000,0.000000,1.491643;;, - 60;3;0.000000,0.000000,1.491643;;, - 90;3;0.000000,0.000000,1.491643;;; - } - } - - Animation Animation26 { - { R_kata_S_Joint_2 } - AnimationKey { - 0; - 6; - 0;4;0.804936,0.000000,0.593362,0.000000;;, - 20;4;0.892586,0.000000,0.450878,0.000000;;, - 30;4;0.892586,0.000000,0.450878,0.000000;;, - 35;4;0.892586,0.000000,0.450878,0.000000;;, - 60;4;0.892586,0.000000,0.450878,0.000000;;, - 90;4;0.892586,0.000000,0.450878,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,1.350000;;, - 20;3;0.000000,0.000000,1.350000;;, - 30;3;0.000000,0.000000,1.350000;;, - 35;3;0.000000,0.000000,1.350000;;, - 60;3;0.000000,0.000000,1.350000;;, - 90;3;0.000000,0.000000,1.350000;;; - } - } - - Animation Animation27 { - { R_Kata_S_End } - AnimationKey { - 0; - 6; - 0;4;-0.692394,-0.000000,0.721520,0.000000;;, - 20;4;-0.707107,-0.000000,0.707107,0.000000;;, - 30;4;-0.707107,-0.000000,0.707107,0.000000;;, - 35;4;-0.707107,-0.000000,0.707107,0.000000;;, - 60;4;-0.707107,-0.000000,0.707107,0.000000;;, - 90;4;-0.707107,-0.000000,0.707107,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,1.350000;;, - 20;3;0.000000,0.000000,1.350000;;, - 30;3;0.000000,0.000000,1.350000;;, - 35;3;0.000000,0.000000,1.350000;;, - 60;3;0.000000,0.000000,1.350000;;, - 90;3;0.000000,0.000000,1.350000;;; - } - } - - Animation Animation28 { - { R_Hand } - AnimationKey { - 0; - 6; - 0;4;0.995956,0.047810,-0.075977,-0.003647;;, - 20;4;0.993909,-0.000000,-0.110208,0.000000;;, - 30;4;0.993909,0.000000,-0.110208,-0.000000;;, - 35;4;0.993909,0.000000,-0.110208,-0.000000;;, - 60;4;0.993909,0.000000,-0.110208,-0.000000;;, - 90;4;0.993909,0.000000,-0.110208,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,2.000000;;, - 20;3;0.000000,0.000000,2.000000;;, - 30;3;0.000000,0.000000,2.000000;;, - 35;3;0.000000,0.000000,2.000000;;, - 60;3;0.000000,0.000000,2.000000;;, - 90;3;0.000000,0.000000,2.000000;;; - } - } - - Animation Animation29 { - { R_Kosi_Momo } - AnimationKey { - 0; - 6; - 0;4;0.707107,0.000000,0.707107,-0.000000;;, - 20;4;0.707107,0.000000,0.707107,-0.000000;;, - 30;4;0.707107,0.000000,0.707107,-0.000000;;, - 35;4;0.707107,0.000000,0.707107,-0.000000;;, - 60;4;0.707107,0.000000,0.707107,-0.000000;;, - 90;4;0.707107,0.000000,0.707107,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,0.650000;;, - 20;3;0.000000,0.000000,0.650000;;, - 30;3;0.000000,0.000000,0.650000;;, - 35;3;0.000000,0.000000,0.650000;;, - 60;3;0.000000,0.000000,0.650000;;, - 90;3;0.000000,0.000000,0.650000;;; - } - } - - Animation Animation30 { - { R_momo } - AnimationKey { - 0; - 6; - 0;4;0.796716,-0.191838,-0.377474,0.431225;;, - 20;4;0.772814,-0.001742,-0.457415,0.439917;;, - 30;4;0.772814,-0.001742,-0.457415,0.439917;;, - 35;4;0.832387,-0.031241,-0.470968,0.290421;;, - 60;4;0.821915,-0.024898,-0.489015,0.291034;;, - 90;4;0.757243,-0.409591,-0.368580,0.350665;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,-0.000000,1.650000;;, - 20;3;0.000000,-0.000000,1.650000;;, - 30;3;0.000000,-0.000000,1.650000;;, - 35;3;0.000000,-0.000000,1.650000;;, - 60;3;0.000000,-0.000000,1.650000;;, - 90;3;0.000000,-0.000000,1.650000;;; - } - } - - Animation Animation31 { - { R_Hiza } - AnimationKey { - 0; - 6; - 0;4;0.964205,0.265157,0.000000,0.000000;;, - 20;4;0.991558,0.129661,-0.000000,-0.000000;;, - 30;4;0.991558,0.129661,-0.000000,-0.000000;;, - 35;4;0.991558,0.129661,-0.000000,-0.000000;;, - 60;4;0.991558,0.129661,-0.000000,-0.000000;;, - 90;4;0.971342,0.237686,0.000000,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,-0.000000,1.400000;;, - 20;3;0.000000,-0.000000,1.400000;;, - 30;3;0.000000,-0.000000,1.400000;;, - 35;3;0.000000,-0.000000,1.400000;;, - 60;3;0.000000,-0.000000,1.400000;;, - 90;3;0.000000,-0.000000,1.400000;;; - } - } - - Animation Animation32 { - { R_Sune } - AnimationKey { - 0; - 6; - 0;4;0.971175,0.238084,0.011318,0.002775;;, - 20;4;0.982613,0.185667,-0.000000,-0.000000;;, - 30;4;0.982613,0.185667,-0.000000,-0.000000;;, - 35;4;0.982613,0.185667,-0.000000,-0.000000;;, - 60;4;0.982613,0.185667,-0.000000,-0.000000;;, - 90;4;0.965700,0.259662,-0.000000,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,0.800000;;, - 20;3;0.000000,0.000000,0.800000;;, - 30;3;0.000000,0.000000,0.800000;;, - 35;3;0.000000,0.000000,0.800000;;, - 60;3;0.000000,0.000000,0.800000;;, - 90;3;0.000000,0.000000,0.800000;;; - } - } - - Animation Animation33 { - { R_Kakato } - AnimationKey { - 0; - 6; - 0;4;0.675697,0.070495,-0.231786,0.696232;;, - 20;4;0.652095,0.070844,-0.273446,0.703549;;, - 30;4;0.652095,0.070844,-0.273446,0.703549;;, - 35;4;0.652095,0.070844,-0.273446,0.703549;;, - 60;4;0.652095,0.070844,-0.273446,0.703549;;, - 90;4;0.814704,0.066152,-0.224614,0.530499;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,2.893634;;, - 20;3;0.000000,0.000000,2.893634;;, - 30;3;0.000000,0.000000,2.893634;;, - 35;3;0.000000,0.000000,2.893634;;, - 60;3;0.000000,0.000000,2.893634;;, - 90;3;0.000000,0.000000,2.893634;;; - } - } - - Animation Animation34 { - { R_Tumasaki } - AnimationKey { - 0; - 6; - 0;4;0.799843,0.000000,-0.600210,-0.000000;;, - 20;4;0.801344,0.000000,-0.598204,-0.000000;;, - 30;4;0.801344,0.000000,-0.598204,-0.000000;;, - 35;4;0.801344,0.000000,-0.598204,-0.000000;;, - 60;4;0.801344,0.000000,-0.598204,-0.000000;;, - 90;4;0.801344,0.000000,-0.598204,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;-0.000000,-0.000000,0.550000;;, - 20;3;-0.000000,-0.000000,0.550000;;, - 30;3;-0.000000,-0.000000,0.550000;;, - 35;3;-0.000000,-0.000000,0.550000;;, - 60;3;-0.000000,-0.000000,0.550000;;, - 90;3;-0.000000,-0.000000,0.550000;;; - } - } - - Animation Animation35 { - { Bone_neck } - AnimationKey { - 0; - 6; - 0;4;1.000000,0.000732,-0.000000,-0.000000;;, - 20;4;1.000000,0.000732,-0.000000,-0.000000;;, - 30;4;1.000000,0.000732,-0.000000,-0.000000;;, - 35;4;1.000000,0.000732,-0.000000,-0.000000;;, - 60;4;1.000000,0.000732,-0.000000,-0.000000;;, - 90;4;1.000000,0.000732,-0.000000,-0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 30;3;0.000000,0.000000,3.000000;;, - 35;3;0.000000,0.000000,3.000000;;, - 60;3;0.000000,0.000000,3.000000;;, - 90;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation36 { - { Bone_Head } - AnimationKey { - 0; - 6; - 0;4;0.632903,-0.143313,0.742065,-0.168031;;, - 20;4;0.566568,-0.314064,0.666295,-0.369345;;, - 30;4;0.566569,-0.314063,0.666295,-0.369344;;, - 35;4;0.632561,0.139650,0.743903,0.164231;;, - 60;4;0.622168,0.180395,0.731681,0.212148;;, - 90;4;0.546773,0.276187,0.705520,0.356374;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,1.407194;;, - 20;3;0.000000,0.000000,1.407194;;, - 30;3;0.000000,0.000000,1.407194;;, - 35;3;0.000000,0.000000,1.407194;;, - 60;3;0.000000,0.000000,1.407194;;, - 90;3;0.000000,0.000000,1.407194;;; - } - } - - Animation Animation37 { - { R_Wpn2 } - AnimationKey { - 0; - 2; - 0;4;0.999997,-0.002406,-0.000013,0.000000;;, - 90;4;0.999997,-0.002412,-0.000013,0.000000;;; - } - AnimationKey { - 1; - 2; - 0;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 2; - 0;3;0.100000,-0.265000,0.600000;;, - 90;3;0.100000,-0.265000,0.600000;;; - } - } - - Animation Animation38 { - { L_Wpn } - AnimationKey { - 0; - 6; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 30;4;1.000000,0.000000,0.000000,0.000000;;, - 35;4;1.000000,0.000000,0.000000,0.000000;;, - 60;4;1.000000,0.000000,0.000000,0.000000;;, - 90;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 6; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 35;3;1.000000,1.000000,1.000000;;, - 60;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 6; - 0;3;0.000000,0.000000,0.800001;;, - 20;3;0.000000,0.000000,0.800001;;, - 30;3;0.000000,0.000000,0.800001;;, - 35;3;0.000000,0.000000,0.800001;;, - 60;3;0.000000,0.000000,0.800001;;, - 90;3;0.000000,0.000000,0.800001;;; - } - } - - Animation Animation39 { - { BarniaBaseR } - AnimationKey { - 0; - 4; - 0;4;-0.501575,0.498420,0.498420,0.501575;;, - 20;4;-0.501575,0.498420,0.498420,0.501575;;, - 30;4;-0.501575,0.498420,0.498420,0.501575;;, - 90;4;-0.501575,0.498420,0.498420,0.501575;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.033058,1.000000;;, - 20;3;1.000000,1.033058,1.000000;;, - 30;3;1.000000,1.033058,1.000000;;, - 90;3;1.000000,1.033058,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,0.000000;;, - 20;3;0.000000,0.000000,0.000000;;, - 30;3;0.000000,0.000000,0.000000;;, - 90;3;0.000000,0.000000,0.000000;;; - } - } - - Animation Animation40 { - { BarniaBaseL } - AnimationKey { - 0; - 4; - 0;4;-0.501575,0.498420,0.498420,0.501575;;, - 20;4;-0.501575,0.498420,0.498420,0.501575;;, - 30;4;-0.501575,0.498420,0.498420,0.501575;;, - 90;4;-0.501575,0.498420,0.498420,0.501575;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.033058,1.000000;;, - 20;3;1.000000,1.033058,1.000000;;, - 30;3;1.000000,1.033058,1.000000;;, - 90;3;1.000000,1.033058,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,0.000000;;, - 20;3;0.000000,0.000000,0.000000;;, - 30;3;0.000000,0.000000,0.000000;;, - 90;3;0.000000,0.000000,0.000000;;; - } - } - - Animation Animation41 { - { BarniaBaseL_2 } - AnimationKey { - 0; - 4; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 30;4;1.000000,0.000000,0.000000,0.000000;;, - 90;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,0.500000;;, - 20;3;0.000000,0.000000,0.500000;;, - 30;3;0.000000,0.000000,0.500000;;, - 90;3;0.000000,0.000000,0.500000;;; - } - } - - Animation Animation42 { - { BarniaBaseR_2 } - AnimationKey { - 0; - 4; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 30;4;1.000000,0.000000,0.000000,0.000000;;, - 90;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,0.500000;;, - 20;3;0.000000,0.000000,0.500000;;, - 30;3;0.000000,0.000000,0.500000;;, - 90;3;0.000000,0.000000,0.500000;;; - } - } - - Animation Animation43 { - { SW2_R_mp } - AnimationKey { - 0; - 4; - 0;4;0.930737,0.000000,-0.365689,0.000000;;, - 20;4;0.930737,0.000000,-0.365689,0.000000;;, - 30;4;0.930737,0.000000,-0.365689,0.000000;;, - 90;4;0.930737,0.000000,-0.365689,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;1.300000,-1.000000,3.000000;;, - 20;3;1.300000,-1.000000,3.000000;;, - 30;3;1.300000,-1.000000,3.000000;;, - 90;3;1.300000,-1.000000,3.000000;;; - } - } - - Animation Animation44 { - { SW2_R_mp_2 } - AnimationKey { - 0; - 4; - 0;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 20;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 30;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 90;4;0.660097,-0.253518,-0.253518,-0.660097;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,1.000000;;, - 20;3;0.000000,0.000000,1.000000;;, - 30;3;0.000000,0.000000,1.000000;;, - 90;3;0.000000,0.000000,1.000000;;; - } - } - - Animation Animation45 { - { SW2_L_mp } - AnimationKey { - 0; - 4; - 0;4;0.930737,0.000000,-0.365689,0.000000;;, - 20;4;0.930737,0.000000,-0.365689,0.000000;;, - 30;4;0.930737,0.000000,-0.365689,0.000000;;, - 90;4;0.930737,0.000000,-0.365689,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;1.300000,1.000000,3.000000;;, - 20;3;1.300000,1.000000,3.000000;;, - 30;3;1.300000,1.000000,3.000000;;, - 90;3;1.300000,1.000000,3.000000;;; - } - } - - Animation Animation46 { - { SW2_L_mp_2 } - AnimationKey { - 0; - 4; - 0;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 20;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 30;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 90;4;0.499564,-0.500435,-0.500435,-0.499564;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,1.000000;;, - 20;3;0.000000,0.000000,1.000000;;, - 30;3;0.000000,0.000000,1.000000;;, - 90;3;0.000000,0.000000,1.000000;;; - } - } - - Animation Animation47 { - { L_Mune_A2 } - AnimationKey { - 0; - 4; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 30;4;1.000000,0.000000,0.000000,0.000000;;, - 90;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,1.051190;;, - 20;3;0.000000,0.000000,1.051190;;, - 30;3;0.000000,0.000000,1.051190;;, - 90;3;0.000000,0.000000,1.051190;;; - } - } - - Animation Animation48 { - { R_Mune2 } - AnimationKey { - 0; - 4; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 30;4;1.000000,0.000000,0.000000,0.000000;;, - 90;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,1.051190;;, - 20;3;0.000000,0.000000,1.051190;;, - 30;3;0.000000,0.000000,1.051190;;, - 90;3;0.000000,0.000000,1.051190;;; - } - } - - Animation Animation49 { - { M_barnia1_1 } - AnimationKey { - 0; - 4; - 0;4;-0.686130,0.000000,0.727479,0.000000;;, - 20;4;-0.686130,0.000000,0.727479,0.000000;;, - 30;4;-0.686130,0.000000,0.727479,0.000000;;, - 90;4;-0.686130,0.000000,0.727479,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 30;3;0.000000,0.000000,3.000000;;, - 90;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation50 { - { M_barnia1_2 } - AnimationKey { - 0; - 4; - 0;4;0.707107,0.000000,0.707107,0.000000;;, - 20;4;0.707107,0.000000,0.707107,0.000000;;, - 30;4;0.707107,0.000000,0.707107,0.000000;;, - 90;4;0.707107,0.000000,0.707107,0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,2.548788;;, - 20;3;0.000000,0.000000,2.548788;;, - 30;3;0.000000,0.000000,2.548788;;, - 90;3;0.000000,0.000000,2.548788;;; - } - } - - Animation Animation51 { - { M_barnia2_1 } - AnimationKey { - 0; - 4; - 0;4;-0.547896,0.000000,0.836547,-0.000000;;, - 20;4;-0.547896,0.000000,0.836547,-0.000000;;, - 30;4;-0.547896,0.000000,0.836547,-0.000000;;, - 90;4;-0.547896,0.000000,0.836547,-0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 30;3;0.000000,0.000000,3.000000;;, - 90;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation52 { - { M_barnia2_2 } - AnimationKey { - 0; - 4; - 0;4;0.558470,-0.000000,0.829525,-0.000000;;, - 20;4;0.558470,-0.000000,0.829525,-0.000000;;, - 30;4;0.558470,-0.000000,0.829525,-0.000000;;, - 90;4;0.558470,-0.000000,0.829525,-0.000000;;; - } - AnimationKey { - 1; - 4; - 0;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 30;3;1.000000,1.000000,1.000000;;, - 90;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 4; - 0;3;0.000000,0.000000,2.261806;;, - 20;3;0.000000,0.000000,2.261806;;, - 30;3;0.000000,0.000000,2.261806;;, - 90;3;0.000000,0.000000,2.261806;;; - } - } -} diff --git a/examples/models/xfile/stand.x b/examples/models/xfile/stand.x deleted file mode 100644 index 97785d64fb2de9..00000000000000 --- a/examples/models/xfile/stand.x +++ /dev/null @@ -1,534 +0,0 @@ -xof 0303txt 0032 - -AnimationSet stand { - - Animation Animation0 { - { AllPutting_2_Layer1 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;; - } - } - - Animation Animation1 { - { Bone01 } - AnimationKey { - 4; - 2; - 0;16;0.000000,0.000000,1.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,6.600000,0.000000,1.000000;;, - 5;16;-0.000000,0.076720,0.997053,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,0.997053,-0.076720,0.000000,0.000000,6.600000,0.000000,1.000000;;; - } - } - - Animation Animation2 { - { L_Mune_A } - AnimationKey { - 4; - 2; - 0;16;0.000000,-0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,3.000000,1.000000;;, - 5;16;0.000000,-0.047564,0.998868,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.998868,0.047564,0.000000,0.000000,0.000000,3.000000,1.000000;;; - } - } - - Animation Animation3 { - { L_Kata_Base } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.150000,0.450000,1.051190,1.000000;;, - 5;16;0.997704,-0.034369,0.058356,0.000000,0.043934,0.984208,-0.171478,0.000000,-0.051541,0.173648,0.983458,0.000000,-0.150000,0.450000,1.051190,1.000000;;; - } - } - - Animation Animation4 { - { L_Ueude } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.030000,0.010000,0.800000,1.000000;;, - 5;16;0.403279,-0.299040,0.864836,0.000000,0.126380,0.954240,0.271023,0.000000,-0.906308,0.000000,0.422618,0.000000,0.030000,0.010000,0.800000,1.000000;;; - } - } - - Animation Animation5 { - { L_Hizi } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,-0.000001,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000001,-0.000000,1.000000,0.000000,-0.000000,0.000000,1.500000,1.000000;;, - 5;16;1.000000,-0.000000,-0.000001,0.000000,0.000000,0.956305,0.292372,0.000000,0.000001,-0.292372,0.956305,0.000000,-0.000000,0.000000,1.500000,1.000000;;; - } - } - - Animation Animation6 { - { L_Sitaude } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.450000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.939693,0.342020,0.000000,0.000000,-0.342020,0.939693,0.000000,-0.000000,0.000000,0.450000,1.000000;;; - } - } - - Animation Animation7 { - { L_kata_Armer } - AnimationKey { - 4; - 2; - 0;16;0.972082,-0.000000,-0.234641,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.234641,0.000000,0.972082,0.000000,-0.050000,-0.000000,0.800000,1.000000;;, - 5;16;0.906308,-0.000000,-0.422618,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.422618,0.000000,0.906308,0.000000,-0.050000,-0.000000,0.800000,1.000000;;; - } - } - - Animation Animation8 { - { L_Kata_S_Joint_1 } - AnimationKey { - 4; - 2; - 0;16;0.979925,0.000000,0.199368,0.000000,0.000000,1.000000,0.000000,0.000000,-0.199368,0.000000,0.979925,0.000000,0.000000,-0.000000,1.491643,1.000000;;, - 5;16;0.000000,0.000000,1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,-1.000000,-0.000000,0.000000,0.000000,-0.000000,-0.000000,1.491643,1.000000;;; - } - } - - Animation Animation9 { - { L_kata_S_Joint_2 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,1.350000,1.000000;;, - 5;16;-0.173648,-0.000000,-0.984808,0.000000,-0.000000,1.000000,0.000000,0.000000,0.984808,0.000000,-0.173648,0.000000,-0.000000,0.000000,1.350000,1.000000;;; - } - } - - Animation Animation10 { - { L_Kata_S_End } - AnimationKey { - 4; - 2; - 0;16;-0.000000,-0.000000,1.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-1.000000,-0.000000,-0.000000,0.000000,-0.000000,-0.000000,1.350000,1.000000;;, - 5;16;-0.438371,-0.000000,0.898794,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.898794,-0.000000,-0.438371,0.000000,-0.000000,-0.000000,1.350000,1.000000;;; - } - } - - Animation Animation11 { - { L_Hand } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.280000,2.000000,1.000000;;, - 5;16;0.928780,0.000000,0.370632,0.000000,-0.000000,1.000000,0.000000,0.000000,-0.370632,-0.000000,0.928780,0.000000,-0.000000,0.280000,2.000000,1.000000;;; - } - } - - Animation Animation12 { - { Kosi } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,6.600000,0.000000,1.000000;;, - 5;16;0.999998,0.000000,-0.001745,0.000000,0.001745,0.000000,0.999998,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,6.600000,0.000000,1.000000;;; - } - } - - Animation Animation13 { - { L_Kosi_Momo } - AnimationKey { - 4; - 2; - 0;16;-0.000000,-0.017452,-0.999848,0.000000,-0.000000,0.999848,-0.017452,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,0.650000,1.000000;;, - 5;16;-0.000000,-0.000000,-1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,0.650000,1.000000;;; - } - } - - Animation Animation14 { - { L_momo } - AnimationKey { - 4; - 2; - 0;16;0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.650000,1.000000;;, - 5;16;0.240268,0.172987,0.955168,0.000000,-0.127850,0.981060,-0.145516,0.000000,-0.962250,-0.087156,0.257834,0.000000,0.000000,-0.000000,1.650000,1.000000;;; - } - } - - Animation Animation15 { - { L_Hiza } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.400000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.977783,-0.209619,0.000000,0.000000,0.209619,0.977783,0.000000,0.000000,0.000000,1.400000,1.000000;;; - } - } - - Animation Animation16 { - { L_Sune } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.800000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.999976,0.006981,0.000000,0.000000,-0.006981,0.999976,0.000000,0.000000,0.000000,0.800000,1.000000;;; - } - } - - Animation Animation17 { - { L_Kakato } - AnimationKey { - 4; - 2; - 0;16;0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,-0.037573,-0.006428,2.820891,1.000000;;, - 5;16;-0.099286,-0.988769,-0.111704,0.000000,0.969497,-0.121406,0.212925,0.000000,-0.224095,-0.087156,0.970662,0.000000,-0.037573,-0.006428,2.820891,1.000000;;; - } - } - - Animation Animation18 { - { L_Tumasaki } - AnimationKey { - 4; - 2; - 0;16;0.173648,0.000000,-0.984808,0.000000,0.000000,1.000000,0.000000,0.000000,0.984808,0.000000,0.173648,0.000000,-0.000000,-0.000000,0.550000,1.000000;;, - 5;16;0.231626,0.000000,-0.972805,0.000000,-0.000000,1.000000,0.000000,0.000000,0.972805,0.000000,0.231626,0.000000,-0.000000,-0.000000,0.550000,1.000000;;; - } - } - - Animation Animation19 { - { R_Mune } - AnimationKey { - 4; - 2; - 0;16;0.000000,-0.000000,-1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,3.000000,1.000000;;, - 5;16;-0.000000,-0.047564,-0.998868,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,-0.998868,0.047564,0.000000,0.000000,0.000000,3.000000,1.000000;;; - } - } - - Animation Animation20 { - { R_Kata_Base } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.110000,0.450000,0.000000,1.000000;;, - 5;16;0.998338,-0.034369,-0.046252,0.000000,0.025769,0.984208,-0.175131,0.000000,0.051541,0.173648,0.983458,0.000000,0.110000,0.450000,0.000000,1.000000;;; - } - } - - Animation Animation21 { - { R_Ueude } - AnimationKey { - 4; - 2; - 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.030000,0.010000,0.800000,1.000000;;, - 5;16;0.412440,0.218143,-0.884481,0.000000,-0.092191,0.975917,0.197705,0.000000,0.906308,-0.000000,0.422618,0.000000,0.030000,0.010000,0.800000,1.000000;;; - } - } - - Animation Animation22 { - { R_Hizi } - AnimationKey { - 4; - 2; - 0;16;1.000000,-0.000000,0.000001,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000001,-0.000000,1.000000,0.000000,-0.000000,-0.000000,1.500000,1.000000;;, - 5;16;1.000000,-0.000000,0.000001,0.000000,-0.000000,0.938493,0.345297,0.000000,-0.000001,-0.345297,0.938493,0.000000,-0.000000,-0.000000,1.500000,1.000000;;; - } - } - - Animation Animation23 { - { R_Sitaude } - AnimationKey { - 4; - 2; - 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.450000,1.000000;;, - 5;16;1.000000,-0.000000,-0.000000,0.000000,0.000000,0.939693,0.342020,0.000000,0.000000,-0.342020,0.939693,0.000000,0.000000,-0.000000,0.450000,1.000000;;; - } - } - - Animation Animation24 { - { R_kata_Armer } - AnimationKey { - 4; - 2; - 0;16;0.977525,0.000000,0.210820,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.210820,0.000000,0.977525,0.000000,-0.050000,0.000000,0.800000,1.000000;;, - 5;16;0.906308,0.000000,0.422618,0.000000,0.000000,1.000000,-0.000000,0.000000,-0.422618,0.000000,0.906308,0.000000,-0.050000,0.000000,0.800000,1.000000;;; - } - } - - Animation Animation25 { - { R_Kata_S_Joint_1 } - AnimationKey { - 4; - 2; - 0;16;0.985109,0.000000,-0.171929,0.000000,0.000000,1.000000,0.000000,0.000000,0.171929,0.000000,0.985109,0.000000,0.000000,0.000000,1.491643,1.000000;;, - 5;16;0.000000,-0.000000,-1.000000,0.000000,-0.000000,1.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.491643,1.000000;;; - } - } - - Animation Animation26 { - { R_kata_S_Joint_2 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.350000,1.000000;;, - 5;16;-0.173648,0.000000,0.984808,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.984808,-0.000000,-0.173648,0.000000,0.000000,0.000000,1.350000,1.000000;;; - } - } - - Animation Animation27 { - { R_Kata_S_End } - AnimationKey { - 4; - 2; - 0;16;0.000000,0.000000,-1.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.350000,1.000000;;, - 5;16;-0.500000,-0.000000,-0.866025,0.000000,-0.000000,1.000000,0.000000,0.000000,0.866025,0.000000,-0.500000,0.000000,0.000000,0.000000,1.350000,1.000000;;; - } - } - - Animation Animation28 { - { R_Hand } - AnimationKey { - 4; - 2; - 0;16;1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,2.000000,1.000000;;, - 5;16;0.975708,-0.000000,-0.219073,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.219073,0.000000,0.975708,0.000000,0.000000,0.000000,2.000000,1.000000;;; - } - } - - Animation Animation29 { - { R_Kosi_Momo } - AnimationKey { - 4; - 2; - 0;16;-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,0.650000,1.000000;;, - 5;16;-0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,0.650000,1.000000;;; - } - } - - Animation Animation30 { - { R_momo } - AnimationKey { - 4; - 2; - 0;16;0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,-0.000000,1.650000,1.000000;;, - 5;16;0.240268,-0.172987,-0.955168,0.000000,0.127850,0.981060,-0.145516,0.000000,0.962250,-0.087156,0.257834,0.000000,0.000000,-0.000000,1.650000,1.000000;;; - } - } - - Animation Animation31 { - { R_Hiza } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,-0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,1.400000,1.000000;;, - 5;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.966376,-0.257133,0.000000,0.000000,0.257133,0.966376,0.000000,0.000000,-0.000000,1.400000,1.000000;;; - } - } - - Animation Animation32 { - { R_Sune } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.800000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,-0.000000,0.996917,0.078459,0.000000,0.000000,-0.078459,0.996917,0.000000,0.000000,0.000000,0.800000,1.000000;;; - } - } - - Animation Animation33 { - { R_Kakato } - AnimationKey { - 4; - 2; - 0;16;-0.000000,-1.000000,0.000000,0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,2.893634,1.000000;;, - 5;16;0.073850,-0.972274,-0.221879,0.000000,0.972620,0.119380,-0.199397,0.000000,0.220356,-0.201078,0.954469,0.000000,0.000000,0.000000,2.893634,1.000000;;; - } - } - - Animation Animation34 { - { R_Tumasaki } - AnimationKey { - 4; - 2; - 0;16;0.173648,0.000000,-0.984808,0.000000,0.000000,1.000000,0.000000,0.000000,0.984808,0.000000,0.173648,0.000000,-0.000000,-0.000000,0.550000,1.000000;;, - 5;16;0.284304,0.000000,-0.958734,0.000000,-0.000000,1.000000,-0.000000,0.000000,0.958734,0.000000,0.284304,0.000000,-0.000000,-0.000000,0.550000,1.000000;;; - } - } - - Animation Animation35 { - { Bone_neck } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,3.000000,1.000000;;, - 5;16;1.000000,-0.000000,-0.000000,0.000000,-0.000000,0.999999,-0.001465,0.000000,0.000000,0.001465,0.999999,0.000000,0.000000,0.000000,3.000000,1.000000;;; - } - } - - Animation Animation36 { - { Bone_Head } - AnimationKey { - 4; - 2; - 0;16;0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.407194,1.000000;;, - 5;16;-0.334617,0.000000,0.942354,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.942354,-0.000000,-0.334617,0.000000,0.000000,0.000000,1.407194,1.000000;;; - } - } - - Animation Animation37 { - { R_Wpn2 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.100000,-0.265000,0.600000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.100000,-0.265000,0.600000,1.000000;;; - } - } - - Animation Animation38 { - { L_Wpn } - AnimationKey { - 4; - 2; - 0;16;0.999848,0.000000,-0.017452,0.000000,0.000000,1.000000,0.000000,0.000000,0.017452,0.000000,0.999848,0.000000,0.000000,0.000000,0.800001,1.000000;;, - 5;16;1.000000,0.000000,-0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.800001,1.000000;;; - } - } - - Animation Animation39 { - { BarniaBaseR } - AnimationKey { - 4; - 2; - 0;16;-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.033058,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;, - 5;16;-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.033058,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;; - } - } - - Animation Animation40 { - { BarniaBaseL } - AnimationKey { - 4; - 2; - 0;16;-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.033058,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;, - 5;16;-0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.033058,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;; - } - } - - Animation Animation41 { - { BarniaBaseL_2 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.999848,0.017452,0.000000,0.000000,-0.017452,0.999848,0.000000,0.000000,0.000000,0.500000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.500000,1.000000;;; - } - } - - Animation Animation42 { - { BarniaBaseR_2 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.999848,0.017452,0.000000,0.000000,-0.017452,0.999848,0.000000,0.000000,0.000000,0.500000,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,0.000000,0.500000,1.000000;;; - } - } - - Animation Animation43 { - { SW2_R_mp } - AnimationKey { - 4; - 2; - 0;16;0.732543,0.000000,-0.680721,0.000000,0.000000,1.000000,0.000000,0.000000,0.680721,0.000000,0.732543,0.000000,1.300000,-1.000000,3.000000,1.000000;;, - 5;16;0.732543,0.000000,-0.680721,0.000000,0.000000,1.000000,0.000000,0.000000,0.680721,0.000000,0.732543,0.000000,1.300000,-1.000000,3.000000,1.000000;;; - } - } - - Animation Animation44 { - { SW2_R_mp_2 } - AnimationKey { - 4; - 2; - 0;16;-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,1.000000;;, - 5;16;-0.000000,1.000000,-0.000000,0.000000,-0.342020,0.000000,0.939693,0.000000,0.939693,0.000000,0.342020,0.000000,0.000000,0.000000,1.000000,1.000000;;; - } - } - - Animation Animation45 { - { SW2_L_mp } - AnimationKey { - 4; - 2; - 0;16;0.732543,0.000000,-0.680721,0.000000,0.000000,1.000000,0.000000,0.000000,0.680721,0.000000,0.732543,0.000000,1.300000,1.000000,3.000000,1.000000;;, - 5;16;0.732543,0.000000,-0.680721,0.000000,0.000000,1.000000,0.000000,0.000000,0.680721,0.000000,0.732543,0.000000,1.300000,1.000000,3.000000,1.000000;;; - } - } - - Animation Animation46 { - { SW2_L_mp_2 } - AnimationKey { - 4; - 2; - 0;16;-0.000000,1.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,1.000000,0.000000,-0.000000,0.000000,0.000000,0.000000,1.000000,1.000000;;, - 5;16;-0.000000,1.000000,-0.000000,0.000000,-0.342020,0.000000,0.939693,0.000000,0.939693,0.000000,0.342020,0.000000,0.000000,0.000000,1.000000,1.000000;;; - } - } - - Animation Animation47 { - { L_Mune_A2 } - AnimationKey { - 4; - 2; - 0;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.051190,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.051190,1.000000;;; - } - } - - Animation Animation48 { - { R_Mune2 } - AnimationKey { - 4; - 2; - 0;16;0.999848,0.000000,0.017452,0.000000,0.000000,1.000000,0.000000,0.000000,-0.017452,0.000000,0.999848,0.000000,0.000000,0.000000,1.051190,1.000000;;, - 5;16;1.000000,0.000000,0.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-0.000000,0.000000,1.000000,0.000000,0.000000,0.000000,1.051190,1.000000;;; - } - } - - Animation Animation49 { - { M_barnia1_1 } - AnimationKey { - 4; - 2; - 0;16;-0.058452,-0.000000,-0.998290,0.000000,0.017423,0.999848,-0.001020,0.000000,0.998138,-0.017452,-0.058443,0.000000,0.000000,0.000000,3.000000,1.000000;;, - 5;16;-0.058452,0.000000,-0.998290,0.000000,0.000000,1.000000,-0.000000,0.000000,0.998290,-0.000000,-0.058452,0.000000,0.000000,0.000000,3.000000,1.000000;;; - } - } - - Animation Animation50 { - { M_barnia1_2 } - AnimationKey { - 4; - 2; - 0;16;0.029667,0.000000,0.999560,0.000000,0.000000,1.000000,0.000000,0.000000,-0.999560,0.000000,0.029667,0.000000,0.000000,0.000000,2.548788,1.000000;;, - 5;16;0.000000,0.000000,1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,2.548788,1.000000;;; - } - } - - Animation Animation51 { - { M_barnia2_1 } - AnimationKey { - 4; - 2; - 0;16;-0.399620,0.000000,-0.916681,0.000000,0.015998,0.999848,-0.006974,0.000000,0.916541,-0.017452,-0.399560,0.000000,0.000000,0.000000,3.000000,1.000000;;, - 5;16;-0.399620,-0.000000,-0.916681,0.000000,0.000000,1.000000,-0.000000,0.000000,0.916681,-0.000000,-0.399620,0.000000,0.000000,0.000000,3.000000,1.000000;;; - } - } - - Animation Animation52 { - { M_barnia2_2 } - AnimationKey { - 4; - 2; - 0;16;-0.277314,-0.000000,0.960779,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.960779,-0.000000,-0.277314,0.000000,0.000000,0.000000,2.261806,1.000000;;, - 5;16;-0.376224,0.000000,0.926529,0.000000,-0.000000,1.000000,-0.000000,0.000000,-0.926529,-0.000000,-0.376224,0.000000,0.000000,0.000000,2.261806,1.000000;;; - } - } -} diff --git a/examples/models/xfile/texture/SSR06_Born2_bp_base.png b/examples/models/xfile/texture/SSR06_Born2_bp_base.png deleted file mode 100644 index a5b7ab06821ccf..00000000000000 Binary files a/examples/models/xfile/texture/SSR06_Born2_bp_base.png and /dev/null differ diff --git a/examples/models/xfile/texture/SSR06_Born2_dif.png b/examples/models/xfile/texture/SSR06_Born2_dif.png deleted file mode 100644 index bcd9af82045e78..00000000000000 Binary files a/examples/models/xfile/texture/SSR06_Born2_dif.png and /dev/null differ diff --git a/examples/models/xfile/wark.x b/examples/models/xfile/wark.x deleted file mode 100644 index a1a6fec130ed90..00000000000000 --- a/examples/models/xfile/wark.x +++ /dev/null @@ -1,1945 +0,0 @@ -xof 0303txt 0032 - - -AnimationSet wark { - - Animation Animation0 { - { AllPutting_2_Layer1 } - AnimationKey { - 0; - 8; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 4;4;1.000000,0.000000,0.000000,0.000000;;, - 10;4;1.000000,0.000000,0.000000,0.000000;;, - 16;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 24;4;1.000000,0.000000,0.000000,0.000000;;, - 28;4;1.000000,0.000000,0.000000,0.000000;;, - 32;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,5.378797,0.000000;;, - 4;3;0.000000,6.500000,0.00366;;, - 10;3;0.000000,6.119430,0.001828;;, - 16;3;0.000000,5.468813,0.000000;;, - 20;3;0.000000,6.500000,0.00366;;, - 24;3;0.000000,6.325220,0.002817;;, - 28;3;0.000000,5.991163,0.001212;;, - 32;3;0.000000,5.738859,-0.000000;;; - } - } - - Animation Animation1 { - { Bone01 } - AnimationKey { - 0; - 8; - 0;4;0.405580,0.579228,0.579228,0.405580;;, - 4;4;0.398926,0.581063,0.583831,0.402947;;, - 10;4;0.395452,0.583664,0.586189,0.399169;;, - 16;4;0.392996,0.586148,0.587839,0.395513;;, - 20;4;0.391766,0.587444,0.588659,0.393585;;, - 24;4;0.391396,0.588157,0.588905,0.392519;;, - 28;4;0.392693,0.587739,0.588041,0.393145;;, - 32;4;0.405580,0.579228,0.579228,0.405580;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,6.600000,0.000000;;, - 4;3;0.000000,6.600000,0.000000;;, - 10;3;0.000000,6.600000,0.000000;;, - 16;3;0.000000,6.600000,0.000000;;, - 20;3;0.000000,6.600000,0.000000;;, - 24;3;0.000000,6.600000,0.000000;;, - 28;3;0.000000,6.600000,0.000000;;, - 32;3;0.000000,6.600000,0.000000;;; - } - } - - Animation Animation2 { - { L_Mune_A } - AnimationKey { - 0; - 8; - 0;4;0.511753,0.487964,0.487964,0.511753;;, - 4;4;0.511753,0.487964,0.487964,0.511753;;, - 10;4;0.511753,0.487964,0.487964,0.511753;;, - 16;4;0.511753,0.487964,0.487964,0.511753;;, - 20;4;0.511753,0.487964,0.487964,0.511753;;, - 24;4;0.511753,0.487964,0.487964,0.511753;;, - 28;4;0.511753,0.487964,0.487964,0.511753;;, - 32;4;0.511753,0.487964,0.487964,0.511753;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,3.000000;;, - 4;3;0.000000,0.000000,3.000000;;, - 10;3;0.000000,0.000000,3.000000;;, - 16;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 24;3;0.000000,0.000000,3.000000;;, - 28;3;0.000000,0.000000,3.000000;;, - 32;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation3 { - { L_Kata_Base } - AnimationKey { - 0; - 8; - 0;4;0.965276,-0.061520,0.000193,-0.253885;;, - 4;4;0.974451,-0.046756,-0.003910,-0.219645;;, - 10;4;0.995645,-0.003072,-0.009464,-0.092694;;, - 16;4;0.999182,0.034549,-0.005154,0.020386;;, - 20;4;0.999392,0.017260,-0.008109,-0.029194;;, - 24;4;0.993565,-0.011765,-0.009239,-0.112224;;, - 28;4;0.979536,-0.041522,-0.005384,-0.196814;;, - 32;4;0.965276,-0.061520,0.000193,-0.253885;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.150000,0.450000,1.051190;;, - 4;3;-0.150000,0.450000,1.051190;;, - 10;3;-0.150000,0.450000,1.051190;;, - 16;3;-0.150000,0.450000,1.051190;;, - 20;3;-0.150000,0.450000,1.051190;;, - 24;3;-0.150000,0.450000,1.051190;;, - 28;3;-0.150000,0.450000,1.051190;;, - 32;3;-0.150000,0.450000,1.051190;;; - } - } - - Animation Animation4 { - { L_Ueude } - AnimationKey { - 0; - 8; - 0;4;0.783000,-0.021687,0.621042,0.027343;;, - 4;4;0.792948,-0.017929,0.608577,0.023361;;, - 10;4;0.824285,-0.007804,0.566007,0.011366;;, - 16;4;0.849440,0.000000,0.527685,0.000000;;, - 20;4;0.837865,-0.002488,0.545858,0.003820;;, - 24;4;0.817902,-0.007523,0.575209,0.010698;;, - 28;4;0.796448,-0.013696,0.604283,0.018052;;, - 32;4;0.783000,-0.021687,0.621042,0.027343;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.030000,0.010000,0.800000;;, - 4;3;0.030000,0.010000,0.800000;;, - 10;3;0.030000,0.010000,0.800000;;, - 16;3;0.030000,0.010000,0.800000;;, - 20;3;0.030000,0.010000,0.800000;;, - 24;3;0.030000,0.010000,0.800000;;, - 28;3;0.030000,0.010000,0.800000;;, - 32;3;0.030000,0.010000,0.800000;;; - } - } - - Animation Animation5 { - { L_Hizi } - AnimationKey { - 0; - 8; - 0;4;0.985944,-0.167074,-0.000000,0.000000;;, - 4;4;0.985985,-0.166837,-0.000000,0.000000;;, - 10;4;0.986369,-0.164548,-0.000000,0.000000;;, - 16;4;0.986802,-0.161932,-0.000000,0.000000;;, - 20;4;0.987125,-0.159949,-0.000000,0.000000;;, - 24;4;0.987391,-0.158303,-0.000000,0.000000;;, - 28;4;0.987448,-0.157944,-0.000000,0.000000;;, - 32;4;0.985944,-0.167074,-0.000000,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.000000,0.000000,1.500000;;, - 4;3;-0.000000,0.000000,1.500000;;, - 10;3;-0.000000,0.000000,1.500000;;, - 16;3;-0.000000,0.000000,1.500000;;, - 20;3;-0.000000,0.000000,1.500000;;, - 24;3;-0.000000,0.000000,1.500000;;, - 28;3;-0.000000,0.000000,1.500000;;, - 32;3;-0.000000,0.000000,1.500000;;; - } - } - - Animation Animation6 { - { L_Sitaude } - AnimationKey { - 0; - 8; - 0;4;0.939040,-0.343343,0.016764,-0.006129;;, - 4;4;0.925085,-0.379488,0.013270,-0.005444;;, - 10;4;0.891084,-0.453793,0.005792,-0.002950;;, - 16;4;0.857972,-0.513696,0.000000,0.000000;;, - 20;4;0.874004,-0.485904,0.003201,-0.001780;;, - 24;4;0.898692,-0.438479,0.008477,-0.004136;;, - 28;4;0.921835,-0.387284,0.014001,-0.005832;;, - 32;4;0.939040,-0.343343,0.016764,-0.006129;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.000000,0.000000,0.450000;;, - 4;3;-0.000000,0.000000,0.450000;;, - 10;3;-0.000000,0.000000,0.450000;;, - 16;3;-0.000000,0.000000,0.450000;;, - 20;3;-0.000000,0.000000,0.450000;;, - 24;3;-0.000000,0.000000,0.450000;;, - 28;3;-0.000000,0.000000,0.450000;;, - 32;3;-0.000000,0.000000,0.450000;;; - } - } - - Animation Animation7 { - { L_kata_Armer } - AnimationKey { - 0; - 8; - 0;4;0.980576,0.000000,-0.196138,0.000000;;, - 4;4;0.980598,0.000000,-0.196027,0.000000;;, - 10;4;0.980837,0.000000,-0.194829,0.000000;;, - 16;4;0.981054,0.000000,-0.193732,0.000000;;, - 20;4;0.980969,0.000000,-0.194163,0.000000;;, - 24;4;0.980822,0.000000,-0.194905,0.000000;;, - 28;4;0.980677,0.000000,-0.195634,0.000000;;, - 32;4;0.980576,0.000000,-0.196138,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.050000,-0.000000,0.800000;;, - 4;3;-0.050000,-0.000000,0.800000;;, - 10;3;-0.050000,-0.000000,0.800000;;, - 16;3;-0.050000,-0.000000,0.800000;;, - 20;3;-0.050000,-0.000000,0.800000;;, - 24;3;-0.050000,-0.000000,0.800000;;, - 28;3;-0.050000,-0.000000,0.800000;;, - 32;3;-0.050000,-0.000000,0.800000;;; - } - } - - Animation Animation8 { - { L_Kata_S_Joint_1 } - AnimationKey { - 0; - 8; - 0;4;0.686912,-0.000000,0.726741,-0.000000;;, - 4;4;0.687634,-0.000000,0.726057,-0.000000;;, - 10;4;0.695401,-0.000000,0.718621,-0.000000;;, - 16;4;0.702439,-0.000000,0.711744,-0.000000;;, - 20;4;0.699679,-0.000000,0.714458,-0.000000;;, - 24;4;0.694913,-0.000000,0.719094,-0.000000;;, - 28;4;0.690192,-0.000000,0.723626,-0.000000;;, - 32;4;0.686912,-0.000000,0.726741,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.000000,-0.000000,1.491643;;, - 4;3;-0.000000,-0.000000,1.491643;;, - 10;3;-0.000000,-0.000000,1.491643;;, - 16;3;-0.000000,-0.000000,1.491643;;, - 20;3;-0.000000,-0.000000,1.491643;;, - 24;3;-0.000000,-0.000000,1.491643;;, - 28;3;-0.000000,-0.000000,1.491643;;, - 32;3;-0.000000,-0.000000,1.491643;;; - } - } - - Animation Animation9 { - { L_kata_S_Joint_2 } - AnimationKey { - 0; - 8; - 0;4;0.761602,0.000000,-0.648046,-0.000000;;, - 4;4;0.762255,0.000000,-0.647277,-0.000000;;, - 10;4;0.769268,0.000000,-0.638926,-0.000000;;, - 16;4;0.775606,0.000000,-0.631217,-0.000000;;, - 20;4;0.773122,0.000000,-0.634257,-0.000000;;, - 24;4;0.768827,0.000000,-0.639456,-0.000000;;, - 28;4;0.764567,0.000000,-0.644545,-0.000000;;, - 32;4;0.761602,0.000000,-0.648046,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.000000,0.000000,1.350000;;, - 4;3;-0.000000,0.000000,1.350000;;, - 10;3;-0.000000,0.000000,1.350000;;, - 16;3;-0.000000,0.000000,1.350000;;, - 20;3;-0.000000,0.000000,1.350000;;, - 24;3;-0.000000,0.000000,1.350000;;, - 28;3;-0.000000,0.000000,1.350000;;, - 32;3;-0.000000,0.000000,1.350000;;; - } - } - - Animation Animation10 { - { L_Kata_S_End } - AnimationKey { - 0; - 8; - 0;4;0.707107,-0.000000,0.707107,0.000000;;, - 4;4;0.707107,-0.000000,0.707107,0.000000;;, - 10;4;0.707107,-0.000000,0.707107,0.000000;;, - 16;4;0.707107,-0.000000,0.707107,0.000000;;, - 20;4;0.707107,-0.000000,0.707107,0.000000;;, - 24;4;0.707107,-0.000000,0.707107,0.000000;;, - 28;4;0.707107,-0.000000,0.707107,0.000000;;, - 32;4;0.707107,-0.000000,0.707107,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.000000,-0.000000,1.350000;;, - 4;3;-0.000000,-0.000000,1.350000;;, - 10;3;-0.000000,-0.000000,1.350000;;, - 16;3;-0.000000,-0.000000,1.350000;;, - 20;3;-0.000000,-0.000000,1.350000;;, - 24;3;-0.000000,-0.000000,1.350000;;, - 28;3;-0.000000,-0.000000,1.350000;;, - 32;3;-0.000000,-0.000000,1.350000;;; - } - } - - Animation Animation11 { - { L_Hand } - AnimationKey { - 0; - 5; - 0;4;0.991834,-0.000000,0.127537,-0.000000;;, - 4;4;0.991983,-0.000107,0.126368,-0.000014;;, - 10;4;0.991920,-0.000228,0.126862,-0.000029;;, - 16;4;0.991671,-0.000679,0.128798,-0.000088;;, - 28;4;0.990597,-0.002870,0.136784,-0.000396;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;-0.000000,0.280000,2.000000;;, - 4;3;-0.000000,0.280000,2.000000;;, - 10;3;-0.000000,0.280000,2.000000;;, - 16;3;-0.000000,0.280000,2.000000;;, - 28;3;-0.000000,0.280000,2.000000;;; - } - } - - Animation Animation12 { - { Kosi } - AnimationKey { - 0; - 8; - 0;4;0.847122,-0.531397,-0.000464,0.000739;;, - 4;4;0.848758,-0.528781,-0.000461,0.000741;;, - 10;4;0.848107,-0.529825,-0.000462,0.000740;;, - 16;4;0.847122,-0.531397,-0.000464,0.000739;;, - 20;4;0.846991,-0.531607,-0.000464,0.000739;;, - 24;4;0.851417,-0.524489,-0.000458,0.000743;;, - 28;4;0.855106,-0.518453,-0.000452,0.000746;;, - 32;4;0.847122,-0.531397,-0.000464,0.000739;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,6.600000,0.000000;;, - 4;3;0.000000,6.600000,0.000000;;, - 10;3;0.000000,6.600000,0.000000;;, - 16;3;0.000000,6.600000,0.000000;;, - 20;3;0.000000,6.600000,0.000000;;, - 24;3;0.000000,6.600000,0.000000;;, - 28;3;0.000000,6.600000,0.000000;;, - 32;3;0.000000,6.600000,0.000000;;; - } - } - - Animation Animation13 { - { L_Kosi_Momo } - AnimationKey { - 0; - 8; - 0;4;0.707107,0.000000,-0.707107,0.000000;;, - 4;4;0.707107,0.000000,-0.707107,0.000000;;, - 10;4;0.707107,0.000000,-0.707107,0.000000;;, - 16;4;0.707107,0.000000,-0.707107,0.000000;;, - 20;4;0.707107,0.000000,-0.707107,0.000000;;, - 24;4;0.707107,0.000000,-0.707107,0.000000;;, - 28;4;0.707107,0.000000,-0.707107,0.000000;;, - 32;4;0.707107,0.000000,-0.707107,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,0.650000;;, - 4;3;0.000000,0.000000,0.650000;;, - 10;3;0.000000,0.000000,0.650000;;, - 16;3;0.000000,0.000000,0.650000;;, - 20;3;0.000000,0.000000,0.650000;;, - 24;3;0.000000,0.000000,0.650000;;, - 28;3;0.000000,0.000000,0.650000;;, - 32;3;0.000000,0.000000,0.650000;;; - } - } - - Animation Animation14 { - { L_momo } - AnimationKey { - 0; - 8; - 0;4;0.699068,0.195973,0.664870,0.175630;;, - 4;4;0.621133,-0.360287,0.591862,-0.366177;;, - 10;4;0.513253,-0.502177,0.497417,-0.486791;;, - 16;4;0.513280,-0.505702,0.494357,-0.486231;;, - 20;4;0.670218,-0.248930,0.661644,-0.225986;;, - 24;4;0.714115,0.094911,0.688105,0.086848;;, - 28;4;0.704441,0.171518,0.671446,0.153313;;, - 32;4;0.699068,0.195973,0.664870,0.175630;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,-0.000000,1.650000;;, - 4;3;0.000000,-0.000000,1.650000;;, - 10;3;0.000000,-0.000000,1.650000;;, - 16;3;0.000000,-0.000000,1.650000;;, - 20;3;0.000000,-0.000000,1.650000;;, - 24;3;0.000000,-0.000000,1.650000;;, - 28;3;0.000000,-0.000000,1.650000;;, - 32;3;0.000000,-0.000000,1.650000;;; - } - } - - Animation Animation15 { - { L_Hiza } - AnimationKey { - 0; - 9; - 0;4;0.999421,-0.034027,0.000000,0.000000;;, - 4;4;0.999025,-0.044141,0.000000,0.000000;;, - 6;4;0.999355,-0.035896,0.000000,0.000000;;, - 10;4;0.999725,0.023446,0.000000,0.000000;;, - 16;4;0.995142,0.098451,0.000000,0.000000;;, - 20;4;0.999244,0.038880,0.000000,0.000000;;, - 24;4;0.999422,-0.033994,0.000000,0.000000;;, - 28;4;0.999485,-0.032099,0.000000,0.000000;;, - 32;4;0.999421,-0.034027,0.000000,0.000000;;; - } - AnimationKey { - 1; - 9; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 6;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 9; - 0;3;0.000000,0.000000,1.400000;;, - 4;3;0.000000,0.000000,1.400000;;, - 6;3;0.000000,0.000000,1.400000;;, - 10;3;0.000000,0.000000,1.400000;;, - 16;3;0.000000,0.000000,1.400000;;, - 20;3;0.000000,0.000000,1.400000;;, - 24;3;0.000000,0.000000,1.400000;;, - 28;3;0.000000,0.000000,1.400000;;, - 32;3;0.000000,0.000000,1.400000;;; - } - } - - Animation Animation16 { - { L_Sune } - AnimationKey { - 0; - 12; - 0;4;0.988843,0.148959,0.000000,0.000000;;, - 4;4;0.929700,0.368317,0.000000,0.000000;;, - 6;4;0.878193,0.478307,0.000000,0.000000;;, - 10;4;0.869994,0.493062,0.000000,0.000000;;, - 14;4;0.873631,0.486588,0.000000,0.000000;;, - 16;4;0.873631,0.486588,0.000000,0.000000;;, - 20;4;0.909784,0.415083,0.000000,0.000000;;, - 22;4;0.933178,0.359413,0.000000,0.000000;;, - 24;4;0.970838,0.239737,0.000000,0.000000;;, - 25;4;0.982650,0.185469,0.000000,0.000000;;, - 28;4;0.994313,0.106499,0.000000,0.000000;;, - 32;4;0.988843,0.148959,0.000000,0.000000;;; - } - AnimationKey { - 1; - 12; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 6;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 14;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 22;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 25;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 12; - 0;3;0.000000,0.000000,0.800000;;, - 4;3;0.000000,0.000000,0.800000;;, - 6;3;0.000000,0.000000,0.800000;;, - 10;3;0.000000,0.000000,0.800000;;, - 14;3;0.000000,0.000000,0.800000;;, - 16;3;0.000000,0.000000,0.800000;;, - 20;3;0.000000,0.000000,0.800000;;, - 22;3;0.000000,0.000000,0.800000;;, - 24;3;0.000000,0.000000,0.800000;;, - 25;3;0.000000,0.000000,0.800000;;, - 28;3;0.000000,0.000000,0.800000;;, - 32;3;0.000000,0.000000,0.800000;;; - } - } - - Animation Animation17 { - { L_Kakato } - AnimationKey { - 0; - 11; - 0;4;0.698095,0.038975,0.081512,0.710232;;, - 3;4;0.713869,0.016752,0.035694,0.699118;;, - 4;4;0.720164,0.010364,0.021031,0.693408;;, - 6;4;0.729083,0.000088,0.000185,0.684425;;, - 10;4;0.719676,-0.007498,0.007731,0.694227;;, - 12;4;0.713665,-0.013440,0.011133,0.700269;;, - 16;4;0.702781,-0.041323,0.000365,0.710205;;, - 20;4;0.705042,-0.009514,0.029026,0.708507;;, - 24;4;0.706742,0.026130,0.059362,0.704492;;, - 28;4;0.701827,0.039277,0.077045,0.707079;;, - 32;4;0.698095,0.038975,0.081512,0.710232;;; - } - AnimationKey { - 1; - 11; - 0;3;1.000000,1.000000,1.000000;;, - 3;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 6;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 12;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 11; - 0;3;-0.037573,-0.006428,2.820891;;, - 3;3;-0.037573,-0.006428,2.402337;;, - 4;3;-0.037573,-0.006428,2.500516;;, - 6;3;-0.037573,-0.006428,2.820891;;, - 10;3;-0.037573,-0.006428,2.838690;;, - 12;3;-0.037573,-0.006428,2.820891;;, - 16;3;-0.037573,-0.006428,2.820891;;, - 20;3;-0.037573,-0.006428,2.694254;;, - 24;3;-0.037573,-0.006428,2.820891;;, - 28;3;-0.037573,-0.006428,2.831444;;, - 32;3;-0.037573,-0.006428,2.820891;;; - } - } - - Animation Animation18 { - { L_Tumasaki } - AnimationKey { - 0; - 10; - 0;4;0.646076,-0.000000,-0.763273,0.000000;;, - 2;4;0.543896,-0.000000,-0.839153,0.000000;;, - 4;4;0.772689,0.000000,-0.634784,0.000000;;, - 6;4;0.767887,-0.000000,-0.640585,0.000000;;, - 10;4;0.780211,-0.000000,-0.625516,0.000000;;, - 16;4;0.738414,0.000000,-0.674348,0.000000;;, - 20;4;0.608663,0.000000,-0.793429,-0.000000;;, - 24;4;0.677005,0.000000,-0.735978,-0.000000;;, - 28;4;0.667589,0.000000,-0.744530,-0.000000;;, - 32;4;0.646076,-0.000000,-0.763273,0.000000;;; - } - AnimationKey { - 1; - 10; - 0;3;1.000000,1.000000,1.000000;;, - 52;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 6;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 10; - 0;3;-0.000000,-0.000000,0.550000;;, - 52;3;-0.000000,-0.000000,0.550000;;, - 4;3;-0.000000,-0.000000,0.550000;;, - 6;3;-0.000000,-0.000000,0.550000;;, - 10;3;-0.000000,-0.000000,0.550000;;, - 16;3;-0.000000,-0.000000,0.550000;;, - 20;3;-0.000000,-0.000000,0.550000;;, - 24;3;-0.000000,-0.000000,0.550000;;, - 28;3;-0.000000,-0.000000,0.550000;;, - 32;3;-0.000000,-0.000000,0.550000;;; - } - } - - Animation Animation19 { - { R_Mune } - AnimationKey { - 0; - 8; - 0;4;0.511753,-0.487964,-0.487964,0.511753;;, - 4;4;0.511753,-0.487964,-0.487964,0.511753;;, - 10;4;0.511753,-0.487964,-0.487964,0.511753;;, - 16;4;0.511753,-0.487964,-0.487964,0.511753;;, - 20;4;0.511753,-0.487964,-0.487964,0.511753;;, - 24;4;0.511753,-0.487964,-0.487964,0.511753;;, - 28;4;0.511753,-0.487964,-0.487964,0.511753;;, - 32;4;0.511753,-0.487964,-0.487964,0.511753;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,3.000000;;, - 4;3;0.000000,0.000000,3.000000;;, - 10;3;0.000000,0.000000,3.000000;;, - 16;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 24;3;0.000000,0.000000,3.000000;;, - 28;3;0.000000,0.000000,3.000000;;, - 32;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation20 { - { R_Kata_Base } - AnimationKey { - 0; - 8; - 0;4;0.975579,0.025319,-0.029939,-0.216119;;, - 4;4;0.985662,0.027035,-0.028581,-0.164079;;, - 10;4;0.998594,0.030525,-0.024854,-0.035493;;, - 16;4;0.996513,0.033040,-0.021379,0.073577;;, - 20;4;0.999045,0.031780,-0.023153,0.019029;;, - 24;4;0.996790,0.029547,-0.025880,-0.069760;;, - 28;4;0.986358,0.027028,-0.028445,-0.159869;;, - 32;4;0.975579,0.025319,-0.029939,-0.216119;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.110000,0.450000,0.000000;;, - 4;3;0.110000,0.450000,0.000000;;, - 10;3;0.110000,0.450000,0.000000;;, - 16;3;0.110000,0.450000,0.000000;;, - 20;3;0.110000,0.450000,0.000000;;, - 24;3;0.110000,0.450000,0.000000;;, - 28;3;0.110000,0.450000,0.000000;;, - 32;3;0.110000,0.450000,0.000000;;; - } - } - - Animation Animation21 { - { R_Ueude } - AnimationKey { - 0; - 8; - 0;4;0.844410,0.000000,-0.535698,-0.000000;;, - 4;4;0.843975,0.000000,-0.536382,-0.000000;;, - 10;4;0.846426,0.000000,-0.532506,-0.000000;;, - 16;4;0.849945,0.000000,-0.526872,-0.000000;;, - 20;4;0.855252,0.000000,-0.518212,-0.000000;;, - 24;4;0.850235,0.000000,-0.526403,-0.000000;;, - 28;4;0.844066,0.000000,-0.536239,-0.000000;;, - 32;4;0.844410,0.000000,-0.535698,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.030000,0.010000,0.800000;;, - 4;3;0.030000,0.010000,0.800000;;, - 10;3;0.030000,0.010000,0.800000;;, - 16;3;0.030000,0.010000,0.800000;;, - 20;3;0.030000,0.010000,0.800000;;, - 24;3;0.030000,0.010000,0.800000;;, - 28;3;0.030000,0.010000,0.800000;;, - 32;3;0.030000,0.010000,0.800000;;; - } - } - - Animation Animation22 { - { R_Hizi } - AnimationKey { - 0; - 8; - 0;4;0.980679,-0.195622,0.000000,-0.000000;;, - 4;4;0.980624,-0.195899,0.000000,-0.000000;;, - 10;4;0.980936,-0.194332,0.000000,-0.000000;;, - 16;4;0.981383,-0.192063,0.000000,-0.000000;;, - 20;4;0.982056,-0.188590,0.000000,-0.000000;;, - 24;4;0.981653,-0.190674,0.000000,-0.000000;;, - 28;4;0.981095,-0.193526,0.000000,-0.000000;;, - 32;4;0.980679,-0.195622,0.000000,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.000000,-0.000000,1.500000;;, - 4;3;-0.000000,-0.000000,1.500000;;, - 10;3;-0.000000,-0.000000,1.500000;;, - 16;3;-0.000000,-0.000000,1.500000;;, - 20;3;-0.000000,-0.000000,1.500000;;, - 24;3;-0.000000,-0.000000,1.500000;;, - 28;3;-0.000000,-0.000000,1.500000;;, - 32;3;-0.000000,-0.000000,1.500000;;; - } - } - - Animation Animation23 { - { R_Sitaude } - AnimationKey { - 0; - 8; - 0;4;0.804838,-0.593494,-0.000000,0.000000;;, - 4;4;0.816950,-0.576702,-0.002279,0.001608;;, - 10;4;0.853112,-0.521614,-0.009295,0.005683;;, - 16;4;0.881358,-0.472112,-0.015734,0.008428;;, - 20;4;0.868451,-0.495563,-0.012599,0.007190;;, - 24;4;0.845870,-0.533313,-0.007649,0.004823;;, - 28;4;0.822135,-0.569280,-0.003036,0.002103;;, - 32;4;0.804838,-0.593494,0.000000,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,-0.000000,0.450000;;, - 4;3;0.000000,-0.000000,0.450000;;, - 10;3;0.000000,-0.000000,0.450000;;, - 16;3;0.000000,-0.000000,0.450000;;, - 20;3;0.000000,-0.000000,0.450000;;, - 24;3;0.000000,-0.000000,0.450000;;, - 28;3;0.000000,-0.000000,0.450000;;, - 32;3;0.000000,-0.000000,0.450000;;; - } - } - - Animation Animation24 { - { R_kata_Armer } - AnimationKey { - 0; - 8; - 0;4;0.928434,0.000000,0.371498,0.000000;;, - 4;4;0.928376,0.000000,0.371641,0.000000;;, - 10;4;0.929324,0.000000,0.369266,0.000000;;, - 16;4;0.930218,0.000000,0.367008,0.000000;;, - 20;4;0.929909,0.000000,0.367789,0.000000;;, - 24;4;0.929359,0.000000,0.369178,0.000000;;, - 28;4;0.928813,0.000000,0.370550,0.000000;;, - 32;4;0.928434,0.000000,0.371498,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;-0.050000,0.000000,0.800000;;, - 4;3;-0.050000,0.000000,0.800000;;, - 10;3;-0.050000,0.000000,0.800000;;, - 16;3;-0.050000,0.000000,0.800000;;, - 20;3;-0.050000,0.000000,0.800000;;, - 24;3;-0.050000,0.000000,0.800000;;, - 28;3;-0.050000,0.000000,0.800000;;, - 32;3;-0.050000,0.000000,0.800000;;; - } - } - - Animation Animation25 { - { R_Kata_S_Joint_1 } - AnimationKey { - 0; - 8; - 0;4;0.714836,0.000000,-0.699292,-0.000000;;, - 4;4;0.714567,0.000000,-0.699567,-0.000000;;, - 10;4;0.719028,0.000000,-0.694981,-0.000000;;, - 16;4;0.723237,0.000000,-0.690600,-0.000000;;, - 20;4;0.721786,0.000000,-0.692117,-0.000000;;, - 24;4;0.719192,0.000000,-0.694811,-0.000000;;, - 28;4;0.716621,0.000000,-0.697463,-0.000000;;, - 32;4;0.714836,0.000000,-0.699292,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,1.491643;;, - 4;3;0.000000,0.000000,1.491643;;, - 10;3;0.000000,0.000000,1.491643;;, - 16;3;0.000000,0.000000,1.491643;;, - 20;3;0.000000,0.000000,1.491643;;, - 24;3;0.000000,0.000000,1.491643;;, - 28;3;0.000000,0.000000,1.491643;;, - 32;3;0.000000,0.000000,1.491643;;; - } - } - - Animation Animation26 { - { R_kata_S_Joint_2 } - AnimationKey { - 0; - 8; - 0;4;0.892586,0.000000,0.450878,0.000000;;, - 4;4;0.892586,0.000000,0.450878,0.000000;;, - 10;4;0.892586,0.000000,0.450878,0.000000;;, - 16;4;0.892586,0.000000,0.450878,0.000000;;, - 20;4;0.892586,0.000000,0.450878,0.000000;;, - 24;4;0.892586,0.000000,0.450878,0.000000;;, - 28;4;0.892586,0.000000,0.450878,0.000000;;, - 32;4;0.892586,0.000000,0.450878,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,1.350000;;, - 4;3;0.000000,0.000000,1.350000;;, - 10;3;0.000000,0.000000,1.350000;;, - 16;3;0.000000,0.000000,1.350000;;, - 20;3;0.000000,0.000000,1.350000;;, - 24;3;0.000000,0.000000,1.350000;;, - 28;3;0.000000,0.000000,1.350000;;, - 32;3;0.000000,0.000000,1.350000;;; - } - } - - Animation Animation27 { - { R_Kata_S_End } - AnimationKey { - 0; - 8; - 0;4;-0.707107,-0.000000,0.707107,0.000000;;, - 4;4;-0.707107,-0.000000,0.707107,0.000000;;, - 10;4;-0.707107,-0.000000,0.707107,0.000000;;, - 16;4;-0.707107,-0.000000,0.707107,0.000000;;, - 20;4;-0.707107,-0.000000,0.707107,0.000000;;, - 24;4;-0.707107,-0.000000,0.707107,0.000000;;, - 28;4;-0.707107,-0.000000,0.707107,0.000000;;, - 32;4;-0.707107,-0.000000,0.707107,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,1.350000;;, - 4;3;0.000000,0.000000,1.350000;;, - 10;3;0.000000,0.000000,1.350000;;, - 16;3;0.000000,0.000000,1.350000;;, - 20;3;0.000000,0.000000,1.350000;;, - 24;3;0.000000,0.000000,1.350000;;, - 28;3;0.000000,0.000000,1.350000;;, - 32;3;0.000000,0.000000,1.350000;;; - } - } - - Animation Animation28 { - { R_Hand } - AnimationKey { - 0; - 5; - 0;4;0.993909,0.000000,-0.110208,-0.000000;;, - 4;4;0.993909,0.000000,-0.110208,-0.000000;;, - 10;4;0.993909,0.000000,-0.110208,-0.000000;;, - 16;4;0.993909,0.000000,-0.110208,-0.000000;;, - 28;4;0.993909,0.000000,-0.110208,-0.000000;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;0.000000,0.000000,2.000000;;, - 4;3;0.000000,0.000000,2.000000;;, - 10;3;0.000000,0.000000,2.000000;;, - 16;3;0.000000,0.000000,2.000000;;, - 28;3;0.000000,0.000000,2.000000;;; - } - } - - Animation Animation29 { - { R_Kosi_Momo } - AnimationKey { - 0; - 8; - 0;4;0.707107,0.000000,0.707107,-0.000000;;, - 4;4;0.707107,0.000000,0.707107,-0.000000;;, - 10;4;0.707107,0.000000,0.707107,-0.000000;;, - 16;4;0.707107,0.000000,0.707107,-0.000000;;, - 20;4;0.707107,0.000000,0.707107,-0.000000;;, - 24;4;0.707107,0.000000,0.707107,-0.000000;;, - 28;4;0.707107,0.000000,0.707107,-0.000000;;, - 32;4;0.707107,0.000000,0.707107,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,0.650000;;, - 4;3;0.000000,0.000000,0.650000;;, - 10;3;0.000000,0.000000,0.650000;;, - 16;3;0.000000,0.000000,0.650000;;, - 20;3;0.000000,0.000000,0.650000;;, - 24;3;0.000000,0.000000,0.650000;;, - 28;3;0.000000,0.000000,0.650000;;, - 32;3;0.000000,0.000000,0.650000;;; - } - } - - Animation Animation30 { - { R_momo } - AnimationKey { - 0; - 8; - 0;4;0.488703,-0.534776,-0.476873,0.497772;;, - 4;4;0.670771,-0.178889,-0.689512,0.206490;;, - 10;4;0.732588,0.105280,-0.668720,-0.071025;;, - 16;4;0.700052,0.164281,-0.676310,-0.159826;;, - 20;4;0.481975,-0.509293,-0.497283,0.510912;;, - 24;4;0.548773,-0.420259,-0.546122,0.473266;;, - 28;4;0.516456,-0.484037,-0.507474,0.491377;;, - 32;4;0.488703,-0.534776,-0.476873,0.497772;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,-0.000000,1.650000;;, - 4;3;0.000000,-0.000000,1.650000;;, - 10;3;0.000000,-0.000000,1.650000;;, - 16;3;0.000000,-0.000000,1.650000;;, - 20;3;0.000000,-0.000000,1.650000;;, - 24;3;0.000000,-0.000000,1.650000;;, - 28;3;0.000000,-0.000000,1.650000;;, - 32;3;0.000000,-0.000000,1.650000;;; - } - } - - Animation Animation31 { - { R_Hiza } - AnimationKey { - 0; - 8; - 0;4;0.991558,0.129661,-0.000000,-0.000000;;, - 4;4;0.996423,0.084503,-0.000000,-0.000000;;, - 10;4;0.999983,0.005756,-0.000000,-0.000000;;, - 16;4;0.999421,-0.034027,0.000000,0.000000;;, - 20;4;0.991711,0.128492,-0.000000,-0.000000;;, - 24;4;0.993018,0.117966,-0.000000,-0.000000;;, - 28;4;0.991261,0.131912,-0.000000,-0.000000;;, - 32;4;0.991558,0.129661,-0.000000,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,-0.000000,1.400000;;, - 4;3;0.000000,-0.000000,1.400000;;, - 10;3;0.000000,-0.000000,1.400000;;, - 16;3;0.000000,-0.000000,1.400000;;, - 20;3;0.000000,-0.000000,1.400000;;, - 24;3;0.000000,-0.000000,1.400000;;, - 28;3;0.000000,-0.000000,1.400000;;, - 32;3;0.000000,-0.000000,1.400000;;; - } - } - - Animation Animation32 { - { R_Sune } - AnimationKey { - 0; - 8; - 0;4;0.874426,0.483706,0.032828,0.018159;;, - 4;4;0.960050,0.277184,0.036867,0.010644;;, - 10;4;0.986868,0.160758,0.015549,0.002533;;, - 16;4;0.988848,0.148931,-0.000000,-0.000000;;, - 20;4;0.877357,0.478370,0.032929,0.017954;;, - 24;4;0.931932,0.360687,0.034986,0.013540;;, - 28;4;0.909607,0.413772,0.034149,0.015534;;, - 32;4;0.874426,0.483706,0.032828,0.018159;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,0.800000;;, - 4;3;0.000000,0.000000,0.800000;;, - 10;3;0.000000,0.000000,0.800000;;, - 16;3;0.000000,0.000000,0.800000;;, - 20;3;0.000000,0.000000,0.800000;;, - 24;3;0.000000,0.000000,0.800000;;, - 28;3;0.000000,0.000000,0.800000;;, - 32;3;0.000000,0.000000,0.800000;;; - } - } - - Animation Animation33 { - { R_Kakato } - AnimationKey { - 0; - 9; - 0;4;0.716004,-0.006239,-0.046159,0.696540;;, - 4;4;0.717534,0.053051,0.015644,0.694324;;, - 10;4;0.717129,0.010260,-0.027575,0.696319;;, - 16;4;0.712599,-0.043780,-0.082471,0.695331;;, - 18;4;0.713845,-0.032249,-0.071386,0.695909;;, - 20;4;0.716097,-0.004691,-0.044709,0.696552;;, - 24;4;0.716835,0.009210,-0.031191,0.696484;;, - 28;4;0.716487,0.001951,-0.038223,0.696550;;, - 32;4;0.716004,-0.006239,-0.046159,0.696540;;; - } - AnimationKey { - 1; - 9; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 18;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 9; - 0;3;0.000000,0.000000,2.893634;;, - 4;3;0.000000,0.000000,2.549442;;, - 10;3;0.000000,0.000000,2.722465;;, - 16;3;0.000000,0.000000,2.893634;;, - 18;3;0.000000,0.000000,2.540794;;, - 20;3;0.000000,0.000000,2.893634;;, - 24;3;0.000000,0.000000,2.893634;;, - 28;3;0.000000,0.000000,2.893634;;, - 32;3;0.000000,0.000000,2.893634;;; - } - } - - Animation Animation34 { - { R_Tumasaki } - AnimationKey { - 0; - 9; - 0;4;0.762063,-0.000000,-0.647503,0.000000;;, - 4;4;0.604558,0.000000,-0.796561,0.000000;;, - 10;4;0.628068,-0.000000,-0.778159,0.000000;;, - 16;4;0.681314,0.000000,-0.731991,0.000000;;, - 18;4;0.635302,-0.000000,-0.772264,0.000000;;, - 20;4;0.794356,0.000000,-0.607453,-0.000000;;, - 24;4;0.774762,0.000000,-0.632253,-0.000000;;, - 28;4;0.788324,0.000000,-0.615260,-0.000000;;, - 32;4;0.796492,0.000000,-0.604649,-0.000000;;; - } - AnimationKey { - 1; - 9; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 18;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 9; - 0;3;-0.000000,-0.000000,0.550000;;, - 4;3;-0.000000,-0.000000,0.550000;;, - 10;3;-0.000000,-0.000000,0.550000;;, - 16;3;-0.000000,-0.000000,0.550000;;, - 18;3;-0.000000,-0.000000,0.550000;;, - 20;3;-0.000000,-0.000000,0.550000;;, - 24;3;-0.000000,-0.000000,0.550000;;, - 28;3;-0.000000,-0.000000,0.550000;;, - 32;3;-0.000000,-0.000000,0.550000;;; - } - } - - Animation Animation35 { - { Bone_neck } - AnimationKey { - 0; - 8; - 0;4;1.000000,0.000732,-0.000000,-0.000000;;, - 4;4;1.000000,0.000732,-0.000000,-0.000000;;, - 10;4;1.000000,0.000732,-0.000000,-0.000000;;, - 16;4;1.000000,0.000732,-0.000000,-0.000000;;, - 20;4;1.000000,0.000732,-0.000000,-0.000000;;, - 24;4;1.000000,0.000732,-0.000000,-0.000000;;, - 28;4;1.000000,0.000732,-0.000000,-0.000000;;, - 32;4;1.000000,0.000732,-0.000000,-0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,3.000000;;, - 4;3;0.000000,0.000000,3.000000;;, - 10;3;0.000000,0.000000,3.000000;;, - 16;3;0.000000,0.000000,3.000000;;, - 20;3;0.000000,0.000000,3.000000;;, - 24;3;0.000000,0.000000,3.000000;;, - 28;3;0.000000,0.000000,3.000000;;, - 32;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation36 { - { Bone_Head } - AnimationKey { - 0; - 8; - 0;4;0.766044,-0.000000,0.642788,-0.000000;;, - 4;4;0.771785,-0.002578,0.635875,-0.002124;;, - 10;4;0.774533,-0.002381,0.632526,-0.001945;;, - 16;4;0.776378,-0.001611,0.630265,-0.001307;;, - 20;4;0.777289,-0.001164,0.629142,-0.000942;;, - 24;4;0.777520,-0.000717,0.628857,-0.000580;;, - 28;4;0.776441,-0.000289,0.630190,-0.000234;;, - 32;4;0.766044,0.000000,0.642788,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,1.407194;;, - 4;3;0.000000,0.000000,1.407194;;, - 10;3;0.000000,0.000000,1.407194;;, - 16;3;0.000000,0.000000,1.407194;;, - 20;3;0.000000,0.000000,1.407194;;, - 24;3;0.000000,0.000000,1.407194;;, - 28;3;0.000000,0.000000,1.407194;;, - 32;3;0.000000,0.000000,1.407194;;; - } - } - - Animation Animation37 { - { R_Wpn2 } - AnimationKey { - 0; - 2; - 0;4;1.000000,-0.000006,-0.000000,0.000000;;, - 32;4;1.000000,-0.000018,-0.000000,0.000000;;; - } - AnimationKey { - 1; - 2; - 0;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 2; - 0;3;0.100000,-0.265000,0.600000;;, - 32;3;0.100000,-0.265000,0.600000;;; - } - } - - Animation Animation38 { - { L_Wpn } - AnimationKey { - 0; - 8; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 4;4;1.000000,0.000000,0.000000,0.000000;;, - 10;4;1.000000,0.000000,0.000000,0.000000;;, - 16;4;1.000000,0.000000,0.000000,0.000000;;, - 20;4;1.000000,0.000000,0.000000,0.000000;;, - 24;4;1.000000,0.000000,0.000000,0.000000;;, - 28;4;1.000000,0.000000,0.000000,0.000000;;, - 32;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 8; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 20;3;1.000000,1.000000,1.000000;;, - 24;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;, - 32;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 8; - 0;3;0.000000,0.000000,0.800001;;, - 4;3;0.000000,0.000000,0.800001;;, - 10;3;0.000000,0.000000,0.800001;;, - 16;3;0.000000,0.000000,0.800001;;, - 20;3;0.000000,0.000000,0.800001;;, - 24;3;0.000000,0.000000,0.800001;;, - 28;3;0.000000,0.000000,0.800001;;, - 32;3;0.000000,0.000000,0.800001;;; - } - } - - Animation Animation39 { - { BarniaBaseR } - AnimationKey { - 0; - 5; - 0;4;-0.500000,0.500000,0.500000,0.500000;;, - 4;4;-0.500000,0.500000,0.500000,0.500000;;, - 10;4;-0.501176,0.498821,0.498821,0.501176;;, - 16;4;-0.500000,0.500000,0.500000,0.500000;;, - 28;4;-0.487992,0.511726,0.511726,0.487992;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.033058,1.000000;;, - 4;3;1.000000,1.033058,1.000000;;, - 10;3;1.000000,1.033058,1.000000;;, - 16;3;1.000000,1.033058,1.000000;;, - 28;3;1.000000,1.033058,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;0.000000,0.000000,0.000000;;, - 4;3;0.000000,0.000000,0.000000;;, - 10;3;0.000000,0.000000,0.000000;;, - 16;3;0.000000,0.000000,0.000000;;, - 28;3;0.000000,0.000000,0.000000;;; - } - } - - Animation Animation40 { - { BarniaBaseL } - AnimationKey { - 0; - 5; - 0;4;-0.500000,0.500000,0.500000,0.500000;;, - 4;4;-0.500000,0.500000,0.500000,0.500000;;, - 10;4;-0.501903,0.498090,0.498090,0.501903;;, - 16;4;-0.500000,0.500000,0.500000,0.500000;;, - 28;4;-0.480420,0.518842,0.518842,0.480420;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.033058,1.000000;;, - 4;3;1.000000,1.033058,1.000000;;, - 10;3;1.000000,1.033058,1.000000;;, - 16;3;1.000000,1.033058,1.000000;;, - 28;3;1.000000,1.033058,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;0.000000,0.000000,0.000000;;, - 4;3;0.000000,0.000000,0.000000;;, - 10;3;0.000000,0.000000,0.000000;;, - 16;3;0.000000,0.000000,0.000000;;, - 28;3;0.000000,0.000000,0.000000;;; - } - } - - Animation Animation41 { - { BarniaBaseL_2 } - AnimationKey { - 0; - 5; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 4;4;1.000000,0.000000,0.000000,0.000000;;, - 10;4;1.000000,0.000000,0.000000,0.000000;;, - 16;4;1.000000,0.000000,0.000000,0.000000;;, - 28;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;0.000000,0.000000,0.500000;;, - 4;3;0.000000,0.000000,0.500000;;, - 10;3;0.000000,0.000000,0.500000;;, - 16;3;0.000000,0.000000,0.500000;;, - 28;3;0.000000,0.000000,0.500000;;; - } - } - - Animation Animation42 { - { BarniaBaseR_2 } - AnimationKey { - 0; - 5; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 4;4;1.000000,0.000000,0.000000,0.000000;;, - 10;4;1.000000,0.000000,0.000000,0.000000;;, - 16;4;1.000000,0.000000,0.000000,0.000000;;, - 28;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;0.000000,0.000000,0.500000;;, - 4;3;0.000000,0.000000,0.500000;;, - 10;3;0.000000,0.000000,0.500000;;, - 16;3;0.000000,0.000000,0.500000;;, - 28;3;0.000000,0.000000,0.500000;;; - } - } - - Animation Animation43 { - { SW2_R_mp } - AnimationKey { - 0; - 5; - 0;4;0.930737,0.000000,-0.365689,0.000000;;, - 4;4;0.930737,0.000000,-0.365689,0.000000;;, - 10;4;0.930755,0.000000,-0.365642,0.000000;;, - 16;4;0.930737,0.000000,-0.365689,0.000000;;, - 28;4;0.930545,0.000000,-0.366178,0.000000;;; - } - AnimationKey { - 1; - 5; - 0;3;1.000000,1.000000,1.000000;;, - 4;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 16;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 5; - 0;3;1.300000,-1.000000,3.000000;;, - 4;3;1.300000,-1.000000,3.000000;;, - 10;3;1.300000,-1.000000,3.000000;;, - 16;3;1.300000,-1.000000,3.000000;;, - 28;3;1.300000,-1.000000,3.000000;;; - } - } - - Animation Animation44 { - { SW2_R_mp_2 } - AnimationKey { - 0; - 3; - 0;4;0.580978,-0.403069,-0.403070,-0.580978;;, - 10;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 28;4;0.579228,-0.405580,-0.405580,-0.579228;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,1.000000;;, - 10;3;0.000000,0.000000,1.000000;;, - 28;3;0.000000,0.000000,1.000000;;; - } - } - - Animation Animation45 { - { SW2_L_mp } - AnimationKey { - 0; - 3; - 0;4;0.930737,0.000000,-0.365689,0.000000;;, - 10;4;0.930585,0.000000,-0.366076,0.000000;;, - 28;4;0.930183,0.000000,-0.367096,0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;1.300000,1.000000,3.000000;;, - 10;3;1.300000,1.000000,3.000000;;, - 28;3;1.300000,1.000000,3.000000;;; - } - } - - Animation Animation46 { - { SW2_L_mp_2 } - AnimationKey { - 0; - 3; - 0;4;0.580978,-0.403069,-0.403070,-0.580978;;, - 10;4;0.579228,-0.405580,-0.405580,-0.579228;;, - 28;4;0.579228,-0.405580,-0.405580,-0.579228;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,1.000000;;, - 10;3;0.000000,0.000000,1.000000;;, - 28;3;0.000000,0.000000,1.000000;;; - } - } - - Animation Animation47 { - { L_Mune_A2 } - AnimationKey { - 0; - 3; - 0;4;1.000000,0.000000,0.000000,0.000000;;, - 10;4;1.000000,0.000000,0.000000,0.000000;;, - 28;4;1.000000,0.000000,0.000000,0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,1.051190;;, - 10;3;0.000000,0.000000,1.051190;;, - 28;3;0.000000,0.000000,1.051190;;; - } - } - - Animation Animation48 { - { R_Mune2 } - AnimationKey { - 0; - 3; - 0;4;0.999999,0.000000,-0.001437,0.000000;;, - 10;4;0.999999,0.000000,-0.001434,0.000000;;, - 28;4;0.999999,0.000000,-0.001349,0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,1.051190;;, - 10;3;0.000000,0.000000,1.051190;;, - 28;3;0.000000,0.000000,1.051190;;; - } - } - - Animation Animation49 { - { M_barnia1_1 } - AnimationKey { - 0; - 3; - 0;4;-0.686130,0.000000,0.727479,0.000000;;, - 10;4;-0.686130,0.000000,0.727479,0.000000;;, - 28;4;-0.686130,0.000000,0.727479,0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,3.000000;;, - 10;3;0.000000,0.000000,3.000000;;, - 28;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation50 { - { M_barnia1_2 } - AnimationKey { - 0; - 3; - 0;4;0.707107,0.000000,0.707107,0.000000;;, - 10;4;0.707107,0.000000,0.707107,0.000000;;, - 28;4;0.707107,0.000000,0.707107,0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,2.548788;;, - 10;3;0.000000,0.000000,2.548788;;, - 28;3;0.000000,0.000000,2.548788;;; - } - } - - Animation Animation51 { - { M_barnia2_1 } - AnimationKey { - 0; - 3; - 0;4;-0.547896,-0.000000,0.836547,0.000000;;, - 10;4;-0.547896,-0.000000,0.836547,0.000000;;, - 28;4;-0.547896,-0.000000,0.836547,0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,3.000000;;, - 10;3;0.000000,0.000000,3.000000;;, - 28;3;0.000000,0.000000,3.000000;;; - } - } - - Animation Animation52 { - { M_barnia2_2 } - AnimationKey { - 0; - 3; - 0;4;0.558470,-0.000000,0.829525,-0.000000;;, - 10;4;0.558470,-0.000000,0.829525,-0.000000;;, - 28;4;0.558470,-0.000000,0.829525,-0.000000;;; - } - AnimationKey { - 1; - 3; - 0;3;1.000000,1.000000,1.000000;;, - 10;3;1.000000,1.000000,1.000000;;, - 28;3;1.000000,1.000000,1.000000;;; - } - AnimationKey { - 2; - 3; - 0;3;0.000000,0.000000,2.261806;;, - 10;3;0.000000,0.000000,2.261806;;, - 28;3;0.000000,0.000000,2.261806;;; - } - } -} diff --git a/examples/physics_ammo_instancing.html b/examples/physics_ammo_instancing.html index b57f2056c45e41..2446bd25a6c808 100644 --- a/examples/physics_ammo_instancing.html +++ b/examples/physics_ammo_instancing.html @@ -72,6 +72,7 @@ const geometryBox = new THREE.BoxGeometry( 0.1, 0.1, 0.1 ); boxes = new THREE.InstancedMesh( geometryBox, material, 100 ); + boxes.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame boxes.castShadow = true; boxes.receiveShadow = true; scene.add( boxes ); @@ -90,6 +91,7 @@ const geometrySphere = new THREE.IcosahedronGeometry( 0.075, 3 ); spheres = new THREE.InstancedMesh( geometrySphere, material, 100 ); + spheres.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame spheres.castShadow = true; spheres.receiveShadow = true; scene.add( spheres ); diff --git a/examples/screenshots/webgl_animation_keyframes.jpg b/examples/screenshots/webgl_animation_keyframes.jpg index 364c9c5c062e3c..54ce7f1851107e 100644 Binary files a/examples/screenshots/webgl_animation_keyframes.jpg and b/examples/screenshots/webgl_animation_keyframes.jpg differ diff --git a/examples/screenshots/webgl_gpgpu_birds.jpg b/examples/screenshots/webgl_gpgpu_birds.jpg index 4939c987b01627..e6763ff0613c49 100644 Binary files a/examples/screenshots/webgl_gpgpu_birds.jpg and b/examples/screenshots/webgl_gpgpu_birds.jpg differ diff --git a/examples/screenshots/webgl_loader_ifc.jpg b/examples/screenshots/webgl_loader_ifc.jpg index 313723a1fe9ec3..5e504eb7ecd343 100644 Binary files a/examples/screenshots/webgl_loader_ifc.jpg and b/examples/screenshots/webgl_loader_ifc.jpg differ diff --git a/examples/screenshots/webgl_loader_x.jpg b/examples/screenshots/webgl_loader_x.jpg deleted file mode 100644 index 9692cd9c4068b0..00000000000000 Binary files a/examples/screenshots/webgl_loader_x.jpg and /dev/null differ diff --git a/examples/screenshots/webgl_materials_standard_nodes.jpg b/examples/screenshots/webgl_materials_standard_nodes.jpg new file mode 100644 index 00000000000000..59f7768dd1e9ac Binary files /dev/null and b/examples/screenshots/webgl_materials_standard_nodes.jpg differ diff --git a/examples/screenshots/webgl_postprocessing_ssr.jpg b/examples/screenshots/webgl_postprocessing_ssr.jpg index 45830d330a4be9..879d7ee80648c1 100644 Binary files a/examples/screenshots/webgl_postprocessing_ssr.jpg and b/examples/screenshots/webgl_postprocessing_ssr.jpg differ diff --git a/examples/screenshots/webgl_shaders_ocean.jpg b/examples/screenshots/webgl_shaders_ocean.jpg index abddd6cce1a686..1d1661acf548ed 100644 Binary files a/examples/screenshots/webgl_shaders_ocean.jpg and b/examples/screenshots/webgl_shaders_ocean.jpg differ diff --git a/examples/screenshots/webgl_shaders_sky.jpg b/examples/screenshots/webgl_shaders_sky.jpg index d6686f245184e7..52ec2566ebd643 100644 Binary files a/examples/screenshots/webgl_shaders_sky.jpg and b/examples/screenshots/webgl_shaders_sky.jpg differ diff --git a/examples/screenshots/webgpu_lights_selective.jpg b/examples/screenshots/webgpu_lights_selective.jpg new file mode 100644 index 00000000000000..a6da7a64623125 Binary files /dev/null and b/examples/screenshots/webgpu_lights_selective.jpg differ diff --git a/examples/screenshots/webxr_vr_sandbox.jpg b/examples/screenshots/webxr_vr_sandbox.jpg index b756594722b0ee..9f731b29b52609 100644 Binary files a/examples/screenshots/webxr_vr_sandbox.jpg and b/examples/screenshots/webxr_vr_sandbox.jpg differ diff --git a/examples/webgl2_materials_texture2darray.html b/examples/webgl2_materials_texture2darray.html index 13686aabdbcf01..7f2ef829ac2031 100644 --- a/examples/webgl2_materials_texture2darray.html +++ b/examples/webgl2_materials_texture2darray.html @@ -56,7 +56,7 @@ import * as THREE from '../build/three.module.js'; import Stats from './jsm/libs/stats.module.js'; - import { unzipSync } from './jsm/libs/fflate.module.min.js'; + import { unzipSync } from './jsm/libs/fflate.module.js'; import { WEBGL } from './jsm/WebGL.js'; diff --git a/examples/webgl2_rendertarget_texture2darray.html b/examples/webgl2_rendertarget_texture2darray.html index d34b685a3edcca..a4117812451b17 100644 --- a/examples/webgl2_rendertarget_texture2darray.html +++ b/examples/webgl2_rendertarget_texture2darray.html @@ -100,7 +100,7 @@ import * as THREE from '../build/three.module.js'; import Stats from './jsm/libs/stats.module.js'; - import { unzipSync } from './jsm/libs/fflate.module.min.js'; + import { unzipSync } from './jsm/libs/fflate.module.js'; import { GUI } from './jsm/libs/dat.gui.module.js'; import { WEBGL } from './jsm/WebGL.js'; diff --git a/examples/webgl_animation_keyframes.html b/examples/webgl_animation_keyframes.html index d1a63b9e123dfe..9792e5300d78a2 100644 --- a/examples/webgl_animation_keyframes.html +++ b/examples/webgl_animation_keyframes.html @@ -34,6 +34,8 @@ import Stats from './jsm/libs/stats.module.js'; import { OrbitControls } from './jsm/controls/OrbitControls.js'; + import { RoomEnvironment } from './jsm/environments/RoomEnvironment.js'; + import { GLTFLoader } from './jsm/loaders/GLTFLoader.js'; import { DRACOLoader } from './jsm/loaders/DRACOLoader.js'; @@ -51,8 +53,11 @@ renderer.outputEncoding = THREE.sRGBEncoding; container.appendChild( renderer.domElement ); + const pmremGenerator = new THREE.PMREMGenerator( renderer ); + const scene = new THREE.Scene(); scene.background = new THREE.Color( 0xbfe3dd ); + scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture; const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 ); camera.position.set( 5, 2, 8 ); @@ -63,21 +68,6 @@ controls.enablePan = false; controls.enableDamping = true; - scene.add( new THREE.HemisphereLight( 0xffffff, 0x000000, 0.4 ) ); - - const dirLight = new THREE.DirectionalLight( 0xffffff, 1 ); - dirLight.position.set( 5, 2, 8 ); - scene.add( dirLight ); - - // envmap - const path = 'textures/cube/Park2/'; - const format = '.jpg'; - const envMap = new THREE.CubeTextureLoader().load( [ - path + 'posx' + format, path + 'negx' + format, - path + 'posy' + format, path + 'negy' + format, - path + 'posz' + format, path + 'negz' + format - ] ); - const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' ); @@ -88,12 +78,6 @@ const model = gltf.scene; model.position.set( 1, 1, 0 ); model.scale.set( 0.01, 0.01, 0.01 ); - model.traverse( function ( child ) { - - if ( child.isMesh ) child.material.envMap = envMap; - - } ); - scene.add( model ); mixer = new THREE.AnimationMixer( model ); diff --git a/examples/webgl_gpgpu_birds.html b/examples/webgl_gpgpu_birds.html index 42fd02727006f1..7ef2a1f5b34e80 100644 --- a/examples/webgl_gpgpu_birds.html +++ b/examples/webgl_gpgpu_birds.html @@ -312,93 +312,99 @@ const BIRDS = WIDTH * WIDTH; // Custom Geometry - using 3 triangles each. No UVs, no normals currently. - function BirdGeometry() { + class BirdGeometry extends THREE.BufferGeometry { - const triangles = BIRDS * 3; - const points = triangles * 3; + constructor() { - THREE.BufferGeometry.call( this ); + super(); - const vertices = new THREE.BufferAttribute( new Float32Array( points * 3 ), 3 ); - const birdColors = new THREE.BufferAttribute( new Float32Array( points * 3 ), 3 ); - const references = new THREE.BufferAttribute( new Float32Array( points * 2 ), 2 ); - const birdVertex = new THREE.BufferAttribute( new Float32Array( points ), 1 ); + const trianglesPerBird = 3; + const triangles = BIRDS * trianglesPerBird; + const points = triangles * 3; - this.setAttribute( 'position', vertices ); - this.setAttribute( 'birdColor', birdColors ); - this.setAttribute( 'reference', references ); - this.setAttribute( 'birdVertex', birdVertex ); + const vertices = new THREE.BufferAttribute( new Float32Array( points * 3 ), 3 ); + const birdColors = new THREE.BufferAttribute( new Float32Array( points * 3 ), 3 ); + const references = new THREE.BufferAttribute( new Float32Array( points * 2 ), 2 ); + const birdVertex = new THREE.BufferAttribute( new Float32Array( points ), 1 ); - // this.setAttribute( 'normal', new Float32Array( points * 3 ), 3 ); + this.setAttribute( 'position', vertices ); + this.setAttribute( 'birdColor', birdColors ); + this.setAttribute( 'reference', references ); + this.setAttribute( 'birdVertex', birdVertex ); + // this.setAttribute( 'normal', new Float32Array( points * 3 ), 3 ); - let v = 0; - function verts_push() { + let v = 0; - for ( let i = 0; i < arguments.length; i ++ ) { + function verts_push() { - vertices.array[ v ++ ] = arguments[ i ]; + for ( let i = 0; i < arguments.length; i ++ ) { + + vertices.array[ v ++ ] = arguments[ i ]; + + } } - } + const wingsSpan = 20; - const wingsSpan = 20; + for ( let f = 0; f < BIRDS; f ++ ) { - for ( let f = 0; f < BIRDS; f ++ ) { + // Body - // Body - verts_push( - 0, - 0, - 20, - 0, 4, - 20, - 0, 0, 30 - ); + verts_push( + 0, - 0, - 20, + 0, 4, - 20, + 0, 0, 30 + ); - // Left Wing - verts_push( - 0, 0, - 15, - - wingsSpan, 0, 0, - 0, 0, 15 - ); + // Wings - // Right Wing - verts_push( - 0, 0, 15, - wingsSpan, 0, 0, - 0, 0, - 15 - ); + verts_push( + 0, 0, - 15, + - wingsSpan, 0, 0, + 0, 0, 15 + ); - } + verts_push( + 0, 0, 15, + wingsSpan, 0, 0, + 0, 0, - 15 + ); - for ( let v = 0; v < triangles * 3; v ++ ) { + } - const i = ~ ~ ( v / 3 ); - const x = ( i % WIDTH ) / WIDTH; - const y = ~ ~ ( i / WIDTH ) / WIDTH; + for ( let v = 0; v < triangles * 3; v ++ ) { - const c = new THREE.Color( - 0x444444 + - ~ ~ ( v / 9 ) / BIRDS * 0x666666 - ); + const triangleIndex = ~ ~ ( v / 3 ); + const birdIndex = ~ ~ ( triangleIndex / trianglesPerBird ); + const x = ( birdIndex % WIDTH ) / WIDTH; + const y = ~ ~ ( birdIndex / WIDTH ) / WIDTH; - birdColors.array[ v * 3 + 0 ] = c.r; - birdColors.array[ v * 3 + 1 ] = c.g; - birdColors.array[ v * 3 + 2 ] = c.b; + const c = new THREE.Color( + 0x444444 + + ~ ~ ( v / 9 ) / BIRDS * 0x666666 + ); - references.array[ v * 2 ] = x; - references.array[ v * 2 + 1 ] = y; + birdColors.array[ v * 3 + 0 ] = c.r; + birdColors.array[ v * 3 + 1 ] = c.g; + birdColors.array[ v * 3 + 2 ] = c.b; - birdVertex.array[ v ] = v % 9; + references.array[ v * 2 ] = x; + references.array[ v * 2 + 1 ] = y; - } + birdVertex.array[ v ] = v % 9; - this.scale( 0.2, 0.2, 0.2 ); + } - } + this.scale( 0.2, 0.2, 0.2 ); + + } - BirdGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); + } + // let container, stats; let camera, scene, renderer; @@ -462,18 +468,18 @@ const valuesChanger = function () { - velocityUniforms[ "separationDistance" ].value = effectController.separation; - velocityUniforms[ "alignmentDistance" ].value = effectController.alignment; - velocityUniforms[ "cohesionDistance" ].value = effectController.cohesion; - velocityUniforms[ "freedomFactor" ].value = effectController.freedom; + velocityUniforms[ 'separationDistance' ].value = effectController.separation; + velocityUniforms[ 'alignmentDistance' ].value = effectController.alignment; + velocityUniforms[ 'cohesionDistance' ].value = effectController.cohesion; + velocityUniforms[ 'freedomFactor' ].value = effectController.freedom; }; valuesChanger(); - gui.add( effectController, "separation", 0.0, 100.0, 1.0 ).onChange( valuesChanger ); - gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger ); - gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger ); + gui.add( effectController, 'separation', 0.0, 100.0, 1.0 ).onChange( valuesChanger ); + gui.add( effectController, 'alignment', 0.0, 100, 0.001 ).onChange( valuesChanger ); + gui.add( effectController, 'cohesion', 0.0, 100, 0.025 ).onChange( valuesChanger ); gui.close(); initBirds(); @@ -495,8 +501,8 @@ fillPositionTexture( dtPosition ); fillVelocityTexture( dtVelocity ); - velocityVariable = gpuCompute.addVariable( "textureVelocity", document.getElementById( 'fragmentShaderVelocity' ).textContent, dtVelocity ); - positionVariable = gpuCompute.addVariable( "texturePosition", document.getElementById( 'fragmentShaderPosition' ).textContent, dtPosition ); + velocityVariable = gpuCompute.addVariable( 'textureVelocity', document.getElementById( 'fragmentShaderVelocity' ).textContent, dtVelocity ); + positionVariable = gpuCompute.addVariable( 'texturePosition', document.getElementById( 'fragmentShaderPosition' ).textContent, dtPosition ); gpuCompute.setVariableDependencies( velocityVariable, [ positionVariable, velocityVariable ] ); gpuCompute.setVariableDependencies( positionVariable, [ positionVariable, velocityVariable ] ); @@ -504,16 +510,16 @@ positionUniforms = positionVariable.material.uniforms; velocityUniforms = velocityVariable.material.uniforms; - positionUniforms[ "time" ] = { value: 0.0 }; - positionUniforms[ "delta" ] = { value: 0.0 }; - velocityUniforms[ "time" ] = { value: 1.0 }; - velocityUniforms[ "delta" ] = { value: 0.0 }; - velocityUniforms[ "testing" ] = { value: 1.0 }; - velocityUniforms[ "separationDistance" ] = { value: 1.0 }; - velocityUniforms[ "alignmentDistance" ] = { value: 1.0 }; - velocityUniforms[ "cohesionDistance" ] = { value: 1.0 }; - velocityUniforms[ "freedomFactor" ] = { value: 1.0 }; - velocityUniforms[ "predator" ] = { value: new THREE.Vector3() }; + positionUniforms[ 'time' ] = { value: 0.0 }; + positionUniforms[ 'delta' ] = { value: 0.0 }; + velocityUniforms[ 'time' ] = { value: 1.0 }; + velocityUniforms[ 'delta' ] = { value: 0.0 }; + velocityUniforms[ 'testing' ] = { value: 1.0 }; + velocityUniforms[ 'separationDistance' ] = { value: 1.0 }; + velocityUniforms[ 'alignmentDistance' ] = { value: 1.0 }; + velocityUniforms[ 'cohesionDistance' ] = { value: 1.0 }; + velocityUniforms[ 'freedomFactor' ] = { value: 1.0 }; + velocityUniforms[ 'predator' ] = { value: new THREE.Vector3() }; velocityVariable.material.defines.BOUNDS = BOUNDS.toFixed( 2 ); velocityVariable.wrapS = THREE.RepeatWrapping; @@ -543,11 +549,11 @@ // For Vertex and Fragment birdUniforms = { - "color": { value: new THREE.Color( 0xff2200 ) }, - "texturePosition": { value: null }, - "textureVelocity": { value: null }, - "time": { value: 1.0 }, - "delta": { value: 0.0 } + 'color': { value: new THREE.Color( 0xff2200 ) }, + 'texturePosition': { value: null }, + 'textureVelocity': { value: null }, + 'time': { value: 1.0 }, + 'delta': { value: 0.0 } }; // THREE.ShaderMaterial @@ -646,22 +652,22 @@ if ( delta > 1 ) delta = 1; // safety cap on large deltas last = now; - positionUniforms[ "time" ].value = now; - positionUniforms[ "delta" ].value = delta; - velocityUniforms[ "time" ].value = now; - velocityUniforms[ "delta" ].value = delta; - birdUniforms[ "time" ].value = now; - birdUniforms[ "delta" ].value = delta; + positionUniforms[ 'time' ].value = now; + positionUniforms[ 'delta' ].value = delta; + velocityUniforms[ 'time' ].value = now; + velocityUniforms[ 'delta' ].value = delta; + birdUniforms[ 'time' ].value = now; + birdUniforms[ 'delta' ].value = delta; - velocityUniforms[ "predator" ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 ); + velocityUniforms[ 'predator' ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 ); mouseX = 10000; mouseY = 10000; gpuCompute.compute(); - birdUniforms[ "texturePosition" ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture; - birdUniforms[ "textureVelocity" ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture; + birdUniforms[ 'texturePosition' ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture; + birdUniforms[ 'textureVelocity' ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture; renderer.render( scene, camera ); diff --git a/examples/webgl_helpers.html b/examples/webgl_helpers.html index cf5afd755d27ed..f7fb6680437df9 100644 --- a/examples/webgl_helpers.html +++ b/examples/webgl_helpers.html @@ -20,8 +20,6 @@ import { VertexNormalsHelper } from './jsm/helpers/VertexNormalsHelper.js'; import { VertexTangentsHelper } from './jsm/helpers/VertexTangentsHelper.js'; - import { BufferGeometryUtils } from './jsm/utils/BufferGeometryUtils.js'; - let scene, renderer; let camera, light; let vnh; @@ -65,7 +63,7 @@ const mesh = gltf.scene.children[ 0 ]; - BufferGeometryUtils.computeTangents( mesh.geometry ); // generates bad data due to degenerate UVs + mesh.geometry.computeTangents(); // generates bad data due to degenerate UVs const group = new THREE.Group(); group.scale.multiplyScalar( 50 ); diff --git a/examples/webgl_loader_3dm.html b/examples/webgl_loader_3dm.html index 3a7e8893de39b8..c069973e8c228b 100644 --- a/examples/webgl_loader_3dm.html +++ b/examples/webgl_loader_3dm.html @@ -8,21 +8,21 @@ @@ -41,9 +41,8 @@ import { GUI } from './jsm/libs/dat.gui.module.js'; - let container, controls; let camera, scene, renderer; - let gui; + let controls, gui; init(); animate(); @@ -51,23 +50,24 @@ function init() { THREE.Object3D.DefaultUp = new THREE.Vector3( 0, 0, 1 ); - container = document.createElement( 'div' ); - document.body.appendChild( container ); + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setPixelRatio( window.devicePixelRatio ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.outputEncoding = THREE.sRGBEncoding; + document.body.appendChild( renderer.domElement ); camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.set( 26, - 40, 5 ); scene = new THREE.Scene(); - const directionalLight = new THREE.DirectionalLight( 0xffffff ); + const directionalLight = new THREE.DirectionalLight( 0xffffff, 2 ); directionalLight.position.set( 0, 0, 2 ); - directionalLight.castShadow = true; - directionalLight.intensity = 2; scene.add( directionalLight ); const loader = new Rhino3dmLoader(); loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@0.15.0-beta/' ); - loader.load( 'models/3dm/Rhino_Logo.3dm', function ( object ) { scene.add( object ); @@ -78,15 +78,7 @@ } ); - const width = window.innerWidth; - const height = window.innerHeight; - - renderer = new THREE.WebGLRenderer( { antialias: true } ); - renderer.setPixelRatio( window.devicePixelRatio ); - renderer.setSize( width, height ); - container.appendChild( renderer.domElement ); - - controls = new OrbitControls( camera, container ); + controls = new OrbitControls( camera, renderer.domElement ); window.addEventListener( 'resize', resize ); @@ -116,6 +108,7 @@ function initGUI( layers ) { gui = new GUI( { width: 300 } ); + const layersControl = gui.addFolder( 'layers' ); layersControl.open(); diff --git a/examples/webgl_loader_ifc.html b/examples/webgl_loader_ifc.html index d1ac7e9d85984b..57db5fa0200800 100644 --- a/examples/webgl_loader_ifc.html +++ b/examples/webgl_loader_ifc.html @@ -11,7 +11,6 @@ -
three.js - @@ -26,61 +25,78 @@ import { IFCLoader } from './jsm/loaders/IFCLoader.js'; - //Scene - const scene = new THREE.Scene(); - scene.background = new THREE.Color( 0x8cc7de ); - - //Renderer - const container = document.querySelector( '#container' ); - const renderer = new THREE.WebGLRenderer( { antialias: true } ); - renderer.setSize( window.innerWidth, window.innerHeight ); - renderer.setPixelRatio( Math.min( window.devicePixelRatio, 2 ) ); - renderer.setAnimationLoop( animation ); - container.appendChild( renderer.domElement ); - - //Camera - const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 ); - camera.position.z = - 70; - camera.position.y = 25; - camera.position.x = 90; - camera.lookAt( 0, 0, 0 ); - const controls = new OrbitControls( camera, renderer.domElement ); - - //Initial cube - const geometry = new THREE.BoxGeometry(); - const material = new THREE.MeshPhongMaterial( { color: 0xffffff } ); - const cube = new THREE.Mesh( geometry, material ); - scene.add( cube ); - - //Lights - const directionalLight1 = new THREE.DirectionalLight( 0xffeeff, 0.8 ); - directionalLight1.position.set( 1, 1, 1 ); - scene.add( directionalLight1 ); - const directionalLight2 = new THREE.DirectionalLight( 0xffffff, 0.8 ); - directionalLight2.position.set( - 1, 0.5, - 1 ); - scene.add( directionalLight2 ); - const ambientLight = new THREE.AmbientLight( 0xffffee, 0.25 ); - scene.add( ambientLight ); - - //Window resize support - window.addEventListener( 'resize', () => { + let scene, camera, renderer; + + init(); + + function init() { + + //Scene + scene = new THREE.Scene(); + scene.background = new THREE.Color( 0x8cc7de ); + + //Camera + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 ); + camera.position.z = - 70; + camera.position.y = 25; + camera.position.x = 90; + + //Initial cube + const geometry = new THREE.BoxGeometry(); + const material = new THREE.MeshPhongMaterial( { color: 0xffffff } ); + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); + + //Lights + const directionalLight1 = new THREE.DirectionalLight( 0xffeeff, 0.8 ); + directionalLight1.position.set( 1, 1, 1 ); + scene.add( directionalLight1 ); + + const directionalLight2 = new THREE.DirectionalLight( 0xffffff, 0.8 ); + directionalLight2.position.set( - 1, 0.5, - 1 ); + scene.add( directionalLight2 ); + + const ambientLight = new THREE.AmbientLight( 0xffffee, 0.25 ); + scene.add( ambientLight ); + + //Setup IFC Loader + const ifcLoader = new IFCLoader(); + ifcLoader.setWasmPath( 'jsm/loaders/ifc/' ); + ifcLoader.load( 'models/ifc/rac_advanced_sample_project.ifc', function ( model ) { + + scene.add( model ); + render(); + + } ); + + //Renderer + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setPixelRatio( window.devicePixelRatio ); + document.body.appendChild( renderer.domElement ); + + //Controls + const controls = new OrbitControls( camera, renderer.domElement ); + controls.addEventListener( 'change', render ); + + window.addEventListener( 'resize', onWindowResize ); + + render(); + + } + + function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); - } ); + render(); - //Setup IFC Loader - const ifcLoader = new IFCLoader(); - - //Load IFC file - ifcLoader.load( 'models/ifc/rac_advanced_sample_project.ifc', ( geometry ) => scene.add( geometry ) ); + } - //Animation - function animation() { + function render() { - controls.update(); renderer.render( scene, camera ); } diff --git a/examples/webgl_loader_md2_control.html b/examples/webgl_loader_md2_control.html index eade4750675a54..0214a596b1d47b 100644 --- a/examples/webgl_loader_md2_control.html +++ b/examples/webgl_loader_md2_control.html @@ -145,7 +145,6 @@ cameraControls = new OrbitControls( camera, renderer.domElement ); cameraControls.target.set( 0, 50, 0 ); - cameraControls.enableKeys = false; cameraControls.update(); // CHARACTER diff --git a/examples/webgl_loader_x.html b/examples/webgl_loader_x.html deleted file mode 100644 index 08b2b2854fa9b8..00000000000000 --- a/examples/webgl_loader_x.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - three.js webgl - loaders - X-File loader - - - - - -
- three.js - X-File Loader
- see more info and samples

- -
- -
- - - - - - diff --git a/examples/webgl_materials_standard_nodes.html b/examples/webgl_materials_standard_nodes.html new file mode 100644 index 00000000000000..5a2e9e9de0302f --- /dev/null +++ b/examples/webgl_materials_standard_nodes.html @@ -0,0 +1,207 @@ + + + + three.js webgl - materials - standard (nodes) + + + + + + +
+ three.js - webgl physically based material
+ Cerberus(FFVII Gun) model by Andrew Maximov. +
+ + + + + + diff --git a/examples/webgl_postprocessing_3dlut.html b/examples/webgl_postprocessing_3dlut.html index 9fac22dd0c02ae..7da3e58d759582 100644 --- a/examples/webgl_postprocessing_3dlut.html +++ b/examples/webgl_postprocessing_3dlut.html @@ -34,7 +34,7 @@ enabled: true, lut: 'Bourbon 64.CUBE', intensity: 1, - use2dLut: false, + use2DLut: false, }; const lutMap = { @@ -137,7 +137,7 @@ if ( renderer.capabilities.isWebGL2 ) { - gui.add( params, 'use2dLut' ); + gui.add( params, 'use2DLut' ); } else { diff --git a/examples/webgl_postprocessing_ssr.html b/examples/webgl_postprocessing_ssr.html index 23dcb0e8386b83..fae182cc4bae17 100644 --- a/examples/webgl_postprocessing_ssr.html +++ b/examples/webgl_postprocessing_ssr.html @@ -130,7 +130,7 @@ geometry = new THREE.PlaneBufferGeometry( 1, 1 ); groundReflector = new ReflectorForSSRPass( geometry, { - clipBias: 0, + clipBias: 0.0003, textureWidth: window.innerWidth, textureHeight: window.innerHeight, color: 0x888888, @@ -197,6 +197,10 @@ } } ); + ssrPass.thickness = 0.018; + gui.add( ssrPass, 'thickness' ).min( 0 ).max( .1 ).step( .0001 ); + ssrPass.infiniteThick = false; + gui.add( ssrPass, 'infiniteThick' ); gui.add( params, 'autoRotate' ).onChange( () => { controls.enabled = ! params.autoRotate; @@ -254,11 +258,8 @@ groundReflector.opacity = ssrPass.opacity; } ); - ssrPass.surfDist = 0.0015; - folder.add( ssrPass, 'surfDist' ).min( 0 ).max( .005 ).step( .0001 ); - folder.add( ssrPass, 'infiniteThick' ); - folder.add( ssrPass, 'thickTolerance' ).min( 0 ).max( .05 ).step( .0001 ); folder.add( ssrPass, 'blur' ); + // folder.open() // gui.close() } diff --git a/examples/webgl_shaders_ocean.html b/examples/webgl_shaders_ocean.html index 6371ce8b27a413..deaa30a40953cc 100644 --- a/examples/webgl_shaders_ocean.html +++ b/examples/webgl_shaders_ocean.html @@ -94,20 +94,18 @@ skyUniforms[ 'mieDirectionalG' ].value = 0.8; const parameters = { - inclination: 0.49, - azimuth: 0.205 + elevation: 2, + azimuth: 180 }; const pmremGenerator = new THREE.PMREMGenerator( renderer ); function updateSun() { - const theta = Math.PI * ( parameters.inclination - 0.5 ); - const phi = 2 * Math.PI * ( parameters.azimuth - 0.5 ); + const phi = THREE.MathUtils.degToRad( 90 - parameters.elevation ); + const theta = THREE.MathUtils.degToRad( parameters.azimuth ); - sun.x = Math.cos( phi ); - sun.y = Math.sin( phi ) * Math.sin( theta ); - sun.z = Math.sin( phi ) * Math.cos( theta ); + sun.setFromSphericalCoords( 1, phi, theta ); sky.material.uniforms[ 'sunPosition' ].value.copy( sun ); water.material.uniforms[ 'sunDirection' ].value.copy( sun ).normalize(); @@ -145,8 +143,8 @@ const gui = new GUI(); const folderSky = gui.addFolder( 'Sky' ); - folderSky.add( parameters, 'inclination', 0, 0.5, 0.0001 ).onChange( updateSun ); - folderSky.add( parameters, 'azimuth', 0, 1, 0.0001 ).onChange( updateSun ); + folderSky.add( parameters, 'elevation', 0, 90, 0.1 ).onChange( updateSun ); + folderSky.add( parameters, 'azimuth', - 180, 180, 0.1 ).onChange( updateSun ); folderSky.open(); const waterUniforms = water.material.uniforms; diff --git a/examples/webgl_shaders_sky.html b/examples/webgl_shaders_sky.html index e7a2848fd36f4e..70ad5a311ef09d 100644 --- a/examples/webgl_shaders_sky.html +++ b/examples/webgl_shaders_sky.html @@ -42,27 +42,25 @@ rayleigh: 3, mieCoefficient: 0.005, mieDirectionalG: 0.7, - inclination: 0.49, // elevation / inclination - azimuth: 0.25, // Facing front, + elevation: 2, + azimuth: 180, exposure: renderer.toneMappingExposure }; function guiChanged() { const uniforms = sky.material.uniforms; - uniforms[ "turbidity" ].value = effectController.turbidity; - uniforms[ "rayleigh" ].value = effectController.rayleigh; - uniforms[ "mieCoefficient" ].value = effectController.mieCoefficient; - uniforms[ "mieDirectionalG" ].value = effectController.mieDirectionalG; + uniforms[ 'turbidity' ].value = effectController.turbidity; + uniforms[ 'rayleigh' ].value = effectController.rayleigh; + uniforms[ 'mieCoefficient' ].value = effectController.mieCoefficient; + uniforms[ 'mieDirectionalG' ].value = effectController.mieDirectionalG; - const theta = Math.PI * ( effectController.inclination - 0.5 ); - const phi = 2 * Math.PI * ( effectController.azimuth - 0.5 ); + const phi = THREE.MathUtils.degToRad( 90 - effectController.elevation ); + const theta = THREE.MathUtils.degToRad( effectController.azimuth ); - sun.x = Math.cos( phi ); - sun.y = Math.sin( phi ) * Math.sin( theta ); - sun.z = Math.sin( phi ) * Math.cos( theta ); + sun.setFromSphericalCoords( 1, phi, theta ); - uniforms[ "sunPosition" ].value.copy( sun ); + uniforms[ 'sunPosition' ].value.copy( sun ); renderer.toneMappingExposure = effectController.exposure; renderer.render( scene, camera ); @@ -71,13 +69,13 @@ const gui = new GUI(); - gui.add( effectController, "turbidity", 0.0, 20.0, 0.1 ).onChange( guiChanged ); - gui.add( effectController, "rayleigh", 0.0, 4, 0.001 ).onChange( guiChanged ); - gui.add( effectController, "mieCoefficient", 0.0, 0.1, 0.001 ).onChange( guiChanged ); - gui.add( effectController, "mieDirectionalG", 0.0, 1, 0.001 ).onChange( guiChanged ); - gui.add( effectController, "inclination", 0, 1, 0.0001 ).onChange( guiChanged ); - gui.add( effectController, "azimuth", 0, 1, 0.0001 ).onChange( guiChanged ); - gui.add( effectController, "exposure", 0, 1, 0.0001 ).onChange( guiChanged ); + gui.add( effectController, 'turbidity', 0.0, 20.0, 0.1 ).onChange( guiChanged ); + gui.add( effectController, 'rayleigh', 0.0, 4, 0.001 ).onChange( guiChanged ); + gui.add( effectController, 'mieCoefficient', 0.0, 0.1, 0.001 ).onChange( guiChanged ); + gui.add( effectController, 'mieDirectionalG', 0.0, 1, 0.001 ).onChange( guiChanged ); + gui.add( effectController, 'elevation', 0, 90, 0.1 ).onChange( guiChanged ); + gui.add( effectController, 'azimuth', - 180, 180, 0.1 ).onChange( guiChanged ); + gui.add( effectController, 'exposure', 0, 1, 0.0001 ).onChange( guiChanged ); guiChanged(); diff --git a/examples/webgpu_instance_uniform.html b/examples/webgpu_instance_uniform.html index 82b02b8671922e..aad7c836db5112 100644 --- a/examples/webgpu_instance_uniform.html +++ b/examples/webgpu_instance_uniform.html @@ -8,7 +8,7 @@
- three.js - WebGPU Instance Uniform
(Chrome Canary with flag: --enable-unsafe-webgpu) + three.js - WebGPU - Instance Uniform
(Chrome Canary with flag: --enable-unsafe-webgpu)
+ + + diff --git a/examples/webxr_vr_handinput.html b/examples/webxr_vr_handinput.html index 13597b7fa9e9bb..e136500b976781 100644 --- a/examples/webxr_vr_handinput.html +++ b/examples/webxr_vr_handinput.html @@ -9,8 +9,7 @@
- three.js vr - handinput
- (Oculus Browser with #webxr-hands flag enabled) + three.js vr - handinput
+