UNPKG

threejs-math

Version:

Stand-alone version of three.js math with TypeScript support

2,132 lines (1,770 loc) 146 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const REVISION = '144dev'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; const CullFaceNone = 0; const CullFaceBack = 1; const CullFaceFront = 2; const CullFaceFrontBack = 3; const BasicShadowMap = 0; const PCFShadowMap = 1; const PCFSoftShadowMap = 2; const VSMShadowMap = 3; const FrontSide = 0; const BackSide = 1; const DoubleSide = 2; const NoBlending = 0; const NormalBlending = 1; const AdditiveBlending = 2; const SubtractiveBlending = 3; const MultiplyBlending = 4; const CustomBlending = 5; const AddEquation = 100; const SubtractEquation = 101; const ReverseSubtractEquation = 102; const MinEquation = 103; const MaxEquation = 104; const ZeroFactor = 200; const OneFactor = 201; const SrcColorFactor = 202; const OneMinusSrcColorFactor = 203; const SrcAlphaFactor = 204; const OneMinusSrcAlphaFactor = 205; const DstAlphaFactor = 206; const OneMinusDstAlphaFactor = 207; const DstColorFactor = 208; const OneMinusDstColorFactor = 209; const SrcAlphaSaturateFactor = 210; const NeverDepth = 0; const AlwaysDepth = 1; const LessDepth = 2; const LessEqualDepth = 3; const EqualDepth = 4; const GreaterEqualDepth = 5; const GreaterDepth = 6; const NotEqualDepth = 7; const MultiplyOperation = 0; const MixOperation = 1; const AddOperation = 2; const NoToneMapping = 0; const LinearToneMapping = 1; const ReinhardToneMapping = 2; const CineonToneMapping = 3; const ACESFilmicToneMapping = 4; const CustomToneMapping = 5; const UVMapping = 300; const CubeReflectionMapping = 301; const CubeRefractionMapping = 302; const EquirectangularReflectionMapping = 303; const EquirectangularRefractionMapping = 304; const CubeUVReflectionMapping = 306; const RepeatWrapping = 1000; const ClampToEdgeWrapping = 1001; const MirroredRepeatWrapping = 1002; const NearestFilter = 1003; const NearestMipmapNearestFilter = 1004; const NearestMipMapNearestFilter = 1004; const NearestMipmapLinearFilter = 1005; const NearestMipMapLinearFilter = 1005; const LinearFilter = 1006; const LinearMipmapNearestFilter = 1007; const LinearMipMapNearestFilter = 1007; const LinearMipmapLinearFilter = 1008; const LinearMipMapLinearFilter = 1008; const UnsignedByteType = 1009; const ByteType = 1010; const ShortType = 1011; const UnsignedShortType = 1012; const IntType = 1013; const UnsignedIntType = 1014; const FloatType = 1015; const HalfFloatType = 1016; const UnsignedShort4444Type = 1017; const UnsignedShort5551Type = 1018; const UnsignedInt248Type = 1020; const AlphaFormat = 1021; const RGBFormat = 1022; // @deprecated since r137 const RGBAFormat = 1023; const LuminanceFormat = 1024; const LuminanceAlphaFormat = 1025; const DepthFormat = 1026; const DepthStencilFormat = 1027; const RedFormat = 1028; const RedIntegerFormat = 1029; const RGFormat = 1030; const RGIntegerFormat = 1031; const RGBAIntegerFormat = 1033; const RGB_S3TC_DXT1_Format = 33776; const RGBA_S3TC_DXT1_Format = 33777; const RGBA_S3TC_DXT3_Format = 33778; const RGBA_S3TC_DXT5_Format = 33779; const RGB_PVRTC_4BPPV1_Format = 35840; const RGB_PVRTC_2BPPV1_Format = 35841; const RGBA_PVRTC_4BPPV1_Format = 35842; const RGBA_PVRTC_2BPPV1_Format = 35843; const RGB_ETC1_Format = 36196; const RGB_ETC2_Format = 37492; const RGBA_ETC2_EAC_Format = 37496; const RGBA_ASTC_4x4_Format = 37808; const RGBA_ASTC_5x4_Format = 37809; const RGBA_ASTC_5x5_Format = 37810; const RGBA_ASTC_6x5_Format = 37811; const RGBA_ASTC_6x6_Format = 37812; const RGBA_ASTC_8x5_Format = 37813; const RGBA_ASTC_8x6_Format = 37814; const RGBA_ASTC_8x8_Format = 37815; const RGBA_ASTC_10x5_Format = 37816; const RGBA_ASTC_10x6_Format = 37817; const RGBA_ASTC_10x8_Format = 37818; const RGBA_ASTC_10x10_Format = 37819; const RGBA_ASTC_12x10_Format = 37820; const RGBA_ASTC_12x12_Format = 37821; const RGBA_BPTC_Format = 36492; const LoopOnce = 2200; const LoopRepeat = 2201; const LoopPingPong = 2202; const InterpolateDiscrete = 2300; const InterpolateLinear = 2301; const InterpolateSmooth = 2302; const ZeroCurvatureEnding = 2400; const ZeroSlopeEnding = 2401; const WrapAroundEnding = 2402; const NormalAnimationBlendMode = 2500; const AdditiveAnimationBlendMode = 2501; const TrianglesDrawMode = 0; const TriangleStripDrawMode = 1; const TriangleFanDrawMode = 2; const LinearEncoding = 3000; const sRGBEncoding = 3001; const BasicDepthPacking = 3200; const RGBADepthPacking = 3201; const TangentSpaceNormalMap = 0; const ObjectSpaceNormalMap = 1; // Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. const NoColorSpace = ''; const SRGBColorSpace = 'srgb'; const LinearSRGBColorSpace = 'srgb-linear'; const ZeroStencilOp = 0; const KeepStencilOp = 7680; const ReplaceStencilOp = 7681; const IncrementStencilOp = 7682; const DecrementStencilOp = 7683; const IncrementWrapStencilOp = 34055; const DecrementWrapStencilOp = 34056; const InvertStencilOp = 5386; const NeverStencilFunc = 512; const LessStencilFunc = 513; const EqualStencilFunc = 514; const LessEqualStencilFunc = 515; const GreaterStencilFunc = 516; const NotEqualStencilFunc = 517; const GreaterEqualStencilFunc = 518; const AlwaysStencilFunc = 519; const StaticDrawUsage = 35044; const DynamicDrawUsage = 35048; const StreamDrawUsage = 35040; const StaticReadUsage = 35045; const DynamicReadUsage = 35049; const StreamReadUsage = 35041; const StaticCopyUsage = 35046; const DynamicCopyUsage = 35050; const StreamCopyUsage = 35042; const GLSL1 = '100'; const GLSL3 = '300 es'; const _SRGBAFormat = 1035; // fallback for WebGL 1 class Vector2 { constructor(x = 0, y = 0) { Vector2.prototype.isVector2 = true; this.x = x; this.y = y; } get width() { return this.x; } set width(value) { this.x = value; } get height() { return this.y; } set height(value) { this.y = value; } set(x, y) { this.x = x; this.y = y; return this; } setScalar(scalar) { this.x = scalar; this.y = scalar; return this; } setX(x) { this.x = x; return this; } setY(y) { this.y = y; return this; } setComponent(index, value) { switch (index) { case 0: this.x = value; break; case 1: this.y = value; break; default: throw new Error('index is out of range: ' + index); } return this; } getComponent(index) { switch (index) { case 0: return this.x; case 1: return this.y; default: throw new Error('index is out of range: ' + index); } } clone() { return new this.constructor(this.x, this.y); } copy(v) { this.x = v.x; this.y = v.y; return this; } add(v) { this.x += v.x; this.y += v.y; return this; } addScalar(s) { this.x += s; this.y += s; return this; } addVectors(a, b) { this.x = a.x + b.x; this.y = a.y + b.y; return this; } addScaledVector(v, s) { this.x += v.x * s; this.y += v.y * s; return this; } sub(v) { this.x -= v.x; this.y -= v.y; return this; } subScalar(s) { this.x -= s; this.y -= s; return this; } subVectors(a, b) { this.x = a.x - b.x; this.y = a.y - b.y; return this; } multiply(v) { this.x *= v.x; this.y *= v.y; return this; } multiplyScalar(scalar) { this.x *= scalar; this.y *= scalar; return this; } divide(v) { this.x /= v.x; this.y /= v.y; return this; } divideScalar(scalar) { return this.multiplyScalar(1 / scalar); } applyMatrix3(m) { const x = this.x, y = this.y; const e = m.elements; this.x = e[0] * x + e[3] * y + e[6]; this.y = e[1] * x + e[4] * y + e[7]; return this; } min(v) { this.x = Math.min(this.x, v.x); this.y = Math.min(this.y, v.y); return this; } max(v) { this.x = Math.max(this.x, v.x); this.y = Math.max(this.y, v.y); return this; } clamp(min, max) { // assumes min < max, componentwise this.x = Math.max(min.x, Math.min(max.x, this.x)); this.y = Math.max(min.y, Math.min(max.y, this.y)); return this; } clampScalar(minVal, maxVal) { this.x = Math.max(minVal, Math.min(maxVal, this.x)); this.y = Math.max(minVal, Math.min(maxVal, this.y)); return this; } clampLength(min, max) { const length = this.length(); return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length))); } floor() { this.x = Math.floor(this.x); this.y = Math.floor(this.y); return this; } ceil() { this.x = Math.ceil(this.x); this.y = Math.ceil(this.y); return this; } round() { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; } roundToZero() { this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); return this; } negate() { this.x = -this.x; this.y = -this.y; return this; } dot(v) { return this.x * v.x + this.y * v.y; } cross(v) { return this.x * v.y - this.y * v.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() { // computes the angle in radians with respect to the positive x-axis const angle = Math.atan2(-this.y, -this.x) + Math.PI; return angle; } distanceTo(v) { return Math.sqrt(this.distanceToSquared(v)); } distanceToSquared(v) { const dx = this.x - v.x, dy = this.y - v.y; return dx * dx + dy * dy; } manhattanDistanceTo(v) { return Math.abs(this.x - v.x) + Math.abs(this.y - v.y); } setLength(length) { return this.normalize().multiplyScalar(length); } lerp(v, alpha) { this.x += (v.x - this.x) * alpha; this.y += (v.y - this.y) * alpha; return this; } lerpVectors(v1, v2, alpha) { this.x = v1.x + (v2.x - v1.x) * alpha; this.y = v1.y + (v2.y - v1.y) * alpha; return this; } equals(v) { return v.x === this.x && v.y === this.y; } fromArray(array, offset = 0) { this.x = array[offset]; this.y = array[offset + 1]; return this; } toArray(array = [], offset = 0) { array[offset] = this.x; array[offset + 1] = this.y; return array; } // fromBufferAttribute( attribute, index ) { // this.x = attribute.getX( index ); // this.y = attribute.getY( index ); // return this; // } rotateAround(center, angle) { const c = Math.cos(angle), s = Math.sin(angle); const x = this.x - center.x; const y = this.y - center.y; this.x = x * c - y * s + center.x; this.y = x * s + y * c + center.y; return this; } random() { this.x = Math.random(); this.y = Math.random(); return this; } *[Symbol.iterator]() { yield this.x; yield this.y; } } const _lut = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff']; let _seed = 1234567; 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 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]; // .toLowerCase() here flattens concatenated strings to save heap memory space. return uuid.toLowerCase(); } function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } // compute euclidean modulo of m % n // https://en.wikipedia.org/wiki/Modulo_operation function euclideanModulo(n, m) { return (n % m + m) % m; } // Linear mapping from range <a1, a2> to range <b1, b2> 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/ 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 <low, high> interval function randInt(low, high) { return low + Math.floor(Math.random() * (high - low + 1)); } // Random float from <low, high> 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; // Mulberry32 generator let t = _seed += 0x6D2B79F5; t = Math.imul(t ^ t >>> 15, t | 1); t ^= t + Math.imul(t ^ t >>> 7, t | 61); return ((t ^ t >>> 14) >>> 0) / 4294967296; } 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); } } function denormalize(value, array) { switch (array.constructor) { case Float32Array: return value; case Uint16Array: return value / 65535.0; case Uint8Array: return value / 255.0; case Int16Array: return Math.max(value / 32767.0, -1.0); case Int8Array: return Math.max(value / 127.0, -1.0); default: throw new Error('Invalid component type.'); } } function normalize(value, array) { switch (array.constructor) { case Float32Array: return value; case Uint16Array: return Math.round(value * 65535.0); case Uint8Array: return Math.round(value * 255.0); case Int16Array: return Math.round(value * 32767.0); case Int8Array: return Math.round(value * 127.0); default: throw new Error('Invalid component type.'); } } 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, normalize: normalize, denormalize: denormalize }); class Quaternion { constructor(x = 0, y = 0, z = 0, w = 1) { this.isQuaternion = true; this._x = x; this._y = y; this._z = z; this._w = w; } static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) { // fuzz-free, array-based Quaternion SLERP operation let x0 = src0[srcOffset0 + 0], y0 = src0[srcOffset0 + 1], z0 = src0[srcOffset0 + 2], w0 = src0[srcOffset0 + 3]; const x1 = src1[srcOffset1 + 0], y1 = src1[srcOffset1 + 1], z1 = src1[srcOffset1 + 2], w1 = src1[srcOffset1 + 3]; if (t === 0) { dst[dstOffset + 0] = x0; dst[dstOffset + 1] = y0; dst[dstOffset + 2] = z0; dst[dstOffset + 3] = w0; return; } if (t === 1) { dst[dstOffset + 0] = x1; dst[dstOffset + 1] = y1; dst[dstOffset + 2] = z1; dst[dstOffset + 3] = w1; return; } if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) { let s = 1 - t; const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, dir = cos >= 0 ? 1 : -1, sqrSin = 1 - cos * cos; // Skip the Slerp for tiny steps to avoid numeric problems: if (sqrSin > Number.EPSILON) { const sin = Math.sqrt(sqrSin), len = Math.atan2(sin, cos * dir); s = Math.sin(s * len) / sin; t = Math.sin(t * len) / sin; } const tDir = t * dir; x0 = x0 * s + x1 * tDir; y0 = y0 * s + y1 * tDir; z0 = z0 * s + z1 * tDir; w0 = w0 * s + w1 * tDir; // Normalize in case we just did a lerp: if (s === 1 - t) { const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0); x0 *= f; y0 *= f; z0 *= f; w0 *= f; } } dst[dstOffset] = x0; dst[dstOffset + 1] = y0; dst[dstOffset + 2] = z0; dst[dstOffset + 3] = w0; } static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) { const x0 = src0[srcOffset0]; const y0 = src0[srcOffset0 + 1]; const z0 = src0[srcOffset0 + 2]; const w0 = src0[srcOffset0 + 3]; const x1 = src1[srcOffset1]; const y1 = src1[srcOffset1 + 1]; const z1 = src1[srcOffset1 + 2]; const w1 = src1[srcOffset1 + 3]; dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; return dst; } get x() { return this._x; } set x(value) { this._x = value; this._onChangeCallback(); } get y() { return this._y; } set y(value) { this._y = value; this._onChangeCallback(); } get z() { return this._z; } set z(value) { this._z = value; this._onChangeCallback(); } get w() { return this._w; } set w(value) { this._w = value; this._onChangeCallback(); } set(x, y, z, w) { this._x = x; this._y = y; this._z = z; this._w = w; this._onChangeCallback(); return this; } clone() { return new this.constructor(this._x, this._y, this._z, this._w); } copy(quaternion) { this._x = quaternion.x; this._y = quaternion.y; this._z = quaternion.z; this._w = quaternion.w; this._onChangeCallback(); return this; } setFromEuler(euler, update) { const x = euler._x, y = euler._y, z = euler._z, order = euler._order; // http://www.mathworks.com/matlabcentral/fileexchange/ // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ // content/SpinCalc.m const cos = Math.cos; const sin = Math.sin; const c1 = cos(x / 2); const c2 = cos(y / 2); const c3 = cos(z / 2); const s1 = sin(x / 2); const s2 = sin(y / 2); const s3 = sin(z / 2); switch (order) { case 'XYZ': this._x = s1 * c2 * c3 + c1 * s2 * s3; this._y = c1 * s2 * c3 - s1 * c2 * s3; this._z = c1 * c2 * s3 + s1 * s2 * c3; this._w = c1 * c2 * c3 - s1 * s2 * s3; break; case 'YXZ': this._x = s1 * c2 * c3 + c1 * s2 * s3; this._y = c1 * s2 * c3 - s1 * c2 * s3; this._z = c1 * c2 * s3 - s1 * s2 * c3; this._w = c1 * c2 * c3 + s1 * s2 * s3; break; case 'ZXY': this._x = s1 * c2 * c3 - c1 * s2 * s3; this._y = c1 * s2 * c3 + s1 * c2 * s3; this._z = c1 * c2 * s3 + s1 * s2 * c3; this._w = c1 * c2 * c3 - s1 * s2 * s3; break; case 'ZYX': this._x = s1 * c2 * c3 - c1 * s2 * s3; this._y = c1 * s2 * c3 + s1 * c2 * s3; this._z = c1 * c2 * s3 - s1 * s2 * c3; this._w = c1 * c2 * c3 + s1 * s2 * s3; break; case 'YZX': this._x = s1 * c2 * c3 + c1 * s2 * s3; this._y = c1 * s2 * c3 + s1 * c2 * s3; this._z = c1 * c2 * s3 - s1 * s2 * c3; this._w = c1 * c2 * c3 - s1 * s2 * s3; break; case 'XZY': this._x = s1 * c2 * c3 - c1 * s2 * s3; this._y = c1 * s2 * c3 - s1 * c2 * s3; this._z = c1 * c2 * s3 + s1 * s2 * c3; this._w = c1 * c2 * c3 + s1 * s2 * s3; break; default: console.warn('THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order); } if (update !== false) this._onChangeCallback(); return this; } setFromAxisAngle(axis, angle) { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm // assumes axis is normalized const halfAngle = angle / 2, s = Math.sin(halfAngle); this._x = axis.x * s; this._y = axis.y * s; this._z = axis.z * s; this._w = Math.cos(halfAngle); this._onChangeCallback(); return this; } setFromRotationMatrix(m) { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) const te = m.elements, m11 = te[0], m12 = te[4], m13 = te[8], m21 = te[1], m22 = te[5], m23 = te[9], m31 = te[2], m32 = te[6], m33 = te[10], trace = m11 + m22 + m33; if (trace > 0) { const s = 0.5 / Math.sqrt(trace + 1.0); this._w = 0.25 / s; this._x = (m32 - m23) * s; this._y = (m13 - m31) * s; this._z = (m21 - m12) * s; } else if (m11 > m22 && m11 > m33) { const s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33); this._w = (m32 - m23) / s; this._x = 0.25 * s; this._y = (m12 + m21) / s; this._z = (m13 + m31) / s; } else if (m22 > m33) { const s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33); this._w = (m13 - m31) / s; this._x = (m12 + m21) / s; this._y = 0.25 * s; this._z = (m23 + m32) / s; } else { const s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22); this._w = (m21 - m12) / s; this._x = (m13 + m31) / s; this._y = (m23 + m32) / s; this._z = 0.25 * s; } this._onChangeCallback(); return this; } setFromUnitVectors(vFrom, vTo) { // assumes direction vectors vFrom and vTo are normalized let r = vFrom.dot(vTo) + 1; if (r < Number.EPSILON) { // vFrom and vTo point in opposite directions r = 0; if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { this._x = -vFrom.y; this._y = vFrom.x; this._z = 0; this._w = r; } else { this._x = 0; this._y = -vFrom.z; this._z = vFrom.y; this._w = r; } } else { // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; this._w = r; } return this.normalize(); } angleTo(q) { return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1))); } rotateTowards(q, step) { const angle = this.angleTo(q); if (angle === 0) return this; const t = Math.min(1, step / angle); this.slerp(q, t); return this; } identity() { return this.set(0, 0, 0, 1); } invert() { // quaternion is assumed to have unit length return this.conjugate(); } conjugate() { this._x *= -1; this._y *= -1; this._z *= -1; this._onChangeCallback(); return this; } dot(v) { return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._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 l = this.length(); if (l === 0) { this._x = 0; this._y = 0; this._z = 0; this._w = 1; } else { l = 1 / l; this._x = this._x * l; this._y = this._y * l; this._z = this._z * l; this._w = this._w * l; } this._onChangeCallback(); return this; } multiply(q) { return this.multiplyQuaternions(this, q); } premultiply(q) { return this.multiplyQuaternions(q, this); } multiplyQuaternions(a, b) { // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; this._onChangeCallback(); return this; } slerp(qb, t) { if (t === 0) return this; if (t === 1) return this.copy(qb); const x = this._x, y = this._y, z = this._z, w = this._w; // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; if (cosHalfTheta < 0) { this._w = -qb._w; this._x = -qb._x; this._y = -qb._y; this._z = -qb._z; cosHalfTheta = -cosHalfTheta; } else { this.copy(qb); } if (cosHalfTheta >= 1.0) { this._w = w; this._x = x; this._y = y; this._z = z; return this; } const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; if (sqrSinHalfTheta <= Number.EPSILON) { const s = 1 - t; this._w = s * w + t * this._w; this._x = s * x + t * this._x; this._y = s * y + t * this._y; this._z = s * z + t * this._z; this.normalize(); this._onChangeCallback(); return this; } const sinHalfTheta = Math.sqrt(sqrSinHalfTheta); const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta); const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, ratioB = Math.sin(t * halfTheta) / sinHalfTheta; this._w = w * ratioA + this._w * ratioB; this._x = x * ratioA + this._x * ratioB; this._y = y * ratioA + this._y * ratioB; this._z = z * ratioA + this._z * ratioB; this._onChangeCallback(); return this; } slerpQuaternions(qa, qb, t) { return this.copy(qa).slerp(qb, t); } random() { // Derived from http://planning.cs.uiuc.edu/node198.html // Note, this source uses w, x, y, z ordering, // so we swap the order below. const u1 = Math.random(); const sqrt1u1 = Math.sqrt(1 - u1); const sqrtu1 = Math.sqrt(u1); const u2 = 2 * Math.PI * Math.random(); const u3 = 2 * Math.PI * Math.random(); return this.set(sqrt1u1 * Math.cos(u2), sqrtu1 * Math.sin(u3), sqrtu1 * Math.cos(u3), sqrt1u1 * Math.sin(u2)); } equals(quaternion) { return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w; } fromArray(array, offset = 0) { this._x = array[offset]; this._y = array[offset + 1]; this._z = array[offset + 2]; this._w = array[offset + 3]; this._onChangeCallback(); return this; } toArray(array = [], offset = 0) { array[offset] = this._x; array[offset + 1] = this._y; array[offset + 2] = this._z; array[offset + 3] = this._w; return array; } // fromBufferAttribute( attribute, index ) { // this._x = attribute.getX( index ); // this._y = attribute.getY( index ); // this._z = attribute.getZ( index ); // this._w = attribute.getW( index ); // return this; // } _onChange(callback) { this._onChangeCallback = callback; return this; } _onChangeCallback() {} *[Symbol.iterator]() { yield this._x; yield this._y; yield this._z; yield this._w; } } class Vector3 { constructor(x = 0, y = 0, z = 0) { Vector3.prototype.isVector3 = true; this.x = x; this.y = y; this.z = z; } set(x, y, z) { if (z === undefined) z = this.z; // sprite.scale.set(x,y) this.x = x; this.y = y; this.z = z; return this; } setScalar(scalar) { this.x = scalar; this.y = scalar; this.z = scalar; return this; } setX(x) { this.x = x; return this; } setY(y) { this.y = y; return this; } setZ(z) { this.z = z; return this; } setComponent(index, value) { switch (index) { case 0: this.x = value; break; case 1: this.y = value; break; case 2: this.z = value; break; default: throw new Error('index is out of range: ' + index); } return this; } getComponent(index) { switch (index) { case 0: return this.x; case 1: return this.y; case 2: return this.z; default: throw new Error('index is out of range: ' + index); } } clone() { return new this.constructor(this.x, this.y, this.z); } copy(v) { this.x = v.x; this.y = v.y; this.z = v.z; return this; } add(v) { this.x += v.x; this.y += v.y; this.z += v.z; return this; } addScalar(s) { this.x += s; this.y += s; this.z += s; return this; } addVectors(a, b) { this.x = a.x + b.x; this.y = a.y + b.y; this.z = a.z + b.z; return this; } addScaledVector(v, s) { this.x += v.x * s; this.y += v.y * s; this.z += v.z * s; return this; } sub(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; return this; } subScalar(s) { this.x -= s; this.y -= s; this.z -= s; return this; } subVectors(a, b) { this.x = a.x - b.x; this.y = a.y - b.y; this.z = a.z - b.z; return this; } multiply(v) { this.x *= v.x; this.y *= v.y; this.z *= v.z; return this; } multiplyScalar(scalar) { this.x *= scalar; this.y *= scalar; this.z *= scalar; return this; } multiplyVectors(a, b) { this.x = a.x * b.x; this.y = a.y * b.y; this.z = a.z * b.z; return this; } applyEuler(euler) { return this.applyQuaternion(_quaternion$1.setFromEuler(euler)); } applyAxisAngle(axis, angle) { return this.applyQuaternion(_quaternion$1.setFromAxisAngle(axis, angle)); } applyMatrix3(m) { const x = this.x, y = this.y, z = this.z; const e = m.elements; this.x = e[0] * x + e[3] * y + e[6] * z; this.y = e[1] * x + e[4] * y + e[7] * z; this.z = e[2] * x + e[5] * y + e[8] * z; return this; } applyNormalMatrix(m) { return this.applyMatrix3(m).normalize(); } applyMatrix4(m) { const x = this.x, y = this.y, z = this.z; const e = m.elements; const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]); this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w; this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w; this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w; return this; } applyQuaternion(q) { const x = this.x, y = this.y, z = this.z; const qx = q.x, qy = q.y, qz = q.z, qw = q.w; // calculate quat * vector const ix = qw * x + qy * z - qz * y; const iy = qw * y + qz * x - qx * z; const iz = qw * z + qx * y - qy * x; const iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; return this; } // project( camera ) { // return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); // } // unproject( camera ) { // return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); // } transformDirection(m) { // input: THREE.Matrix4 affine matrix // vector interpreted as a direction const x = this.x, y = this.y, z = this.z; const e = m.elements; this.x = e[0] * x + e[4] * y + e[8] * z; this.y = e[1] * x + e[5] * y + e[9] * z; this.z = e[2] * x + e[6] * y + e[10] * z; return this.normalize(); } divide(v) { this.x /= v.x; this.y /= v.y; this.z /= v.z; return this; } divideScalar(scalar) { return this.multiplyScalar(1 / scalar); } min(v) { this.x = Math.min(this.x, v.x); this.y = Math.min(this.y, v.y); this.z = Math.min(this.z, v.z); return this; } max(v) { this.x = Math.max(this.x, v.x); this.y = Math.max(this.y, v.y); this.z = Math.max(this.z, v.z); return this; } clamp(min, max) { // assumes min < max, componentwise this.x = Math.max(min.x, Math.min(max.x, this.x)); this.y = Math.max(min.y, Math.min(max.y, this.y)); this.z = Math.max(min.z, Math.min(max.z, this.z)); return this; } clampScalar(minVal, maxVal) { this.x = Math.max(minVal, Math.min(maxVal, this.x)); this.y = Math.max(minVal, Math.min(maxVal, this.y)); this.z = Math.max(minVal, Math.min(maxVal, this.z)); return this; } clampLength(min, max) { const length = this.length(); return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length))); } floor() { this.x = Math.floor(this.x); this.y = Math.floor(this.y); this.z = Math.floor(this.z); return this; } ceil() { this.x = Math.ceil(this.x); this.y = Math.ceil(this.y); this.z = Math.ceil(this.z); return this; } round() { this.x = Math.round(this.x); this.y = Math.round(this.y); this.z = Math.round(this.z); return this; } roundToZero() { this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x); this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y); this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z); return this; } negate() { this.x = -this.x; this.y = -this.y; this.z = -this.z; return this; } dot(v) { return this.x * v.x + this.y * v.y + this.z * v.z; } // TODO lengthSquared? 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(length) { return this.normalize().multiplyScalar(length); } lerp(v, alpha) { this.x += (v.x - this.x) * alpha; this.y += (v.y - this.y) * alpha; this.z += (v.z - this.z) * alpha; return this; } lerpVectors(v1, v2, alpha) { this.x = v1.x + (v2.x - v1.x) * alpha; this.y = v1.y + (v2.y - v1.y) * alpha; this.z = v1.z + (v2.z - v1.z) * alpha; return this; } cross(v) { return this.crossVectors(this, v); } crossVectors(a, b) { const ax = a.x, ay = a.y, az = a.z; const bx = b.x, by = b.y, bz = b.z; this.x = ay * bz - az * by; this.y = az * bx - ax * bz; this.z = ax * by - ay * bx; return this; } projectOnVector(v) { const denominator = v.lengthSq(); if (denominator === 0) return this.set(0, 0, 0); const scalar = v.dot(this) / denominator; return this.copy(v).multiplyScalar(scalar); } projectOnPlane(planeNormal) { _vector$3.copy(this).projectOnVector(planeNormal); return this.sub(_vector$3); } reflect(normal) { // reflect incident vector off plane orthogonal to normal // normal is assumed to have unit length return this.sub(_vector$3.copy(normal).multiplyScalar(2 * this.dot(normal))); } angleTo(v) { const denominator = Math.sqrt(this.lengthSq() * v.lengthSq()); if (denominator === 0) return Math.PI / 2; const theta = this.dot(v) / denominator; // clamp, to handle numerical problems return Math.acos(clamp(theta, -1, 1)); } distanceTo(v) { return Math.sqrt(this.distanceToSquared(v)); } distanceToSquared(v) { const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; return dx * dx + dy * dy + dz * dz; } manhattanDistanceTo(v) { return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z); } setFromSpherical(s) { return this.setFromSphericalCoords(s.radius, s.phi, s.theta); } setFromSphericalCoords(radius, phi, theta) { const sinPhiRadius = Math.sin(phi) * radius; this.x = sinPhiRadius * Math.sin(theta); this.y = Math.cos(phi) * radius; this.z = sinPhiRadius * Math.cos(theta); return this; } setFromCylindrical(c) { return this.setFromCylindricalCoords(c.radius, c.theta, c.y); } setFromCylindricalCoords(radius, theta, y) { this.x = radius * Math.sin(theta); this.y = y; this.z = radius * Math.cos(theta); return this; } setFromMatrixPosition(m) { const e = m.elements; this.x = e[12]; this.y = e[13]; this.z = e[14]; return this; } setFromMatrixScale(m) { const sx = this.setFromMatrixColumn(m, 0).length(); const sy = this.setFromMatrixColumn(m, 1).length(); const sz = this.setFromMatrixColumn(m, 2).length(); this.x = sx; this.y = sy; this.z = sz; return this; } setFromMatrixColumn(m, index) { return this.fromArray(m.elements, index * 4); } setFromMatrix3Column(m, index) { return this.fromArray(m.elements, index * 3); } setFromEuler(e) { this.x = e._x; this.y = e._y; this.z = e._z; return this; } equals(v) { return v.x === this.x && v.y === this.y && v.z === this.z; } fromArray(array, offset = 0) { this.x = array[offset]; this.y = array[offset + 1]; this.z = array[offset + 2]; return this; } toArray(array = [], offset = 0) { array[offset] = this.x; array[offset + 1] = this.y; array[offset + 2] = this.z; return array; } // fromBufferAttribute( attribute, index ) { // this.x = attribute.getX( index ); // this.y = attribute.getY( index ); // this.z = attribute.getZ( index ); // return this; // } random() { this.x = Math.random(); this.y = Math.random(); this.z = Math.random(); return this; } randomDirection() { // Derived from https://mathworld.wolfram.com/SpherePointPicking.html const u = (Math.random() - 0.5) * 2; const t = Math.random() * Math.PI * 2; const f = Math.sqrt(1 - u ** 2); this.x = f * Math.cos(t); this.y = f * Math.sin(t); this.z = u; return this; } *[Symbol.iterator]() { yield this.x; yield this.y; yield this.z; } } const _vector$3 = /*@__PURE__*/new Vector3(); const _quaternion$1 = /*@__PURE__*/new Quaternion(); const _vector$2 = /*@__PURE__*/new Vector2(); class Box2 { constructor(min = new Vector2(+Infinity, +Infinity), max = new Vector2(-Infinity, -Infinity)) { this.isBox2 = true; this.min = min; this.max = max; } set(min, max) { this.min.copy(min); this.max.copy(max); return this; } setFromPoints(points) { this.makeEmpty(); for (let i = 0, il = points.length; i < il; i++) { this.expandByPoint(points[i]); } return this; } setFromCenterAndSize(center, size) { const halfSize = _vector$2.copy(size).multiplyScalar(0.5); this.min.copy(center).sub(halfSize); this.max.copy(center).add(halfSize); return this; } clone() { return new this.constructor().copy(this); } copy(box) { this.min.copy(box.min); this.max.copy(box.max); return this; } makeEmpty() { this.min.x = this.min.y = +Infinity; this.max.x = this.max.y = -Infinity; return this; } isEmpty() { // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes return this.max.x < this.min.x || this.max.y < this.min.y; } getCenter(target = new Vector2()) { return this.isEmpty() ? target.set(0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5); } getSize(target = new Vector2()) { return this.isEmpty() ? target.set(0, 0) : target.subVectors(this.max, this.min); } expandByPoint(point) { this.min.min(point); this.max.max(point); return this; } expandByVector(vector) { this.min.sub(vector); this.max.add(vector); return this; } expandByScalar(scalar) { this.min.addScalar(-scalar); this.max.addScalar(scalar); return this; } containsPoint(point) { return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y ? false : true; } containsBox(box) { return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y; } getParameter(point, target) { // This can potentially have a divide by zero if the box // has a size dimension of 0. return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y)); } intersectsBox(box) { // using 4 splitting planes to rule out intersections return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y ? false : true; } clampPoint(point, target) { return target.copy(point).clamp(this.min, this.max); } distanceToPoint(point) { const clampedPoint = _vector$2.copy(point).clamp(this.min, this.max); return clampedPoint.sub(point).length(); } intersect(box) { this.min.max(box.min); this.max.min(box.max); return this; } union(box) { this.min.min(box.min); this.max.max(box.max); return this; } translate(offset) { this.min.add(offset); this.max.add(offset); return this; } equals(box) { return box.min.equals(this.min) && box.max.equals(this.max); } } class Box3 { constructor(min = new Vector3(+Infinity, +Infinity, +Infinity), max = new Vector3(-Infinity, -Infinity, -Infinity)) { this.isBox3 = true; this.min = min; this.max = max; } set(min, max) { this.min.copy(min); this.max.copy(max); return this; } setFromArray(array) { let minX = +Infinity; let minY = +Infinity; let minZ = +Infinity; let maxX = -Infinity; let maxY = -Infinity; let maxZ = -Infinity; for (let i = 0, l = array.length; i < l; i += 3) { const x = array[i]; const y = array[i + 1]; const z = array[i + 2]; if (x < minX) minX = x; if (y < minY) minY = y; if (z < minZ) minZ = z; if (x > maxX) maxX = x; if (y > maxY) maxY = y; if (z > maxZ) maxZ = z; } this.min.set(minX, minY, minZ); this.max.set(maxX, maxY, maxZ); return this; } // setFromBufferAttribute( attribute ) { // let minX = + Infinity; // let minY = + Infinity; // let minZ = + Infinity; // let maxX = - Infinity; // let maxY = - Infinity; // let maxZ = - Infinity; // for ( let i = 0, l = attribute.count; i < l; i ++ ) { // const x = attribute.getX( i ); // const y = attribute.getY( i ); // const z = attribute.getZ( i ); // if ( x < minX ) minX = x; // if ( y < minY ) minY = y; // if ( z < minZ ) minZ = z; // if ( x > maxX ) maxX = x; // if ( y > maxY ) maxY = y; // if ( z > maxZ ) maxZ = z; // } // this.min.set( minX, minY, minZ ); // this.max.set( maxX, maxY, maxZ ); // return this; // } setFromPoints(points) { this.makeEmpty(); for (let i = 0, il = points.length; i < il; i++) { this.expandByPoint(points[i]); } return this; } setFromCenterAndSize(center, size) { const halfSize = _vector$1.copy(size).multiplyScalar(0.5); this.min.copy(center).sub(halfSize); this.max.copy(center).add(halfSize); return this; } setFromObject(object, precise = false) { this.makeEmpty(); return this.expandByObject(object, precise); } clone() { return new this.constructor().copy(this); } copy(box) { this.min.copy(box.min); this.max.copy(box.max); return this; } makeEmpty() { this.min.x = this.min.y = this.min.z = +Infinity; this.max.x = this.max.y = this.max.z = -Infinity; return this; } isEmpty() { // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z; } getCenter(target = new Vector3()) { return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5); } getSize(target = new Vector3()) { return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min); } expandByPoint(point) { this.min.min(point); this.max.max(point); return this; } expandByVector(vector) { this.min.sub(vector); this.max.add(vector); return this; } expandByScalar(scalar) { this.min.addScalar(-scalar); this.max.addScalar(scalar); return this; } // expandByObject( object, precise = false ) { // // Computes the world-axis-aligned bounding box of an object (including its children), // // accounting for both the object's, and children's, world transforms // object.updateWorldMatrix( false, false ); // const geometry = object.geometry; // if ( geometry !== undefined ) { // if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) { // const position = geometry.attributes.position; // for ( let i = 0, l = position.count; i < l; i ++ ) { // _vector.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); // this.expandByPoint( _vector ); // } // } else { // if ( geometry.boundingBox === null ) { // geometry.computeBoundingBox(); // } // _box.copy( geometry.boundingBox ); // _box.applyMatrix4( object.matrixWorld ); // this.union( _box ); // } // } // const children = object.children; // for ( let i = 0, l = children.length; i < l; i ++ ) { // this.expandByObject( children[ i ], precise ); // } // return this; // } containsPoint(point) { return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z ? false : true; } containsBox(box) { return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z; } getParameter(point, target) { // This can potentially have a divide by zero if the box // has a size dimension of 0. return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z)); } intersectsBox(box) { // using 6 splitting planes to rule out intersections. return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z ? false : true; } intersectsSphere(sphere) { // Find the point on the AABB closest to the sphere center. this.clampPoint(sphere.center, _vector$1); // If that point is inside the sphere, the AABB and sphere intersect. return _vector$1.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius; } intersectsPlane(plane) { // We compute the minimum and maximum dot product values. If those values // are on the same side (back or front) of the plane, then there is no intersection. let min, max; if (plane.normal.x > 0) { min = plane.normal.x * this.min.x; max = plane.normal.x * this.max.x; } else { min = plane.normal.x * this.max.x; max = plane.normal.x * this.min.x; } if (plane.normal.y > 0) { min += plane.normal.y * this.min.y; max += plane.normal.y * this.max.y; } else { min += plane.normal.y * this.max.y; max += plane.normal.y * this.min.y; } if (plane.normal.z > 0) { min += plane.normal.z * this.min.z; max += plane.normal.z * this.max.z; } else { min += plane.normal.z * this.max.z; max += plane.normal.z * this.min.z; } return min <= -plane.constant && max >= -plane.const